From e4373d32bfd2ca980bd6948e8570633a4f2a9ae9 Mon Sep 17 00:00:00 2001 From: Allofich <19624336+Allofich@users.noreply.github.com> Date: Wed, 25 Sep 2024 13:01:18 +0900 Subject: [PATCH] "Decouple CMS and OPL emulations" - dosbox-staging --- CHANGELOG | 1 + include/hardware.h | 5 +-- src/dosbox.cpp | 13 ++++++-- src/hardware/adlib.cpp | 1 - src/hardware/sblaster.cpp | 64 ++++++++++++++++++++++++++++----------- 5 files changed, 62 insertions(+), 22 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index a077ba92ff8..a34035b211d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -95,6 +95,7 @@ NEXT - remove few rendundant labels, adjust names of some others - retain 'show advanced options' state throughout session - SVN r4483: Fix compilation in Visual Studio 2008. (Allofich) + - DOSBox Staging: Decouple CMS and OPL emulations (Allofich) 2024.07.01 - Correct Hercules InColor memory emulation. Read and write planar diff --git a/include/hardware.h b/include/hardware.h index 40ca0d409f3..a3e43dd2721 100644 --- a/include/hardware.h +++ b/include/hardware.h @@ -22,7 +22,7 @@ class Section; enum OPL_Mode { - OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3,OPL_opl3gold,OPL_hardware,OPL_hardwareCMS,OPL_esfm + OPL_none,OPL_opl2,OPL_dualopl2,OPL_opl3,OPL_opl3gold,OPL_hardware,OPL_hardwareCMS,OPL_esfm }; #define CAPTURE_WAVE 0x01 #define CAPTURE_OPL 0x02 @@ -36,8 +36,9 @@ enum OPL_Mode { extern Bitu CaptureState; void OPL_Init(Section* sec,OPL_Mode oplmode); -void CMS_Init(Section* sec); void OPL_ShutDown(Section* sec); + +void CMS_Init(Section* sec); void CMS_ShutDown(Section* sec); bool SB_Get_Address(Bitu& sbaddr, Bitu& sbirq, Bitu& sbdma); diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 9b6bd4595a8..2804e71474c 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -1392,7 +1392,8 @@ void DOSBOX_SetupConfigSections(void) { const char *mt32reverbLevels[] = {"0", "1", "2", "3", "4", "5", "6", "7", nullptr}; const char* gustypes[] = { "classic", "classic37", "max", "interwave", nullptr }; const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "sb16vibra", "gb", "ess688", "ess1688", "reveal_sc400", "none", nullptr }; - const char* oplmodes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "opl3gold", "none", "hardware", "hardwaregb", "esfm", nullptr }; + const char* cms_settings[] = { "on", "off", "auto", nullptr }; + const char* oplmodes[] = { "auto", "opl2", "dualopl2", "opl3", "opl3gold", "none", "hardware", "hardwaregb", "esfm", nullptr }; const char* serials[] = { "dummy", "disabled", "modem", "nullmodem", "serialmouse", "directserial", "log", "file", nullptr }; const char* acpi_rsd_ptr_settings[] = { "auto", "bios", "ebda", nullptr }; const char* cpm_compat_modes[] = { "auto", "off", "msdos2", "msdos5", "direct", nullptr }; @@ -3669,10 +3670,18 @@ void DOSBOX_SetupConfigSections(void) { Pbool->Set_help("Allow the Sound Blaster mixer to modify the DOSBox-X mixer."); Pbool->SetBasic(true); + Pstring = secprop->Add_string("cms", Property::Changeable::WhenIdle, "auto"); + Pstring->Set_values(cms_settings); + Pstring->Set_help( + "Enable CMS emulation ('auto' by default).\n" + " off: Disable CMS emulation (except when the Game Blaster is selected).\n" + " on: Enable CMS emulation on Sound Blaster 1 and 2.\n" + " auto: Auto-enable CMS emulation for Sound Blaster 1 and Game Blaster."); + Pstring = secprop->Add_string("oplmode",Property::Changeable::WhenIdle,"auto"); Pstring->Set_values(oplmodes); Pstring->Set_help("Type of OPL emulation. On 'auto' the mode is determined by the 'sbtype' setting.\n" - "All OPL modes are AdLib-compatible, except for 'cms' (set 'sbtype=none' with 'cms' for a Game Blaster)."); + "All OPL modes are AdLib-compatible."); Pstring->SetBasic(true); Pbool = secprop->Add_bool("adlib force timer overflow on detect",Property::Changeable::WhenIdle,false); diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index 982d9f8d7e6..1385f041848 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -1544,7 +1544,6 @@ OPL_Mode Module::oplmode=OPL_none; std::string getoplmode() { if (Adlib::Module::oplmode == OPL_none) return "None"; - else if (Adlib::Module::oplmode == OPL_cms) return "CMS"; else if (Adlib::Module::oplmode == OPL_opl2) return "OPL2"; else if (Adlib::Module::oplmode == OPL_dualopl2) return "Dual OPL2"; else if (Adlib::Module::oplmode == OPL_opl3) return "OPL3"; diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 3ad62c6afe1..74e27733841 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -174,6 +174,7 @@ struct SB_INFO { bool busy_cycle_always; bool ess_playback_mode; bool no_filtering; + bool cms; uint8_t sc400_cfg; uint8_t time_constant; uint8_t sc400_dsp_major,sc400_dsp_minor; @@ -3718,7 +3719,7 @@ class SBLASTER: public Module_base { /* OPL/CMS Init */ const char * omode=config->Get_string("oplmode"); if (!strcasecmp(omode,"none")) opl_mode=OPL_none; - else if (!strcasecmp(omode,"cms")) opl_mode=OPL_cms; + else if (!strcasecmp(omode,"cms")); // Skip for backward compatibility with existing configurations else if (!strcasecmp(omode,"opl2")) opl_mode=OPL_opl2; else if (!strcasecmp(omode,"dualopl2")) opl_mode=OPL_dualopl2; else if (!strcasecmp(omode,"opl3")) opl_mode=OPL_opl3; @@ -3730,10 +3731,8 @@ class SBLASTER: public Module_base { else { switch (type) { case SBT_NONE: - opl_mode=OPL_none; - break; case SBT_GB: - opl_mode=OPL_cms; + opl_mode=OPL_none; break; case SBT_1: case SBT_2: @@ -3929,15 +3928,7 @@ class SBLASTER: public Module_base { if (!IS_PC98_ARCH) WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); break; - case OPL_cms: - assert(!IS_PC98_ARCH); - WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); - CMS_Init(section); - break; case OPL_opl2: - assert(!IS_PC98_ARCH); - CMS_Init(section); - // fall-through case OPL_dualopl2: assert(!IS_PC98_ARCH); // fall-through @@ -3962,6 +3953,47 @@ class SBLASTER: public Module_base { #endif break; } + + // Backward compatibility with existing configurations + if(section->Get_string("oplmode") == "cms") { + LOG(LOG_SB, LOG_WARN)("The 'cms' setting for 'oplmode' is deprecated; use 'cms = on' instead."); + sb.cms = true; + } + else { + const auto cms_str = section->Get_string("cms"); + if(cms_str == "on") { + sb.cms = true; + } + else if(cms_str == "auto") { + sb.cms = (sb.type == SBT_1 || sb.type == SBT_GB); + } + else + sb.cms = false; + } + + switch(sb.type) { + case SBT_1: // CMS is optional for Sound Blaster 1 and 2 + case SBT_2:; + case SBT_GB: + if(!sb.cms) { + LOG(LOG_SB, LOG_WARN)("'cms' setting is 'off', but is forced to 'auto' on the Game Blaster."); + auto* sect_updater = static_cast(control->GetSection("sblaster")); + sect_updater->Get_prop("cms")->SetValue("auto"); + } + sb.cms = true; // Game Blaster is CMS + default: + if(sb.cms) { + LOG(LOG_SB, LOG_WARN)("'cms' setting 'on' not supported on this card, forcing 'auto'."); + auto* sect_updater = static_cast(control->GetSection("sblaster")); + sect_updater->Get_prop("cms")->SetValue("auto"); + } + sb.cms = false; + } + + if(sb.cms) { + CMS_Init(section); + } + if (sb.type==SBT_NONE || sb.type==SBT_GB) return; sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB"); @@ -4227,12 +4259,7 @@ ASP> switch (oplmode) { case OPL_none: break; - case OPL_cms: - CMS_ShutDown(m_configuration); - break; case OPL_opl2: - CMS_ShutDown(m_configuration); - // fall-through case OPL_dualopl2: case OPL_opl3: case OPL_opl3gold: @@ -4242,6 +4269,9 @@ ASP> default: break; } + if(sb.cms) { + CMS_ShutDown(m_configuration); + } if (sb.type==SBT_NONE || sb.type==SBT_GB) return; DSP_Reset(); // Stop everything }