1
0
Fork 0

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
This commit is contained in:
ripsaw8080 2015-09-20 23:39:55 +00:00
parent 0c979d54a5
commit babb297c60
5 changed files with 86 additions and 3 deletions

View file

@ -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

View file

@ -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'.");

View file

@ -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 );

View file

@ -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;

View file

@ -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;
}