From babb297c600562cb3cb7da21d6fb2a00aa79f688 Mon Sep 17 00:00:00 2001 From: ripsaw8080 Date: Sun, 20 Sep 2015 23:39:55 +0000 Subject: [PATCH] Add opl3gold option to oplmode setting. With this option the AdLib Gold music can be selected in Dune. Only FM music without effects (reverb, stereo enhancement, surround sound, etc.) is supported; and FM volume control, used in the CD-ROM version of Dune, does work. Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3936 --- include/hardware.h | 2 +- src/dosbox.cpp | 2 +- src/hardware/adlib.cpp | 70 +++++++++++++++++++++++++++++++++++++++ src/hardware/adlib.h | 12 ++++++- src/hardware/sblaster.cpp | 3 ++ 5 files changed, 86 insertions(+), 3 deletions(-) diff --git a/include/hardware.h b/include/hardware.h index 5f5e4c74..26d3fde8 100644 --- a/include/hardware.h +++ b/include/hardware.h @@ -24,7 +24,7 @@ class Section; enum OPL_Mode { - OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3 + OPL_none,OPL_cms,OPL_opl2,OPL_dualopl2,OPL_opl3,OPL_opl3gold }; #define CAPTURE_WAVE 0x01 #define CAPTURE_OPL 0x02 diff --git a/src/dosbox.cpp b/src/dosbox.cpp index 83e6f434..1462fae3 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -537,7 +537,7 @@ void DOSBOX_Init(void) { Pbool = secprop->Add_bool("sbmixer",Property::Changeable::WhenIdle,true); Pbool->Set_help("Allow the soundblaster mixer to modify the DOSBox mixer."); - const char* oplmodes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "none", 0}; + const char* oplmodes[]={ "auto", "cms", "opl2", "dualopl2", "opl3", "opl3gold", "none", 0}; 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 sblaster type. All OPL modes are Adlib-compatible, except for 'cms'."); diff --git a/src/hardware/adlib.cpp b/src/hardware/adlib.cpp index 89e512bf..6c4b3983 100644 --- a/src/hardware/adlib.cpp +++ b/src/hardware/adlib.cpp @@ -440,6 +440,36 @@ void Module::DualWrite( Bit8u index, Bit8u reg, Bit8u val ) { CacheWrite( fullReg, val ); } +void Module::CtrlWrite( Bit8u val ) { + switch ( ctrl.index ) { + case 0x09: /* Left FM Volume */ + ctrl.lvol = val; + goto setvol; + case 0x0a: /* Right FM Volume */ + ctrl.rvol = val; +setvol: + if ( ctrl.mixer ) { + //Dune cdrom uses 32 volume steps in an apparent mistake, should be 128 + mixerChan->SetVolume( (float)(ctrl.lvol&0x1f)/31.0f, (float)(ctrl.rvol&0x1f)/31.0f ); + } + break; + } +} + +Bitu Module::CtrlRead( void ) { + switch ( ctrl.index ) { + case 0x00: /* Board Options */ + return 0x70; //No options installed + case 0x09: /* Left FM Volume */ + return ctrl.lvol; + case 0x0a: /* Right FM Volume */ + return ctrl.rvol; + case 0x15: /* Audio Relocation */ + return 0x388 >> 3; //Cryo installer detection + } + return 0xff; +} + void Module::PortWrite( Bitu port, Bitu val, Bitu iolen ) { //Keep track of last write time @@ -450,6 +480,14 @@ void Module::PortWrite( Bitu port, Bitu val, Bitu iolen ) { } if ( port&1 ) { switch ( mode ) { + case MODE_OPL3GOLD: + if ( port == 0x38b ) { + if ( ctrl.active ) { + CtrlWrite( val ); + break; + } + } + //Fall-through if not handled by control chip case MODE_OPL2: case MODE_OPL3: if ( !chip[0].Write( reg.normal, val ) ) { @@ -476,6 +514,20 @@ void Module::PortWrite( Bitu port, Bitu val, Bitu iolen ) { case MODE_OPL2: reg.normal = handler->WriteAddr( port, val ) & 0xff; break; + case MODE_OPL3GOLD: + if ( port == 0x38a ) { + if ( val == 0xff ) { + ctrl.active = true; + break; + } else if ( val == 0xfe ) { + ctrl.active = false; + break; + } else if ( ctrl.active ) { + ctrl.index = val & 0xff; + break; + } + } + //Fall-through if not handled by control chip case MODE_OPL3: reg.normal = handler->WriteAddr( port, val ) & 0x1ff; break; @@ -504,6 +556,15 @@ Bitu Module::PortRead( Bitu port, Bitu iolen ) { } else { return 0xff; } + case MODE_OPL3GOLD: + if ( ctrl.active ) { + if ( port == 0x38a ) { + return 0; //Control status, not busy + } else if ( port == 0x38b ) { + return CtrlRead(); + } + } + //Fall-through if not handled by control chip case MODE_OPL3: //We allocated 4 ports, so just return -1 for the higher ones if ( !(port & 3 ) ) { @@ -527,6 +588,7 @@ void Module::Init( Mode m ) { mode = m; switch ( mode ) { case MODE_OPL3: + case MODE_OPL3GOLD: case MODE_OPL2: break; case MODE_DUALOPL2: @@ -627,6 +689,10 @@ Module::Module( Section* configuration ) : Module_base(configuration) { reg.dual[0] = 0; reg.dual[1] = 0; reg.normal = 0; + ctrl.active = false; + ctrl.index = 0; + ctrl.lvol = 0xff; + ctrl.rvol = 0xff; handler = 0; capture = 0; @@ -637,6 +703,7 @@ Module::Module( Section* configuration ) : Module_base(configuration) { if ( rate < 8000 ) rate = 8000; std::string oplemu( section->Get_string( "oplemu" ) ); + ctrl.mixer = section->Get_bool("sbmixer"); mixerChan = mixerObject.Install(OPL_CallBack,rate,"FM"); mixerChan->SetScale( 2.0 ); @@ -664,6 +731,9 @@ Module::Module( Section* configuration ) : Module_base(configuration) { case OPL_opl3: Init( Adlib::MODE_OPL3 ); break; + case OPL_opl3gold: + Init( Adlib::MODE_OPL3GOLD ); + break; } //0x388 range WriteHandler[0].Install(0x388,OPL_Write,IO_MB, 4 ); diff --git a/src/hardware/adlib.h b/src/hardware/adlib.h index 681fd491..26114c2c 100644 --- a/src/hardware/adlib.h +++ b/src/hardware/adlib.h @@ -90,7 +90,8 @@ struct Chip { typedef enum { MODE_OPL2, MODE_DUALOPL2, - MODE_OPL3 + MODE_OPL3, + MODE_OPL3GOLD } Mode; class Handler { @@ -125,8 +126,17 @@ class Module: public Module_base { Bit32u normal; Bit8u dual[2]; } reg; + struct { + bool active; + Bit8u index; + Bit8u lvol; + Bit8u rvol; + bool mixer; + } ctrl; void CacheWrite( Bit32u reg, Bit8u val ); void DualWrite( Bit8u index, Bit8u reg, Bit8u val ); + void CtrlWrite( Bit8u val ); + Bitu CtrlRead( void ); public: static OPL_Mode oplmode; MixerChannel* mixerChan; diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index d72066bb..80376a67 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -1533,6 +1533,7 @@ private: 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; + else if (!strcasecmp(omode,"opl3gold")) opl_mode=OPL_opl3gold; /* Else assume auto */ else { switch (type) { @@ -1588,6 +1589,7 @@ public: // fall-through case OPL_dualopl2: case OPL_opl3: + case OPL_opl3gold: OPL_Init(section,oplmode); break; } @@ -1645,6 +1647,7 @@ public: // fall-through case OPL_dualopl2: case OPL_opl3: + case OPL_opl3gold: OPL_ShutDown(m_configuration); break; }