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
This commit is contained in:
parent
1d7e48c0dc
commit
bf5257415d
3 changed files with 75 additions and 33 deletions
|
@ -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);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "mem.h"
|
||||
#include "hardware.h"
|
||||
#include "setup.h"
|
||||
#include "support.h"
|
||||
#include "pic.h"
|
||||
#include <cstring>
|
||||
#include <math.h>
|
||||
|
@ -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<Section_prop *>(configuration);
|
||||
Bitu sample_rate_temp = section->Get_int("oplrate");
|
||||
sample_rate = static_cast<double>(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");
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue