From bf5257415d23dd5917ae4b9b1287cf4f420b5f93 Mon Sep 17 00:00:00 2001 From: Ralf Grillenberger Date: Wed, 6 Jan 2010 19:40:45 +0000 Subject: [PATCH] CMS/Gameblaster: add sbtype=gb, fix base addresses other than 220h, fix lack of sound when starting from autoexec, add autodetection (Thanks robertmo and Cloudschatze) Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3523 --- src/dosbox.cpp | 4 +- src/hardware/gameblaster.cpp | 85 ++++++++++++++++++++++++++---------- src/hardware/sblaster.cpp | 19 +++++--- 3 files changed, 75 insertions(+), 33 deletions(-) diff --git a/src/dosbox.cpp b/src/dosbox.cpp index c965186c..672f5546 100644 --- a/src/dosbox.cpp +++ b/src/dosbox.cpp @@ -480,10 +480,10 @@ void DOSBOX_Init(void) { secprop=control->AddSection_prop("sblaster",&SBLASTER_Init,true);//done - const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "none", 0 }; + const char* sbtypes[] = { "sb1", "sb2", "sbpro1", "sbpro2", "sb16", "gb", "none", 0 }; Pstring = secprop->Add_string("sbtype",Property::Changeable::WhenIdle,"sb16"); Pstring->Set_values(sbtypes); - Pstring->Set_help("Type of sblaster to emulate."); + Pstring->Set_help("Type of Soundblaster to emulate. gb is Gameblaster."); Phex = secprop->Add_hex("sbbase",Property::Changeable::WhenIdle,0x220); Phex->Set_values(ios); diff --git a/src/hardware/gameblaster.cpp b/src/hardware/gameblaster.cpp index 628d368b..8488eddc 100644 --- a/src/hardware/gameblaster.cpp +++ b/src/hardware/gameblaster.cpp @@ -22,6 +22,7 @@ #include "mem.h" #include "hardware.h" #include "setup.h" +#include "support.h" #include "pic.h" #include #include @@ -139,6 +140,7 @@ static Bit16s * cms_buf_point[4] = { cms_buffer[0][0],cms_buffer[0][1],cms_buffer[1][0],cms_buffer[1][1] }; static Bitu last_command; +static Bitu base_port; static void saa1099_envelope(int chip, int ch) @@ -286,6 +288,16 @@ static void saa1099_update(int chip, INT16 **buffer, int length) static void saa1099_write_port_w( int chip, int offset, int data ) { struct SAA1099 *saa = &saa1099[chip]; + if(offset == 1) { + // address port + saa->selected_reg = data & 0x1f; + if (saa->selected_reg == 0x18 || saa->selected_reg == 0x19) { + /* clock the envelope channels */ + if (saa->env_clock[0]) saa1099_envelope(chip,0); + if (saa->env_clock[1]) saa1099_envelope(chip,1); + } + return; + } int reg = saa->selected_reg; int ch; @@ -364,37 +376,26 @@ static void saa1099_write_port_w( int chip, int offset, int data ) } } - -static void write_cms(Bitu port,Bitu val,Bitu iolen) { - if (last_command + 1000 < PIC_Ticks) if(cms_chan) cms_chan->Enable(true); +static void write_cms(Bitu port, Bitu val, Bitu /* iolen */) { + if(cms_chan && (!cms_chan->enabled)) cms_chan->Enable(true); last_command = PIC_Ticks; - switch (port) { - case 0x0220: + switch (port-base_port) { + case 0: + saa1099_write_port_w(0,0,val); + break; + case 1: saa1099_write_port_w(0,1,val); break; - case 0x221: - saa1099[0].selected_reg = val & 0x1f; - if (saa1099[0].selected_reg == 0x18 || saa1099[0].selected_reg == 0x19) { - /* clock the envelope channels */ - if (saa1099[0].env_clock[0]) saa1099_envelope(0,0); - if (saa1099[0].env_clock[1]) saa1099_envelope(0,1); - } + case 2: + saa1099_write_port_w(1,0,val); break; - case 0x0222: + case 3: saa1099_write_port_w(1,1,val); break; - case 0x223: - saa1099[1].selected_reg = val & 0x1f; - if (saa1099[1].selected_reg == 0x18 || saa1099[1].selected_reg == 0x19) { - /* clock the envelope channels */ - if (saa1099[1].env_clock[0]) saa1099_envelope(1,0); - if (saa1099[1].env_clock[1]) saa1099_envelope(1,1); - } - break; } } - static void CMS_CallBack(Bitu len) { +static void CMS_CallBack(Bitu len) { if (len > CMS_BUFFER_SIZE) return; saa1099_update(0, &cms_buf_point[0], (int)len); @@ -421,10 +422,38 @@ static void write_cms(Bitu port,Bitu val,Bitu iolen) { if (last_command + 10000 < PIC_Ticks) if(cms_chan) cms_chan->Enable(false); } +// The Gameblaster detection +static Bit8u cms_detect_register = 0xff; + +static void write_cms_detect(Bitu port, Bitu val, Bitu /* iolen */) { + switch(port-base_port) { + case 0x6: + case 0x7: + cms_detect_register = val; + break; + } +} + +static Bitu read_cms_detect(Bitu port, Bitu /* iolen */) { + Bit8u retval = 0xff; + switch(port-base_port) { + case 0x4: + retval = 0x7f; + break; + case 0xa: + case 0xb: + retval = cms_detect_register; + break; + } + return retval; +} + class CMS:public Module_base { private: IO_WriteHandleObject WriteHandler; + IO_WriteHandleObject DetWriteHandler; + IO_ReadHandleObject DetReadHandler; MixerObject MixerChan; public: @@ -432,8 +461,16 @@ public: Section_prop * section = static_cast(configuration); Bitu sample_rate_temp = section->Get_int("oplrate"); sample_rate = static_cast(sample_rate_temp); - Bitu base = section->Get_hex("sbbase"); - WriteHandler.Install(base,write_cms,IO_MB,4); + base_port = section->Get_hex("sbbase"); + WriteHandler.Install(base_port, write_cms, IO_MB,4); + + // A standalone Gameblaster has a magic chip on it which is + // sometimes used for detection. + const char * sbtype=section->Get_string("sbtype"); + if (!strcasecmp(sbtype,"gb")) { + DetWriteHandler.Install(base_port+4,write_cms_detect,IO_MB,12); + DetReadHandler.Install(base_port,read_cms_detect,IO_MB,16); + } /* Register the Mixer CallBack */ cms_chan = MixerChan.Install(CMS_CallBack,sample_rate_temp,"CMS"); diff --git a/src/hardware/sblaster.cpp b/src/hardware/sblaster.cpp index 392a155c..f45ca282 100644 --- a/src/hardware/sblaster.cpp +++ b/src/hardware/sblaster.cpp @@ -63,7 +63,7 @@ bool MIDI_Available(void); #define SB_SH_MASK ((1 << SB_SH)-1) enum {DSP_S_RESET,DSP_S_RESET_WAIT,DSP_S_NORMAL,DSP_S_HIGHSPEED}; -enum SB_TYPES {SBT_NONE=0,SBT_1=1,SBT_PRO1=2,SBT_2=3,SBT_PRO2=4,SBT_16=6}; +enum SB_TYPES {SBT_NONE=0,SBT_1=1,SBT_PRO1=2,SBT_2=3,SBT_PRO2=4,SBT_16=6,SBT_GB=7}; enum SB_IRQS {SB_IRQ_8,SB_IRQ_16,SB_IRQ_MPU}; enum DSP_MODES { @@ -1478,6 +1478,7 @@ private: else if (!strcasecmp(sbtype,"sbpro1")) type=SBT_PRO1; else if (!strcasecmp(sbtype,"sbpro2")) type=SBT_PRO2; else if (!strcasecmp(sbtype,"sb16")) type=SBT_16; + else if (!strcasecmp(sbtype,"gb")) type=SBT_GB; else if (!strcasecmp(sbtype,"none")) type=SBT_NONE; else type=SBT_16; @@ -1495,7 +1496,9 @@ private: /* Else assume auto */ else { switch (type) { - case SBT_NONE:opl_mode=OPL_none;break; + case SBT_NONE: + case SBT_GB: + opl_mode=OPL_none;break; case SBT_1:opl_mode=OPL_opl2;break; case SBT_2:opl_mode=OPL_opl2;break; case SBT_PRO1:opl_mode=OPL_dualopl2;break; @@ -1524,23 +1527,25 @@ public: OPL_Mode opl_mode = OPL_none; Find_Type_And_Opl(section,sb.type,opl_mode); + bool do_cms = (sb.type==SBT_GB)? true:false; + switch (opl_mode) { case OPL_none: WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); break; case OPL_cms: WriteHandler[0].Install(0x388,adlib_gusforward,IO_MB); - CMS_Init(section); + do_cms = true; break; case OPL_opl2: - CMS_Init(section); + do_cms = true; case OPL_dualopl2: case OPL_opl3: OPL_Init(section,opl_mode); break; } - - if (sb.type==SBT_NONE) return; + if (do_cms) CMS_Init(section); + if (sb.type==SBT_NONE || sb.type==SBT_GB) return; sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB"); sb.dsp.state=DSP_S_NORMAL; @@ -1603,7 +1608,7 @@ public: break; } - if (sb.type==SBT_NONE) return; + if (sb.type==SBT_NONE || sb.type==SBT_GB) return; DSP_Reset();//Stop everything } }; //End of SBLASTER class