Merge branch 'svn/trunk' r4279
This commit is contained in:
commit
d68af8b650
3 changed files with 60 additions and 38 deletions
|
@ -24,7 +24,7 @@ enum DMAEvent {
|
|||
DMA_REACHED_TC,
|
||||
DMA_MASKED,
|
||||
DMA_UNMASKED,
|
||||
DMA_TRANSFEREND
|
||||
// DMA_TRANSFEREND, this shouldn't really be a ignal
|
||||
};
|
||||
|
||||
class DmaChannel;
|
||||
|
|
|
@ -308,7 +308,7 @@ again:
|
|||
currcnt=0xffff;
|
||||
masked=true;
|
||||
UpdateEMSMapping();
|
||||
DoCallBack(DMA_TRANSFEREND);
|
||||
DoCallBack(DMA_MASKED);
|
||||
}
|
||||
}
|
||||
return done;
|
||||
|
@ -340,7 +340,7 @@ again:
|
|||
currcnt=0xffff;
|
||||
masked=true;
|
||||
UpdateEMSMapping();
|
||||
DoCallBack(DMA_TRANSFEREND);
|
||||
DoCallBack(DMA_MASKED);
|
||||
}
|
||||
}
|
||||
return done;
|
||||
|
|
|
@ -90,7 +90,10 @@ struct SB_INFO {
|
|||
bool stereo,sign,autoinit;
|
||||
DMA_MODES mode;
|
||||
Bitu rate,mul;
|
||||
Bitu total,left,min;
|
||||
Bit32u singlesize; //size for single cycle transfers
|
||||
Bit32u autosize; //size for auto init transfers
|
||||
Bitu left; //Left in active cycle
|
||||
Bitu min;
|
||||
Bit64u start;
|
||||
union {
|
||||
Bit8u b8[DMA_BUFSIZE];
|
||||
|
@ -298,8 +301,6 @@ static void DSP_DMA_CallBack(DmaChannel * chan, DMAEvent event) {
|
|||
// DSP_ChangeMode(MODE_DMA_MASKED);
|
||||
LOG(LOG_SB,LOG_NORMAL)("DMA masked,stopping output, left %d",chan->currcnt);
|
||||
}
|
||||
} else if (event==DMA_TRANSFEREND) {
|
||||
if (sb.mode==MODE_DMA) sb.mode=MODE_DMA_MASKED;
|
||||
} else if (event==DMA_UNMASKED) {
|
||||
if (sb.mode==MODE_DMA_MASKED && sb.dma.mode!=DSP_DMA_NONE) {
|
||||
DSP_ChangeMode(MODE_DMA);
|
||||
|
@ -308,6 +309,9 @@ static void DSP_DMA_CallBack(DmaChannel * chan, DMAEvent event) {
|
|||
LOG(LOG_SB,LOG_NORMAL)("DMA unmasked,starting output, auto %d block %d",chan->autoinit,chan->basecnt);
|
||||
}
|
||||
}
|
||||
else {
|
||||
E_Exit("Unknown sblaster dma event");
|
||||
}
|
||||
}
|
||||
|
||||
#define MIN_ADAPTIVE_STEP_SIZE 0
|
||||
|
@ -414,6 +418,7 @@ static void GenerateDMASound(Bitu size) {
|
|||
Bitu read=0;Bitu done=0;Bitu i=0;
|
||||
last_dma_callback = PIC_FullIndex();
|
||||
|
||||
//Determine how much you should read
|
||||
if(sb.dma.autoinit) {
|
||||
if (sb.dma.left <= size)
|
||||
size = sb.dma.left;
|
||||
|
@ -422,6 +427,7 @@ static void GenerateDMASound(Bitu size) {
|
|||
size = sb.dma.left;
|
||||
}
|
||||
|
||||
//Read the actual data, process it and send it off to the mixer
|
||||
switch (sb.dma.mode) {
|
||||
case DSP_DMA_2:
|
||||
read=sb.dma.chan->Read(size,sb.dma.buf.b8);
|
||||
|
@ -523,6 +529,7 @@ static void GenerateDMASound(Bitu size) {
|
|||
sb.mode=MODE_NONE;
|
||||
return;
|
||||
}
|
||||
//Check how many bytes were actually read
|
||||
sb.dma.left-=read;
|
||||
if (!sb.dma.left) {
|
||||
PIC_RemoveEvents(END_DMA_Event);
|
||||
|
@ -530,24 +537,28 @@ static void GenerateDMASound(Bitu size) {
|
|||
SB_RaiseIRQ(SB_IRQ_16);
|
||||
else
|
||||
SB_RaiseIRQ(SB_IRQ_8);
|
||||
//Copy the new size
|
||||
sb.dma.left = sb.dma.total;
|
||||
|
||||
if (!sb.dma.autoinit) {
|
||||
if (!sb.dma.left) {
|
||||
//Not new single cycle transfer waiting?
|
||||
if (!sb.dma.singlesize) {
|
||||
LOG(LOG_SB, LOG_NORMAL)("Single cycle transfer ended");
|
||||
sb.mode = MODE_NONE;
|
||||
sb.dma.mode = DSP_DMA_NONE;
|
||||
}
|
||||
else {
|
||||
//Copied this value as the count for the final single cycle
|
||||
sb.dma.total = 0;
|
||||
//A single size transfer is still waiting, handle that now
|
||||
sb.dma.left = sb.dma.singlesize;
|
||||
sb.dma.singlesize = 0;
|
||||
LOG(LOG_SB, LOG_NORMAL)("Switch to Single cycle transfer begun");
|
||||
}
|
||||
} else {
|
||||
if (!sb.dma.left) {
|
||||
if (!sb.dma.autosize) {
|
||||
LOG(LOG_SB,LOG_NORMAL)("Auto-init transfer with 0 size");
|
||||
sb.mode=MODE_NONE;
|
||||
}
|
||||
//Continue with a new auto init transfer
|
||||
sb.dma.left = sb.dma.autosize;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -577,8 +588,9 @@ static void DMA_Silent_Event(Bitu val) {
|
|||
if (!sb.dma.left) {
|
||||
if (sb.dma.mode >= DSP_DMA_16) SB_RaiseIRQ(SB_IRQ_16);
|
||||
else SB_RaiseIRQ(SB_IRQ_8);
|
||||
//FIX, use the auto to single switch mechanics here as well or find a better way to silence
|
||||
if (sb.dma.autoinit)
|
||||
sb.dma.left=sb.dma.total;
|
||||
sb.dma.left=sb.dma.autosize;
|
||||
else {
|
||||
sb.mode=MODE_NONE;
|
||||
sb.dma.mode=DSP_DMA_NONE;
|
||||
|
@ -589,7 +601,6 @@ static void DMA_Silent_Event(Bitu val) {
|
|||
float delay=(bigger*1000.0f)/sb.dma.rate;
|
||||
PIC_AddEvent(DMA_Silent_Event,delay,bigger);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void END_DMA_Event(Bitu val) {
|
||||
|
@ -660,29 +671,20 @@ static void DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool autoinit, bool stere
|
|||
return;
|
||||
}
|
||||
|
||||
#if (C_DEBUG)
|
||||
LOG(LOG_SB, LOG_NORMAL)("DMA Transfer:%s %s %s freq %d rate %d size %d",
|
||||
type,
|
||||
stereo ? "Stereo" : "Mono",
|
||||
autoinit ? "Auto-Init" : "Single-Cycle",
|
||||
freq, sb.dma.rate, sb.dma.total
|
||||
);
|
||||
#endif
|
||||
//Going from an active autoinit into a single cycle
|
||||
if (sb.mode >= MODE_DMA && sb.dma.autoinit && !autoinit) {
|
||||
//Don't do anything, the total will flip over on the next transfer
|
||||
}
|
||||
//Just a normal single cycle transfer
|
||||
else if (!autoinit) {
|
||||
sb.dma.left = sb.dma.total;
|
||||
sb.dma.total = 0;
|
||||
sb.dma.left = sb.dma.singlesize;
|
||||
sb.dma.singlesize = 0;
|
||||
}
|
||||
//Going into an autoinit transfer
|
||||
else {
|
||||
//Transfer full cycle again
|
||||
sb.dma.left = sb.dma.total;
|
||||
sb.dma.left = sb.dma.autosize;
|
||||
}
|
||||
|
||||
sb.dma.autoinit = autoinit;
|
||||
sb.dma.mode = mode;
|
||||
sb.dma.stereo = stereo;
|
||||
|
@ -697,26 +699,36 @@ static void DSP_DoDMATransfer(DMA_MODES mode,Bitu freq,bool autoinit, bool stere
|
|||
//Set to be masked, the dma call can change this again.
|
||||
sb.mode = MODE_DMA_MASKED;
|
||||
sb.dma.chan->Register_Callback(DSP_DMA_CallBack);
|
||||
|
||||
#if (C_DEBUG)
|
||||
LOG(LOG_SB, LOG_NORMAL)("DMA Transfer:%s %s %s freq %d rate %d size %d",
|
||||
type,
|
||||
stereo ? "Stereo" : "Mono",
|
||||
autoinit ? "Auto-Init" : "Single-Cycle",
|
||||
freq, sb.dma.rate, sb.dma.left
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void DSP_PrepareDMA_Old(DMA_MODES mode,bool autoinit,bool sign) {
|
||||
sb.dma.sign=sign;
|
||||
if (!autoinit) sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
|
||||
if (!autoinit)
|
||||
sb.dma.singlesize=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
|
||||
sb.dma.chan=GetDMAChannel(sb.hw.dma8);
|
||||
DSP_DoDMATransfer(mode,sb.freq / (sb.mixer.stereo ? 2 : 1), autoinit, sb.mixer.stereo);
|
||||
}
|
||||
|
||||
static void DSP_PrepareDMA_New(DMA_MODES mode,Bitu length,bool autoinit,bool stereo) {
|
||||
Bitu freq=sb.freq;
|
||||
|
||||
//equal length if data format and dma channel are both 16-bit or 8-bit
|
||||
sb.dma.total=length;
|
||||
if (mode==DSP_DMA_16) {
|
||||
if (sb.hw.dma16!=0xff) {
|
||||
sb.dma.chan=GetDMAChannel(sb.hw.dma16);
|
||||
if (sb.dma.chan==NULL) {
|
||||
sb.dma.chan=GetDMAChannel(sb.hw.dma8);
|
||||
mode=DSP_DMA_16_ALIASED;
|
||||
sb.dma.total<<=1;
|
||||
length *= 2;
|
||||
}
|
||||
} else {
|
||||
sb.dma.chan=GetDMAChannel(sb.hw.dma8);
|
||||
|
@ -724,9 +736,16 @@ static void DSP_PrepareDMA_New(DMA_MODES mode,Bitu length,bool autoinit,bool ste
|
|||
//UNDOCUMENTED:
|
||||
//In aliased mode sample length is written to DSP as number of
|
||||
//16-bit samples so we need double 8-bit DMA buffer length
|
||||
sb.dma.total<<=1;
|
||||
length *= 2;
|
||||
}
|
||||
} else sb.dma.chan=GetDMAChannel(sb.hw.dma8);
|
||||
//Set the length to the correct register depending on mode
|
||||
if (autoinit) {
|
||||
sb.dma.autosize = length;
|
||||
}
|
||||
else {
|
||||
sb.dma.singlesize = length;
|
||||
}
|
||||
DSP_DoDMATransfer(mode,freq,autoinit,stereo);
|
||||
}
|
||||
|
||||
|
@ -762,7 +781,8 @@ static void DSP_Reset(void) {
|
|||
PIC_RemoveEvents(DSP_FinishReset);
|
||||
|
||||
sb.dma.left=0;
|
||||
sb.dma.total=0;
|
||||
sb.dma.singlesize=0;
|
||||
sb.dma.autosize = 0;
|
||||
sb.dma.stereo=false;
|
||||
sb.dma.sign=false;
|
||||
sb.dma.autoinit=false;
|
||||
|
@ -892,9 +912,10 @@ static void DSP_DoCommand(void) {
|
|||
}
|
||||
break;
|
||||
case 0x24: /* Singe Cycle 8-Bit DMA ADC */
|
||||
sb.dma.left=sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
|
||||
//Directly write to left?
|
||||
sb.dma.left = 1 + sb.dsp.in.data[0] + (sb.dsp.in.data[1] << 8);
|
||||
sb.dma.sign=false;
|
||||
LOG(LOG_SB,LOG_ERROR)("DSP:Faked ADC for %d bytes",sb.dma.total);
|
||||
LOG(LOG_SB,LOG_ERROR)("DSP:Faked ADC for %d bytes",sb.dma.left);
|
||||
GetDMAChannel(sb.hw.dma8)->Register_Callback(DSP_ADC_CallBack);
|
||||
break;
|
||||
case 0x14: /* Singe Cycle 8-Bit DMA DAC */
|
||||
|
@ -922,8 +943,7 @@ static void DSP_DoCommand(void) {
|
|||
break;
|
||||
case 0x48: /* Set DMA Block Size */
|
||||
DSP_SB2_ABOVE;
|
||||
//TODO Maybe check limit for new irq?
|
||||
sb.dma.total=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
|
||||
sb.dma.autosize=1+sb.dsp.in.data[0]+(sb.dsp.in.data[1] << 8);
|
||||
break;
|
||||
case 0x75: /* 075h : Single Cycle 4-bit ADPCM Reference */
|
||||
sb.adpcm.haveref=true;
|
||||
|
@ -967,6 +987,7 @@ static void DSP_DoCommand(void) {
|
|||
DSP_SB16_ONLY;
|
||||
case 0xd0: /* Halt 8-bit DMA */
|
||||
// DSP_ChangeMode(MODE_NONE);
|
||||
LOG(LOG_SB, LOG_NORMAL)("Halt DMA Command");
|
||||
// Games sometimes already program a new dma before stopping, gives noise
|
||||
if (sb.mode==MODE_NONE) {
|
||||
// possibly different code here that does not switch to MODE_DMA_PAUSE
|
||||
|
@ -989,6 +1010,7 @@ static void DSP_DoCommand(void) {
|
|||
case 0xd6: /* Continue DMA 16-bit */
|
||||
DSP_SB16_ONLY;
|
||||
case 0xd4: /* Continue DMA 8-bit*/
|
||||
LOG(LOG_SB, LOG_NORMAL)("Continue DMA command");
|
||||
if (sb.mode==MODE_DMA_PAUSE) {
|
||||
sb.mode=MODE_DMA_MASKED;
|
||||
if (sb.dma.chan!=NULL) sb.dma.chan->Register_Callback(DSP_DMA_CallBack);
|
||||
|
@ -998,10 +1020,8 @@ static void DSP_DoCommand(void) {
|
|||
DSP_SB16_ONLY;
|
||||
case 0xda: /* Exit Autoinitialize 8-bit */
|
||||
DSP_SB2_ABOVE;
|
||||
/* Set mode to single transfer so it ends with current block */
|
||||
LOG(LOG_SB, LOG_NORMAL)("Exit Autoinit command");
|
||||
sb.dma.autoinit=false; //Should stop itself
|
||||
sb.dma.total = 0; //This will cancel the switch to single cycle mode
|
||||
//Should really have some sb.dma.autoexit variable since we don't support continue autoinit dsp commands
|
||||
break;
|
||||
case 0xe0: /* DSP Identification - SB2.0+ */
|
||||
DSP_FlushData();
|
||||
|
@ -1052,10 +1072,12 @@ static void DSP_DoCommand(void) {
|
|||
case 0xf2: /* Trigger 8bit IRQ */
|
||||
//Small delay in order to emulate the slowness of the DSP, fixes Llamatron 2012 and Lemmings 3D
|
||||
PIC_AddEvent(&DSP_RaiseIRQEvent,0.01f);
|
||||
LOG(LOG_SB, LOG_NORMAL)("Trigger 8bit IRQ command");
|
||||
break;
|
||||
case 0xf3: /* Trigger 16bit IRQ */
|
||||
DSP_SB16_ONLY;
|
||||
SB_RaiseIRQ(SB_IRQ_16);
|
||||
LOG(LOG_SB, LOG_NORMAL)("Trigger 16bit IRQ command");
|
||||
break;
|
||||
case 0xf8: /* Undocumented, pre-SB16 only */
|
||||
DSP_FlushData();
|
||||
|
|
Loading…
Add table
Reference in a new issue