better sb dsp reset mechanism (hal), fixes stmik-based applications;
add sb irq acknowledge logic Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3416
This commit is contained in:
parent
fbfe0dbf3d
commit
f5fc904ff5
1 changed files with 63 additions and 31 deletions
|
@ -16,7 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
/* $Id: sblaster.cpp,v 1.73 2009-04-25 07:02:28 qbix79 Exp $ */
|
||||
/* $Id: sblaster.cpp,v 1.74 2009-06-06 15:45:31 c2woody Exp $ */
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
@ -62,7 +62,7 @@ bool MIDI_Available(void);
|
|||
#define SB_SH 14
|
||||
#define SB_SH_MASK ((1 << SB_SH)-1)
|
||||
|
||||
enum {DSP_S_RESET,DSP_S_NORMAL,DSP_S_HIGHSPEED};
|
||||
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_IRQS {SB_IRQ_8,SB_IRQ_16,SB_IRQ_MPU};
|
||||
|
||||
|
@ -117,6 +117,7 @@ struct SB_INFO {
|
|||
Bit8u cmd_in_pos;
|
||||
Bit8u cmd_in[DSP_BUFSIZE];
|
||||
struct {
|
||||
Bit8u lastval;
|
||||
Bit8u data[DSP_BUFSIZE];
|
||||
Bitu pos,used;
|
||||
} in,out;
|
||||
|
@ -145,7 +146,7 @@ struct SB_INFO {
|
|||
struct {
|
||||
Bitu base;
|
||||
Bitu irq;
|
||||
Bitu dma8,dma16;
|
||||
Bit8u dma8,dma16;
|
||||
} hw;
|
||||
struct {
|
||||
Bits value;
|
||||
|
@ -246,13 +247,22 @@ static void DSP_SetSpeaker(bool how) {
|
|||
|
||||
static INLINE void SB_RaiseIRQ(SB_IRQS type) {
|
||||
LOG(LOG_SB,LOG_NORMAL)("Raising IRQ");
|
||||
PIC_ActivateIRQ(sb.hw.irq);
|
||||
switch (type) {
|
||||
case SB_IRQ_8:
|
||||
if (sb.irq.pending_8bit) {
|
||||
E_Exit("SB: 8bit irq pending");
|
||||
return;
|
||||
}
|
||||
sb.irq.pending_8bit=true;
|
||||
PIC_ActivateIRQ(sb.hw.irq);
|
||||
break;
|
||||
case SB_IRQ_16:
|
||||
if (sb.irq.pending_16bit) {
|
||||
E_Exit("SB: 16bit irq pending");
|
||||
return;
|
||||
}
|
||||
sb.irq.pending_16bit=true;
|
||||
PIC_ActivateIRQ(sb.hw.irq);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -316,7 +326,7 @@ static INLINE Bit8u decode_ADPCM_4_sample(Bit8u sample,Bit8u & reference,Bits& s
|
|||
Bits ref = reference + scaleMap[samp];
|
||||
if (ref > 0xff) reference = 0xff;
|
||||
else if (ref < 0x00) reference = 0x00;
|
||||
else reference = ref;
|
||||
else reference = (Bit8u)(ref&0xff);
|
||||
scale = (scale + adjustMap[samp]) & 0xff;
|
||||
|
||||
return reference;
|
||||
|
@ -345,7 +355,7 @@ static INLINE Bit8u decode_ADPCM_2_sample(Bit8u sample,Bit8u & reference,Bits& s
|
|||
Bits ref = reference + scaleMap[samp];
|
||||
if (ref > 0xff) reference = 0xff;
|
||||
else if (ref < 0x00) reference = 0x00;
|
||||
else reference = ref;
|
||||
else reference = (Bit8u)(ref&0xff);
|
||||
scale = (scale + adjustMap[samp]) & 0xff;
|
||||
|
||||
return reference;
|
||||
|
@ -377,7 +387,7 @@ INLINE Bit8u decode_ADPCM_3_sample(Bit8u sample,Bit8u & reference,Bits& scale) {
|
|||
Bits ref = reference + scaleMap[samp];
|
||||
if (ref > 0xff) reference = 0xff;
|
||||
else if (ref < 0x00) reference = 0x00;
|
||||
else reference = ref;
|
||||
else reference = (Bit8u)(ref&0xff);
|
||||
scale = (scale + adjustMap[samp]) & 0xff;
|
||||
|
||||
return reference;
|
||||
|
@ -573,7 +583,7 @@ static void DSP_ChangeMode(DSP_MODES mode) {
|
|||
sb.mode=mode;
|
||||
}
|
||||
|
||||
static void DSP_RaiseIRQEvent(Bitu val) {
|
||||
static void DSP_RaiseIRQEvent(Bitu /*val*/) {
|
||||
SB_RaiseIRQ(SB_IRQ_8);
|
||||
}
|
||||
|
||||
|
@ -678,13 +688,23 @@ static void DSP_AddData(Bit8u val) {
|
|||
}
|
||||
|
||||
|
||||
static void DSP_FinishReset(Bitu /*val*/) {
|
||||
DSP_FlushData();
|
||||
DSP_AddData(0xaa);
|
||||
sb.dsp.state=DSP_S_NORMAL;
|
||||
}
|
||||
|
||||
static void DSP_Reset(void) {
|
||||
LOG(LOG_SB,LOG_ERROR)("DSP:Reset");
|
||||
PIC_DeActivateIRQ(sb.hw.irq);
|
||||
|
||||
DSP_ChangeMode(MODE_NONE);
|
||||
DSP_FlushData();
|
||||
sb.dsp.cmd_len=0;
|
||||
sb.dsp.in.pos=0;
|
||||
sb.dsp.write_busy=0;
|
||||
PIC_RemoveEvents(DSP_FinishReset);
|
||||
|
||||
sb.dma.left=0;
|
||||
sb.dma.total=0;
|
||||
sb.dma.stereo=false;
|
||||
|
@ -693,6 +713,7 @@ static void DSP_Reset(void) {
|
|||
sb.dma.mode=DSP_DMA_NONE;
|
||||
sb.dma.remain_size=0;
|
||||
if (sb.dma.chan) sb.dma.chan->Clear_Request();
|
||||
|
||||
sb.freq=22050;
|
||||
sb.time_constant=45;
|
||||
sb.dac.used=0;
|
||||
|
@ -706,29 +727,28 @@ static void DSP_Reset(void) {
|
|||
PIC_RemoveEvents(END_DMA_Event);
|
||||
}
|
||||
|
||||
|
||||
static void DSP_DoReset(Bit8u val) {
|
||||
if ((val&1)!=0) {
|
||||
if (((val&1)!=0) && (sb.dsp.state!=DSP_S_RESET)) {
|
||||
//TODO Get out of highspeed mode
|
||||
DSP_Reset();
|
||||
sb.dsp.state=DSP_S_RESET;
|
||||
} else {
|
||||
DSP_FlushData();
|
||||
DSP_AddData(0xaa);
|
||||
sb.dsp.state=DSP_S_NORMAL;
|
||||
} else if (((val&1)==0) && (sb.dsp.state==DSP_S_RESET)) { // reset off
|
||||
sb.dsp.state=DSP_S_RESET_WAIT;
|
||||
PIC_RemoveEvents(DSP_FinishReset);
|
||||
PIC_AddEvent(DSP_FinishReset,20.0f/1000.0f,0); // 20 microseconds
|
||||
}
|
||||
}
|
||||
|
||||
static void DSP_E2_DMA_CallBack(DmaChannel * chan, DMAEvent event) {
|
||||
static void DSP_E2_DMA_CallBack(DmaChannel * /*chan*/, DMAEvent event) {
|
||||
if (event==DMA_UNMASKED) {
|
||||
Bit8u val=sb.e2.value;
|
||||
Bit8u val=(Bit8u)(sb.e2.value&0xff);
|
||||
DmaChannel * chan=GetDMAChannel(sb.hw.dma8);
|
||||
chan->Register_Callback(0);
|
||||
chan->Write(1,&val);
|
||||
}
|
||||
}
|
||||
|
||||
static void DSP_ADC_CallBack(DmaChannel * chan, DMAEvent event) {
|
||||
static void DSP_ADC_CallBack(DmaChannel * /*chan*/, DMAEvent event) {
|
||||
if (event!=DMA_UNMASKED) return;
|
||||
Bit8u val=128;
|
||||
DmaChannel * ch=GetDMAChannel(sb.hw.dma8);
|
||||
|
@ -1047,14 +1067,13 @@ static void DSP_DoWrite(Bit8u val) {
|
|||
|
||||
static Bit8u DSP_ReadData(void) {
|
||||
/* Static so it repeats the last value on succesive reads (JANGLE DEMO) */
|
||||
static Bit8u data = 0;
|
||||
if (sb.dsp.out.used) {
|
||||
data=sb.dsp.out.data[sb.dsp.out.pos];
|
||||
sb.dsp.out.lastval=sb.dsp.out.data[sb.dsp.out.pos];
|
||||
sb.dsp.out.pos++;
|
||||
if (sb.dsp.out.pos>=DSP_BUFSIZE) sb.dsp.out.pos-=DSP_BUFSIZE;
|
||||
sb.dsp.out.used--;
|
||||
}
|
||||
return data;
|
||||
return sb.dsp.out.lastval;
|
||||
}
|
||||
|
||||
//The soundblaster manual says 2.0 Db steps but we'll go for a bit less
|
||||
|
@ -1337,7 +1356,7 @@ static Bit8u CTMIXER_Read(void) {
|
|||
}
|
||||
|
||||
|
||||
static Bitu read_sb(Bitu port,Bitu iolen) {
|
||||
static Bitu read_sb(Bitu port,Bitu /*iolen*/) {
|
||||
switch (port-sb.hw.base) {
|
||||
case MIXER_INDEX:
|
||||
return sb.mixer.index;
|
||||
|
@ -1360,6 +1379,7 @@ static Bitu read_sb(Bitu port,Bitu iolen) {
|
|||
if (sb.dsp.write_busy & 8) return 0xff;
|
||||
return 0x7f;
|
||||
case DSP_S_RESET:
|
||||
case DSP_S_RESET_WAIT:
|
||||
return 0xff;
|
||||
}
|
||||
return 0xff;
|
||||
|
@ -1372,19 +1392,20 @@ static Bitu read_sb(Bitu port,Bitu iolen) {
|
|||
return 0xff;
|
||||
}
|
||||
|
||||
static void write_sb(Bitu port,Bitu val,Bitu iolen) {
|
||||
static void write_sb(Bitu port,Bitu val,Bitu /*iolen*/) {
|
||||
Bit8u val8=(Bit8u)(val&0xff);
|
||||
switch (port-sb.hw.base) {
|
||||
case DSP_RESET:
|
||||
DSP_DoReset(val);
|
||||
DSP_DoReset(val8);
|
||||
break;
|
||||
case DSP_WRITE_DATA:
|
||||
DSP_DoWrite(val);
|
||||
DSP_DoWrite(val8);
|
||||
break;
|
||||
case MIXER_INDEX:
|
||||
sb.mixer.index=val;
|
||||
sb.mixer.index=val8;
|
||||
break;
|
||||
case MIXER_DATA:
|
||||
CTMIXER_Write(val);
|
||||
CTMIXER_Write(val8);
|
||||
break;
|
||||
default:
|
||||
LOG(LOG_SB,LOG_NORMAL)("Unhandled write to SB Port %4X",port);
|
||||
|
@ -1392,8 +1413,8 @@ static void write_sb(Bitu port,Bitu val,Bitu iolen) {
|
|||
}
|
||||
}
|
||||
|
||||
static void adlib_gusforward(Bitu port,Bitu val,Bitu iolen) {
|
||||
adlib_commandreg=val;
|
||||
static void adlib_gusforward(Bitu /*port*/,Bitu val,Bitu /*iolen*/) {
|
||||
adlib_commandreg=(Bit8u)(val&0xff);
|
||||
}
|
||||
|
||||
static void SBLASTER_CallBack(Bitu len) {
|
||||
|
@ -1469,10 +1490,16 @@ public:
|
|||
SBLASTER(Section* configuration):Module_base(configuration) {
|
||||
Bitu i;
|
||||
Section_prop * section=static_cast<Section_prop *>(configuration);
|
||||
|
||||
sb.hw.base=section->Get_hex("sbbase");
|
||||
sb.hw.irq=section->Get_int("irq");
|
||||
sb.hw.dma8=section->Get_int("dma");
|
||||
sb.hw.dma16=section->Get_int("hdma");
|
||||
Bitu dma8bit=section->Get_int("dma");
|
||||
if (dma8bit>0xff) dma8bit=0xff;
|
||||
sb.hw.dma8=(Bit8u)(dma8bit&0xff);
|
||||
Bitu dma16bit=section->Get_int("hdma");
|
||||
if (dma16bit>0xff) dma16bit=0xff;
|
||||
sb.hw.dma16=(Bit8u)(dma16bit&0xff);
|
||||
|
||||
sb.mixer.enabled=section->Get_bool("sbmixer");
|
||||
sb.mixer.stereo=false;
|
||||
OPL_Mode opl_mode = OPL_none;
|
||||
|
@ -1493,9 +1520,12 @@ public:
|
|||
OPL_Init(section,opl_mode);
|
||||
break;
|
||||
}
|
||||
|
||||
if (sb.type==SBT_NONE) return;
|
||||
|
||||
sb.chan=MixerChan.Install(&SBLASTER_CallBack,22050,"SB");
|
||||
sb.dsp.state=DSP_S_NORMAL;
|
||||
sb.dsp.out.lastval=0xaa;
|
||||
sb.dma.chan=NULL;
|
||||
|
||||
for (i=4;i<=0xf;i++) {
|
||||
|
@ -1508,8 +1538,10 @@ public:
|
|||
for (i=0;i<256;i++) ASP_regs[i] = 0;
|
||||
ASP_regs[5] = 0x01;
|
||||
ASP_regs[9] = 0xf8;
|
||||
|
||||
DSP_Reset();
|
||||
CTMIXER_Reset();
|
||||
|
||||
// The documentation does not specify if SB gets initialized with the speaker enabled
|
||||
// or disabled. Real SBPro2 has it disabled.
|
||||
sb.speaker=false;
|
||||
|
@ -1559,7 +1591,7 @@ public:
|
|||
|
||||
|
||||
static SBLASTER* test;
|
||||
void SBLASTER_ShutDown(Section* sec) {
|
||||
void SBLASTER_ShutDown(Section* /*sec*/) {
|
||||
delete test;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue