summaryrefslogtreecommitdiff
path: root/plugins/ao/eng_psf/peops2/spu2.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/ao/eng_psf/peops2/spu2.c')
-rw-r--r--plugins/ao/eng_psf/peops2/spu2.c559
1 files changed, 263 insertions, 296 deletions
diff --git a/plugins/ao/eng_psf/peops2/spu2.c b/plugins/ao/eng_psf/peops2/spu2.c
index 4ae14247..5b7ae050 100644
--- a/plugins/ao/eng_psf/peops2/spu2.c
+++ b/plugins/ao/eng_psf/peops2/spu2.c
@@ -99,6 +99,7 @@
#define _IN_SPU
+#include "../psx.h"
#include "../peops2/externals.h"
#include "../peops2/regs.h"
#include "../peops2/dma.h"
@@ -108,50 +109,6 @@
// globals
////////////////////////////////////////////////////////////////////////
-// psx buffer / addresses
-
-unsigned short regArea[32*1024];
-unsigned short spuMem[1*1024*1024];
-unsigned char * spuMemC;
-unsigned char * pSpuIrq[2];
-unsigned char * pSpuBuffer;
-
-// user settings
-
-int iUseXA=0;
-int iVolume=3;
-int iXAPitch=1;
-int iUseTimer=2;
-int iSPUIRQWait=1;
-int iDebugMode=0;
-int iRecordMode=0;
-int iUseReverb=1;
-int iUseInterpolation=2;
-
-// MAIN infos struct for each channel
-
-SPUCHAN s_chan[MAXCHAN+1]; // channel + 1 infos (1 is security for fmod handling)
-REVERBInfo rvb[2];
-
-unsigned long dwNoiseVal=1; // global noise generator
-
-unsigned short spuCtrl2[2]; // some vars to store psx reg infos
-unsigned short spuStat2[2];
-unsigned long spuIrq2[2];
-unsigned long spuAddr2[2]; // address into spu mem
-unsigned long spuRvbAddr2[2];
-unsigned long spuRvbAEnd2[2];
-int bEndThread=0; // thread handlers
-int bThreadEnded=0;
-int bSpuInit=0;
-int bSPUIsOpen=0;
-
-unsigned long dwNewChannel2[2]; // flags for faster testing, if new channel starts
-unsigned long dwEndChannel2[2];
-
-// UNUSED IN PS2 YET
-void (CALLBACK *irqCallback)(void)=0; // func of main emu, called on spu irq
-void (CALLBACK *cddavCallback)(unsigned short,unsigned short)=0;
// certain globals (were local before, but with the new timeproc I need em global)
@@ -160,14 +117,6 @@ const int f[5][2] = { { 0, 0 },
{ 115, -52 },
{ 98, -55 },
{ 122, -60 } };
-int SSumR[NSSIZE];
-int SSumL[NSSIZE];
-int iCycle=0;
-short * pS;
-
-static int lastch=-1; // last channel processed on spu irq in timer mode
-static int lastns=0; // last ns pos
-static int iSecureStart=0; // secure start counter
////////////////////////////////////////////////////////////////////////
// CODE AREA
@@ -221,69 +170,69 @@ static int iSecureStart=0; // secure start counter
//
-INLINE void InterpolateUp(int ch)
+INLINE void InterpolateUp(spu2_state_t *spu, int ch)
{
- if(s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass
+ if(spu->s_chan[ch].SB[32]==1) // flag == 1? calc step and set flag... and don't change the value in this pass
{
- const int id1=s_chan[ch].SB[30]-s_chan[ch].SB[29]; // curr delta to next val
- const int id2=s_chan[ch].SB[31]-s_chan[ch].SB[30]; // and next delta to next-next val :)
+ const int id1=spu->s_chan[ch].SB[30]-spu->s_chan[ch].SB[29]; // curr delta to next val
+ const int id2=spu->s_chan[ch].SB[31]-spu->s_chan[ch].SB[30]; // and next delta to next-next val :)
- s_chan[ch].SB[32]=0;
+ spu->s_chan[ch].SB[32]=0;
if(id1>0) // curr delta positive
{
if(id2<id1)
- {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
+ {spu->s_chan[ch].SB[28]=id1;spu->s_chan[ch].SB[32]=2;}
else
if(id2<(id1<<1))
- s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
+ spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x10000L;
else
- s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
+ spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x20000L;
}
else // curr delta negative
{
if(id2>id1)
- {s_chan[ch].SB[28]=id1;s_chan[ch].SB[32]=2;}
+ {spu->s_chan[ch].SB[28]=id1;spu->s_chan[ch].SB[32]=2;}
else
if(id2>(id1<<1))
- s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x10000L;
+ spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x10000L;
else
- s_chan[ch].SB[28]=(id1*s_chan[ch].sinc)/0x20000L;
+ spu->s_chan[ch].SB[28]=(id1*spu->s_chan[ch].sinc)/0x20000L;
}
}
else
- if(s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass
+ if(spu->s_chan[ch].SB[32]==2) // flag 1: calc step and set flag... and don't change the value in this pass
{
- s_chan[ch].SB[32]=0;
+ spu->s_chan[ch].SB[32]=0;
- s_chan[ch].SB[28]=(s_chan[ch].SB[28]*s_chan[ch].sinc)/0x20000L;
- if(s_chan[ch].sinc<=0x8000)
- s_chan[ch].SB[29]=s_chan[ch].SB[30]-(s_chan[ch].SB[28]*((0x10000/s_chan[ch].sinc)-1));
- else s_chan[ch].SB[29]+=s_chan[ch].SB[28];
+ spu->s_chan[ch].SB[28]=(spu->s_chan[ch].SB[28]*spu->s_chan[ch].sinc)/0x20000L;
+ if(spu->s_chan[ch].sinc<=0x8000)
+ spu->s_chan[ch].SB[29]=spu->s_chan[ch].SB[30]-(spu->s_chan[ch].SB[28]*((0x10000/spu->s_chan[ch].sinc)-1));
+ else spu->s_chan[ch].SB[29]+=spu->s_chan[ch].SB[28];
}
else // no flags? add bigger val (if possible), calc smaller step, set flag1
- s_chan[ch].SB[29]+=s_chan[ch].SB[28];
+ spu->s_chan[ch].SB[29]+=spu->s_chan[ch].SB[28];
}
//
// even easier interpolation on downsampling, also no special filter, again just "Pete's common sense" tm
//
-INLINE void InterpolateDown(int ch)
+INLINE void InterpolateDown(spu2_state_t *spu, int ch)
{
- if(s_chan[ch].sinc>=0x20000L) // we would skip at least one val?
+ if(spu->s_chan[ch].sinc>=0x20000L) // we would skip at least one val?
{
- s_chan[ch].SB[29]+=(s_chan[ch].SB[30]-s_chan[ch].SB[29])/2; // add easy weight
- if(s_chan[ch].sinc>=0x30000L) // we would skip even more vals?
- s_chan[ch].SB[29]+=(s_chan[ch].SB[31]-s_chan[ch].SB[30])/2;// add additional next weight
+ spu->s_chan[ch].SB[29]+=(spu->s_chan[ch].SB[30]-spu->s_chan[ch].SB[29])/2; // add easy weight
+ if(spu->s_chan[ch].sinc>=0x30000L) // we would skip even more vals?
+ spu->s_chan[ch].SB[29]+=(spu->s_chan[ch].SB[31]-spu->s_chan[ch].SB[30])/2;// add additional next weight
}
}
////////////////////////////////////////////////////////////////////////
// helpers for gauss interpolation
-#define gval0 (((short*)(&s_chan[ch].SB[29]))[gpos])
-#define gval(x) (((short*)(&s_chan[ch].SB[29]))[(gpos+x)&3])
+#define gval0 (((short*)(&spu->s_chan[ch].SB[29]))[gpos])
+#define gval(x) (((short*)(&spu->s_chan[ch].SB[29]))[(gpos+x)&3])
#include "gauss_i.h"
@@ -295,30 +244,30 @@ INLINE void InterpolateDown(int ch)
// START SOUND... called by main thread to setup a new sound on a channel
////////////////////////////////////////////////////////////////////////
-INLINE void StartSound(int ch)
+INLINE void StartSound(spu2_state_t *spu, int ch)
{
- dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit
- dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit
+ spu->dwNewChannel2[ch/24]&=~(1<<(ch%24)); // clear new channel bit
+ spu->dwEndChannel2[ch/24]&=~(1<<(ch%24)); // clear end channel bit
- StartADSR(ch);
- StartREVERB(ch);
+ StartADSR(spu, ch);
+ StartREVERB(spu, ch);
- s_chan[ch].pCurr=s_chan[ch].pStart; // set sample start
+ spu->s_chan[ch].pCurr=spu->s_chan[ch].pStart; // set sample start
- s_chan[ch].s_1=0; // init mixing vars
- s_chan[ch].s_2=0;
- s_chan[ch].iSBPos=28;
+ spu->s_chan[ch].s_1=0; // init mixing vars
+ spu->s_chan[ch].s_2=0;
+ spu->s_chan[ch].iSBPos=28;
- s_chan[ch].bNew=0; // init channel flags
- s_chan[ch].bStop=0;
- s_chan[ch].bOn=1;
+ spu->s_chan[ch].bNew=0; // init channel flags
+ spu->s_chan[ch].bStop=0;
+ spu->s_chan[ch].bOn=1;
- s_chan[ch].SB[29]=0; // init our interpolation helpers
- s_chan[ch].SB[30]=0;
+ spu->s_chan[ch].SB[29]=0; // init our interpolation helpers
+ spu->s_chan[ch].SB[30]=0;
- if(iUseInterpolation>=2) // gauss interpolation?
- {s_chan[ch].spos=0x30000L;s_chan[ch].SB[28]=0;} // -> start with more decoding
- else {s_chan[ch].spos=0x10000L;s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding
+ if(spu->iUseInterpolation>=2) // gauss interpolation?
+ {spu->s_chan[ch].spos=0x30000L;spu->s_chan[ch].SB[28]=0;} // -> start with more decoding
+ else {spu->s_chan[ch].spos=0x10000L;spu->s_chan[ch].SB[31]=0;} // -> no/simple interpolation starts with one 44100 decoding
}
////////////////////////////////////////////////////////////////////////
@@ -327,24 +276,20 @@ INLINE void StartSound(int ch)
// basically the whole sound processing is done in this fat func!
////////////////////////////////////////////////////////////////////////
-static u32 sampcount;
-static u32 decaybegin;
-static u32 decayend;
-
// Counting to 65536 results in full volume offage.
-void setlength2(s32 stop, s32 fade)
+void setlength2(spu2_state_t *spu, s32 stop, s32 fade)
{
if(stop==~0)
{
- decaybegin=~0;
+ spu->decaybegin=~0;
}
else
{
stop=(stop*441)/10;
fade=(fade*441)/10;
- decaybegin=stop;
- decayend=stop+fade;
+ spu->decaybegin=stop;
+ spu->decayend=stop+fade;
}
}
// 5 ms waiting phase, if buffer is full and no new sound has to get started
@@ -356,11 +301,10 @@ void setlength2(s32 stop, s32 fade)
////////////////////////////////////////////////////////////////////////
-int iSpuAsyncWait=0;
-
static void *MAINThread(mips_cpu_context *cpu, int samp2run)
{
- int s_1,s_2,fa,voldiv=iVolume;
+ spu2_state_t *spu = cpu->spu2;
+ int s_1,s_2,fa,voldiv=spu->iVolume;
unsigned char * start;unsigned int nSample;
int ch,predict_nr,shift_factor,flags,d,d2,s;
int gpos,bIRQReturn=0;
@@ -375,12 +319,12 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
// until enuff free place is available/a new channel gets
// started
- if(dwNewChannel2[0] || dwNewChannel2[1]) // new channel should start immedately?
+ if(spu->dwNewChannel2[0] || spu->dwNewChannel2[1]) // new channel should start immedately?
{ // (at least one bit 0 ... MAXCHANNEL is set?)
- iSecureStart++; // -> set iSecure
- if(iSecureStart>5) iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance)
+ spu->iSecureStart++; // -> set iSecure
+ if(spu->iSecureStart>5) spu->iSecureStart=0; // (if it is set 5 times - that means on 5 tries a new samples has been started - in a row, we will reset it, to give the sound update a chance)
}
- else iSecureStart=0; // 0: no new channel should start
+ else spu->iSecureStart=0; // 0: no new channel should start
/* if (!iSecureStart)
{
@@ -403,9 +347,9 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
//--------------------------------------------------// continue from irq handling in timer mode?
- if(lastch>=0) // will be -1 if no continue is pending
+ if(spu->lastch>=0) // will be -1 if no continue is pending
{
- ch=lastch; lastch=-1; // -> setup all kind of vars to continue
+ ch=spu->lastch; spu->lastch=-1; // -> setup all kind of vars to continue
goto GOON; // -> directly jump to the continue point
}
@@ -415,39 +359,39 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
{
for(ch=0;ch<MAXCHAN;ch++) // loop em all... we will collect 1 ms of sound of each playing channel
{
- if(s_chan[ch].bNew) StartSound(ch); // start new sound
- if(!s_chan[ch].bOn) continue; // channel not playing? next
+ if(spu->s_chan[ch].bNew) StartSound(spu, ch); // start new sound
+ if(!spu->s_chan[ch].bOn) continue; // channel not playing? next
- if(s_chan[ch].iActFreq!=s_chan[ch].iUsedFreq) // new psx frequency?
+ if(spu->s_chan[ch].iActFreq!=spu->s_chan[ch].iUsedFreq) // new psx frequency?
{
- s_chan[ch].iUsedFreq=s_chan[ch].iActFreq; // -> take it and calc steps
- s_chan[ch].sinc=s_chan[ch].iRawPitch<<4;
- if(!s_chan[ch].sinc) s_chan[ch].sinc=1;
- if(iUseInterpolation==1) s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag
+ spu->s_chan[ch].iUsedFreq=spu->s_chan[ch].iActFreq; // -> take it and calc steps
+ spu->s_chan[ch].sinc=spu->s_chan[ch].iRawPitch<<4;
+ if(!spu->s_chan[ch].sinc) spu->s_chan[ch].sinc=1;
+ if(spu->iUseInterpolation==1) spu->s_chan[ch].SB[32]=1; // -> freq change in simle imterpolation mode: set flag
}
// ns=0;
// while(ns<NSSIZE) // loop until 1 ms of data is reached
{
- while(s_chan[ch].spos>=0x10000L)
+ while(spu->s_chan[ch].spos>=0x10000L)
{
- if(s_chan[ch].iSBPos==28) // 28 reached?
+ if(spu->s_chan[ch].iSBPos==28) // 28 reached?
{
- start=s_chan[ch].pCurr; // set up the current pos
+ start=spu->s_chan[ch].pCurr; // set up the current pos
if (start == (unsigned char*)-1) // special "stop" sign
{
- s_chan[ch].bOn=0; // -> turn everything off
- s_chan[ch].ADSRX.lVolume=0;
- s_chan[ch].ADSRX.EnvelopeVol=0;
+ spu->s_chan[ch].bOn=0; // -> turn everything off
+ spu->s_chan[ch].ADSRX.lVolume=0;
+ spu->s_chan[ch].ADSRX.EnvelopeVol=0;
goto ENDX; // -> and done for this channel
}
- s_chan[ch].iSBPos=0;
+ spu->s_chan[ch].iSBPos=0;
//////////////////////////////////////////// spu irq handler here? mmm... do it later
- s_1=s_chan[ch].s_1;
- s_2=s_chan[ch].s_2;
+ s_1=spu->s_chan[ch].s_1;
+ s_2=spu->s_chan[ch].s_2;
predict_nr=(int)*start;start++;
shift_factor=predict_nr&0xf;
@@ -467,38 +411,38 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
s_2=s_1;s_1=fa;
s=((d & 0xf0) << 8);
- s_chan[ch].SB[nSample++]=fa;
+ spu->s_chan[ch].SB[nSample++]=fa;
if(s&0x8000) s|=0xffff0000;
fa=(s>>shift_factor);
fa=fa + ((s_1 * f[predict_nr][0])>>6) + ((s_2 * f[predict_nr][1])>>6);
s_2=s_1;s_1=fa;
- s_chan[ch].SB[nSample++]=fa;
+ spu->s_chan[ch].SB[nSample++]=fa;
}
//////////////////////////////////////////// irq check
- if(spuCtrl2[ch/24]&0x40) // some irq active?
+ if(spu->spuCtrl2[ch/24]&0x40) // some irq active?
{
- if((pSpuIrq[ch/24] > start-16 && // irq address reached?
- pSpuIrq[ch/24] <= start) ||
+ if((spu->pSpuIrq[ch/24] > start-16 && // irq address reached?
+ spu->pSpuIrq[ch/24] <= start) ||
((flags&1) && // special: irq on looping addr, when stop/loop flag is set
- (pSpuIrq[ch/24] > s_chan[ch].pLoop-16 &&
- pSpuIrq[ch/24] <= s_chan[ch].pLoop)))
+ (spu->pSpuIrq[ch/24] > spu->s_chan[ch].pLoop-16 &&
+ spu->pSpuIrq[ch/24] <= spu->s_chan[ch].pLoop)))
{
- s_chan[ch].iIrqDone=1; // -> debug flag
+ spu->s_chan[ch].iIrqDone=1; // -> debug flag
- if(irqCallback) irqCallback(); // -> call main emu (not supported in SPU2 right now)
+ if(spu->irqCallback) spu->irqCallback(); // -> call main emu (not supported in SPU2 right now)
else
{
- if(ch<24) InterruptDMA4(); // -> let's see what is happening if we call our irqs instead ;)
- else InterruptDMA7();
+ if(ch<24) InterruptDMA4(cpu); // -> let's see what is happening if we call our irqs instead ;)
+ else InterruptDMA7(cpu);
}
- if(iSPUIRQWait) // -> option: wait after irq for main emu
+ if(spu->iSPUIRQWait) // -> option: wait after irq for main emu
{
- iSpuAsyncWait=1;
+ spu->iSpuAsyncWait=1;
bIRQReturn=1;
}
}
@@ -506,29 +450,29 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
//////////////////////////////////////////// flag handler
- if((flags&4) && (!s_chan[ch].bIgnoreLoop))
- s_chan[ch].pLoop=start-16; // loop adress
+ if((flags&4) && (!spu->s_chan[ch].bIgnoreLoop))
+ spu->s_chan[ch].pLoop=start-16; // loop adress
if(flags&1) // 1: stop/loop
{
- dwEndChannel2[ch/24]|=(1<<(ch%24));
+ spu->dwEndChannel2[ch/24]|=(1<<(ch%24));
// We play this block out first...
- //if(!(flags&2)|| s_chan[ch].pLoop==NULL)
+ //if(!(flags&2)|| spu->s_chan[ch].pLoop==NULL)
// 1+2: do loop... otherwise: stop
- if(flags!=3 || s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
+ if(flags!=3 || spu->s_chan[ch].pLoop==NULL) // PETE: if we don't check exactly for 3, loop hang ups will happen (DQ4, for example)
{ // and checking if pLoop is set avoids crashes, yeah
start = (unsigned char*)-1;
}
else
{
- start = s_chan[ch].pLoop;
+ start = spu->s_chan[ch].pLoop;
}
}
- s_chan[ch].pCurr=start; // store values for next cycle
- s_chan[ch].s_1=s_1;
- s_chan[ch].s_2=s_2;
+ spu->s_chan[ch].pCurr=start; // store values for next cycle
+ spu->s_chan[ch].s_1=s_1;
+ spu->s_chan[ch].s_2=s_2;
////////////////////////////////////////////
@@ -536,7 +480,7 @@ static void *MAINThread(mips_cpu_context *cpu, int samp2run)
{
bIRQReturn=0;
{
- lastch=ch;
+ spu->lastch=ch;
// lastns=ns; // changemeback
return 0;
@@ -549,34 +493,34 @@ GOON: ;
}
- fa=s_chan[ch].SB[s_chan[ch].iSBPos++]; // get sample data
+ fa=spu->s_chan[ch].SB[spu->s_chan[ch].iSBPos++]; // get sample data
-// if((spuCtrl2[ch/24]&0x4000)==0) fa=0; // muted?
+// if((spu->spuCtrl2[ch/24]&0x4000)==0) fa=0; // muted?
// else // else adjust
{
if(fa>32767L) fa=32767L;
if(fa<-32767L) fa=-32767L;
}
- if(iUseInterpolation>=2) // gauss/cubic interpolation
+ if(spu->iUseInterpolation>=2) // gauss/cubic interpolation
{
- gpos = s_chan[ch].SB[28];
+ gpos = spu->s_chan[ch].SB[28];
gval0 = fa;
gpos = (gpos+1) & 3;
- s_chan[ch].SB[28] = gpos;
+ spu->s_chan[ch].SB[28] = gpos;
}
else
- if(iUseInterpolation==1) // simple interpolation
+ if(spu->iUseInterpolation==1) // simple interpolation
{
- s_chan[ch].SB[28] = 0;
- s_chan[ch].SB[29] = s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour'
- s_chan[ch].SB[30] = s_chan[ch].SB[31];
- s_chan[ch].SB[31] = fa;
- s_chan[ch].SB[32] = 1; // -> flag: calc new interolation
+ spu->s_chan[ch].SB[28] = 0;
+ spu->s_chan[ch].SB[29] = spu->s_chan[ch].SB[30]; // -> helpers for simple linear interpolation: delay real val for two slots, and calc the two deltas, for a 'look at the future behaviour'
+ spu->s_chan[ch].SB[30] = spu->s_chan[ch].SB[31];
+ spu->s_chan[ch].SB[31] = fa;
+ spu->s_chan[ch].SB[32] = 1; // -> flag: calc new interolation
}
- else s_chan[ch].SB[29]=fa; // no interpolation
+ else spu->s_chan[ch].SB[29]=fa; // no interpolation
- s_chan[ch].spos -= 0x10000L;
+ spu->s_chan[ch].spos -= 0x10000L;
}
////////////////////////////////////////////////
@@ -584,32 +528,32 @@ GOON: ;
// surely wrong... and no noise frequency (spuCtrl&0x3f00) will be used...
// and sometimes the noise will be used as fmod modulation... pfff
- if(s_chan[ch].bNoise)
+ if(spu->s_chan[ch].bNoise)
{
- if((dwNoiseVal<<=1)&0x80000000L)
+ if((spu->dwNoiseVal<<=1)&0x80000000L)
{
- dwNoiseVal^=0x0040001L;
- fa=((dwNoiseVal>>2)&0x7fff);
+ spu->dwNoiseVal^=0x0040001L;
+ fa=((spu->dwNoiseVal>>2)&0x7fff);
fa=-fa;
}
- else fa=(dwNoiseVal>>2)&0x7fff;
+ else fa=(spu->dwNoiseVal>>2)&0x7fff;
// mmm... depending on the noise freq we allow bigger/smaller changes to the previous val
- fa=s_chan[ch].iOldNoise+((fa-s_chan[ch].iOldNoise)/((0x001f-((spuCtrl2[ch/24]&0x3f00)>>9))+1));
+ fa=spu->s_chan[ch].iOldNoise+((fa-spu->s_chan[ch].iOldNoise)/((0x001f-((spu->spuCtrl2[ch/24]&0x3f00)>>9))+1));
if(fa>32767L) fa=32767L;
if(fa<-32767L) fa=-32767L;
- s_chan[ch].iOldNoise=fa;
+ spu->s_chan[ch].iOldNoise=fa;
- if(iUseInterpolation<2) // no gauss/cubic interpolation?
- s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot
+ if(spu->iUseInterpolation<2) // no gauss/cubic interpolation?
+ spu->s_chan[ch].SB[29] = fa; // -> store noise val in "current sample" slot
} //----------------------------------------
else // NO NOISE (NORMAL SAMPLE DATA) HERE
{//------------------------------------------//
- if(iUseInterpolation==3) // cubic interpolation
+ if(spu->iUseInterpolation==3) // cubic interpolation
{
long xd;
- xd = ((s_chan[ch].spos) >> 1)+1;
- gpos = s_chan[ch].SB[28];
+ xd = ((spu->s_chan[ch].spos) >> 1)+1;
+ gpos = spu->s_chan[ch].SB[28];
fa = gval(3) - 3*gval(2) + 3*gval(1) - gval0;
fa *= (xd - (2<<15)) / 6;
@@ -624,11 +568,11 @@ GOON: ;
}
//------------------------------------------//
else
- if(iUseInterpolation==2) // gauss interpolation
+ if(spu->iUseInterpolation==2) // gauss interpolation
{
int vl, vr;
- vl = (s_chan[ch].spos >> 6) & ~3;
- gpos = s_chan[ch].SB[28];
+ vl = (spu->s_chan[ch].spos >> 6) & ~3;
+ gpos = spu->s_chan[ch].SB[28];
vr=(gauss[vl]*gval0)&~2047;
vr+=(gauss[vl+1]*gval(1))&~2047;
vr+=(gauss[vl+2]*gval(2))&~2047;
@@ -644,25 +588,25 @@ GOON: ;
}
//------------------------------------------//
else
- if(iUseInterpolation==1) // simple interpolation
+ if(spu->iUseInterpolation==1) // simple interpolation
{
- if(s_chan[ch].sinc<0x10000L) // -> upsampling?
- InterpolateUp(ch); // --> interpolate up
- else InterpolateDown(ch); // --> else down
- fa=s_chan[ch].SB[29];
+ if(spu->s_chan[ch].sinc<0x10000L) // -> upsampling?
+ InterpolateUp(spu, ch); // --> interpolate up
+ else InterpolateDown(spu, ch); // --> else down
+ fa=spu->s_chan[ch].SB[29];
}
//------------------------------------------//
- else fa=s_chan[ch].SB[29]; // no interpolation
+ else fa=spu->s_chan[ch].SB[29]; // no interpolation
}
- s_chan[ch].sval = (MixADSR(ch) * fa) / 1023; // add adsr
+ spu->s_chan[ch].sval = (MixADSR(spu, ch) * fa) / 1023; // add adsr
- if(s_chan[ch].bFMod==2) // fmod freq channel
+ if(spu->s_chan[ch].bFMod==2) // fmod freq channel
{
- int NP=s_chan[ch+1].iRawPitch;
+ int NP=spu->s_chan[ch+1].iRawPitch;
double intr;
- NP=((32768L+s_chan[ch].sval)*NP)/32768L; // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :)
+ NP=((32768L+spu->s_chan[ch].sval)*NP)/32768L; // mmm... I still need to adjust that to 1/48 khz... we will wait for the first game/demo using it to decide how to do it :)
if(NP>0x3fff) NP=0x3fff;
if(NP<0x1) NP=0x1;
@@ -672,42 +616,42 @@ GOON: ;
NP=(44100L*NP)/(4096L); // calc frequency
- s_chan[ch+1].iActFreq=NP;
- s_chan[ch+1].iUsedFreq=NP;
- s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
- if(!s_chan[ch+1].sinc) s_chan[ch+1].sinc=1;
- if(iUseInterpolation==1) // freq change in sipmle interpolation mode
- s_chan[ch+1].SB[32]=1;
+ spu->s_chan[ch+1].iActFreq=NP;
+ spu->s_chan[ch+1].iUsedFreq=NP;
+ spu->s_chan[ch+1].sinc=(((NP/10)<<16)/4410);
+ if(!spu->s_chan[ch+1].sinc) spu->s_chan[ch+1].sinc=1;
+ if(spu->iUseInterpolation==1) // freq change in sipmle interpolation mode
+ spu->s_chan[ch+1].SB[32]=1;
// mmmm... set up freq decoding positions?
-// s_chan[ch+1].iSBPos=28;
-// s_chan[ch+1].spos=0x10000L;
+// spu->s_chan[ch+1].iSBPos=28;
+// spu->s_chan[ch+1].spos=0x10000L;
}
else
{
//////////////////////////////////////////////
// ok, left/right sound volume (psx volume goes from 0 ... 0x3fff)
- if(s_chan[ch].iMute)
- s_chan[ch].sval=0; // debug mute
+ if(spu->s_chan[ch].iMute)
+ spu->s_chan[ch].sval=0; // debug mute
else
{
- if(s_chan[ch].bVolumeL)
- SSumL[0]+=(s_chan[ch].sval*s_chan[ch].iLeftVolume)/0x4000L;
- if(s_chan[ch].bVolumeR)
- SSumR[0]+=(s_chan[ch].sval*s_chan[ch].iRightVolume)/0x4000L;
+ if(spu->s_chan[ch].bVolumeL)
+ spu->SSumL[0]+=(spu->s_chan[ch].sval*spu->s_chan[ch].iLeftVolume)/0x4000L;
+ if(spu->s_chan[ch].bVolumeR)
+ spu->SSumR[0]+=(spu->s_chan[ch].sval*spu->s_chan[ch].iRightVolume)/0x4000L;
}
//////////////////////////////////////////////
// now let us store sound data for reverb
- if(s_chan[ch].bRVBActive) StoreREVERB(ch,0);
+ if(spu->s_chan[ch].bRVBActive) StoreREVERB(spu, ch,0);
}
////////////////////////////////////////////////
// ok, go on until 1 ms data of this channel is collected
- s_chan[ch].spos += s_chan[ch].sinc;
+ spu->s_chan[ch].spos += spu->s_chan[ch].sinc;
}
ENDX: ;
@@ -721,54 +665,54 @@ ENDX: ;
///////////////////////////////////////////////////////
// mix all channels (including reverb) into one buffer
- SSumL[0]+=MixREVERBLeft(0,0);
- SSumL[0]+=MixREVERBLeft(0,1);
- SSumR[0]+=MixREVERBRight(0);
- SSumR[0]+=MixREVERBRight(1);
+ spu->SSumL[0]+=MixREVERBLeft(spu, 0,0);
+ spu->SSumL[0]+=MixREVERBLeft(spu, 0,1);
+ spu->SSumR[0]+=MixREVERBRight(spu, 0);
+ spu->SSumR[0]+=MixREVERBRight(spu, 1);
- d=SSumL[0]/voldiv;SSumL[0]=0;
- d2=SSumR[0]/voldiv;SSumR[0]=0;
+ d=spu->SSumL[0]/voldiv;spu->SSumL[0]=0;
+ d2=spu->SSumR[0]/voldiv;spu->SSumR[0]=0;
if(d<-32767) d=-32767;if(d>32767) d=32767;
if(d2<-32767) d2=-32767;if(d2>32767) d2=32767;
- if(sampcount>=decaybegin)
+ if(spu->sampcount>=spu->decaybegin)
{
s32 dmul;
- if(decaybegin!=~0) // Is anyone REALLY going to be playing a song
+ if(spu->decaybegin!=~0) // Is anyone REALLY going to be playing a song
// for 13 hours?
{
- if(sampcount>=decayend)
+ if(spu->sampcount>=spu->decayend)
{
// ao_song_done = 1;
return(0);
}
- dmul=256-(256*(sampcount-decaybegin)/(decayend-decaybegin));
+ dmul=256-(256*(spu->sampcount-spu->decaybegin)/(spu->decayend-spu->decaybegin));
d=(d*dmul)>>8;
d2=(d2*dmul)>>8;
}
}
- sampcount++;
+ spu->sampcount++;
- *pS++=d;
- *pS++=d2;
+ *spu->pS++=d;
+ *spu->pS++=d2;
- InitREVERB();
+ InitREVERB(spu);
//////////////////////////////////////////////////////
// feed the sound
// wanna have around 1/60 sec (16.666 ms) updates
- if ((((unsigned char *)pS)-((unsigned char *)pSpuBuffer)) == (735*4))
+ if ((((unsigned char *)spu->pS)-((unsigned char *)spu->pSpuBuffer)) == (735*4))
{
- cpu->spu_callback((u8*)pSpuBuffer,(u8*)pS-(u8*)pSpuBuffer, cpu->spu_callback_data);
- pS=(short *)pSpuBuffer;
+ cpu->spu_callback((u8*)spu->pSpuBuffer,(u8*)spu->pS-(u8*)spu->pSpuBuffer, cpu->spu_callback_data);
+ spu->pS=(short *)spu->pSpuBuffer;
}
}
// end of big main loop...
- bThreadEnded=1;
+ spu->bThreadEnded=1;
return 0;
}
@@ -784,11 +728,12 @@ ENDX: ;
EXPORT_GCC void CALLBACK SPU2async(mips_cpu_context *cpu, unsigned long cycle)
{
- if(iSpuAsyncWait)
+ spu2_state_t *spu = cpu->spu2;
+ if(spu->iSpuAsyncWait)
{
- iSpuAsyncWait++;
- if(iSpuAsyncWait<=64) return;
- iSpuAsyncWait=0;
+ spu->iSpuAsyncWait++;
+ if(spu->iSpuAsyncWait<=64) return;
+ spu->iSpuAsyncWait=0;
}
MAINThread(cpu, 0); // -> linux high-compat mode
@@ -805,13 +750,27 @@ EXPORT_GCC void CALLBACK SPU2async(mips_cpu_context *cpu, unsigned long cycle)
EXPORT_GCC long CALLBACK SPU2init(mips_cpu_context *cpu, void (*callback)(unsigned char *, long, void *), void *data)
{
+ cpu->spu2 = malloc (sizeof (spu2_state_t));
+ memset (cpu->spu2, 0, sizeof (spu2_state_t));
+ cpu->spu2->iUseXA=0;
+ cpu->spu2->iVolume=3;
+ cpu->spu2->iXAPitch=1;
+ cpu->spu2->iUseTimer=2;
+ cpu->spu2->iSPUIRQWait=1;
+ cpu->spu2->iDebugMode=0;
+ cpu->spu2->iRecordMode=0;
+ cpu->spu2->iUseReverb=1;
+ cpu->spu2->iUseInterpolation=2;
+ cpu->spu2->dwNoiseVal=1; // global noise generator
+ cpu->spu2->lastch=-1;
+
cpu->spu_callback = callback;
cpu->spu_callback_data = data;
- spuMemC=(unsigned char *)spuMem; // just small setup
- memset((void *)s_chan,0,MAXCHAN*sizeof(SPUCHAN));
- memset(rvb,0,2*sizeof(REVERBInfo));
+ cpu->spu2->spuMemC=(unsigned char *)cpu->spu2->spuMem; // just small setup
+ memset((void *)cpu->spu2->s_chan,0,MAXCHAN*sizeof(SPUCHAN));
+ memset(cpu->spu2->rvb,0,2*sizeof(REVERBInfo));
- sampcount = 0;
+ cpu->spu2->sampcount = 0;
InitADSR();
@@ -824,13 +783,14 @@ EXPORT_GCC long CALLBACK SPU2init(mips_cpu_context *cpu, void (*callback)(unsign
static void SetupTimer(mips_cpu_context *cpu)
{
- memset(SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers
- memset(SSumL,0,NSSIZE*sizeof(int));
- pS=(short *)pSpuBuffer; // setup soundbuffer pointer
-
- bEndThread=0; // init thread vars
- bThreadEnded=0;
- bSpuInit=1; // flag: we are inited
+ spu2_state_t *spu = cpu->spu2;
+ memset(spu->SSumR,0,NSSIZE*sizeof(int)); // init some mixing buffers
+ memset(spu->SSumL,0,NSSIZE*sizeof(int));
+ spu->pS=(short *)spu->pSpuBuffer; // setup soundbuffer pointer
+
+ spu->bEndThread=0; // init thread vars
+ spu->bThreadEnded=0;
+ spu->bSpuInit=1; // flag: we are inited
}
////////////////////////////////////////////////////////////////////////
@@ -839,9 +799,10 @@ static void SetupTimer(mips_cpu_context *cpu)
static void RemoveTimer(mips_cpu_context *cpu)
{
- bEndThread=1; // raise flag to end thread
- bThreadEnded=0; // no more spu is running
- bSpuInit=0;
+ spu2_state_t *spu = cpu->spu2;
+ spu->bEndThread=1; // raise flag to end thread
+ spu->bThreadEnded=0; // no more spu is running
+ spu->bSpuInit=0;
}
////////////////////////////////////////////////////////////////////////
@@ -850,32 +811,33 @@ static void RemoveTimer(mips_cpu_context *cpu)
static void SetupStreams(mips_cpu_context *cpu)
{
+ spu2_state_t *spu = cpu->spu2;
int i;
- pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer
+ spu->pSpuBuffer=(unsigned char *)malloc(32768); // alloc mixing buffer
i=NSSIZE*2;
- sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer
- memset(sRVBStart[0],0,i*4);
- sRVBEnd[0] = sRVBStart[0] + i;
- sRVBPlay[0] = sRVBStart[0];
- sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer
- memset(sRVBStart[1],0,i*4);
- sRVBEnd[1] = sRVBStart[1] + i;
- sRVBPlay[1] = sRVBStart[1];
+ spu->sRVBStart[0] = (int *)malloc(i*4); // alloc reverb buffer
+ memset(spu->sRVBStart[0],0,i*4);
+ spu->sRVBEnd[0] = spu->sRVBStart[0] + i;
+ spu->sRVBPlay[0] = spu->sRVBStart[0];
+ spu->sRVBStart[1] = (int *)malloc(i*4); // alloc reverb buffer
+ memset(spu->sRVBStart[1],0,i*4);
+ spu->sRVBEnd[1] = spu->sRVBStart[1] + i;
+ spu->sRVBPlay[1] = spu->sRVBStart[1];
for(i=0;i<MAXCHAN;i++) // loop sound channels
{
// we don't use mutex sync... not needed, would only
// slow us down:
-// s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL);
- s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain
- s_chan[i].iMute=0;
- s_chan[i].iIrqDone=0;
- s_chan[i].pLoop=spuMemC;
- s_chan[i].pStart=spuMemC;
- s_chan[i].pCurr=spuMemC;
+// spu->s_chan[i].hMutex=CreateMutex(NULL,FALSE,NULL);
+ spu->s_chan[i].ADSRX.SustainLevel = 1024; // -> init sustain
+ spu->s_chan[i].iMute=0;
+ spu->s_chan[i].iIrqDone=0;
+ spu->s_chan[i].pLoop=spu->spuMemC;
+ spu->s_chan[i].pStart=spu->spuMemC;
+ spu->s_chan[i].pCurr=spu->spuMemC;
}
}
@@ -885,21 +847,22 @@ static void SetupStreams(mips_cpu_context *cpu)
static void RemoveStreams(mips_cpu_context *cpu)
{
- free(pSpuBuffer); // free mixing buffer
- pSpuBuffer=NULL;
- free(sRVBStart[0]); // free reverb buffer
- sRVBStart[0]=0;
- free(sRVBStart[1]); // free reverb buffer
- sRVBStart[1]=0;
+ spu2_state_t *spu = cpu->spu2;
+ free(spu->pSpuBuffer); // free mixing buffer
+ spu->pSpuBuffer=NULL;
+ free(spu->sRVBStart[0]); // free reverb buffer
+ spu->sRVBStart[0]=0;
+ free(spu->sRVBStart[1]); // free reverb buffer
+ spu->sRVBStart[1]=0;
/*
int i;
for(i=0;i<MAXCHAN;i++)
{
- WaitForSingleObject(s_chan[i].hMutex,2000);
- ReleaseMutex(s_chan[i].hMutex);
- if(s_chan[i].hMutex)
- {CloseHandle(s_chan[i].hMutex);s_chan[i].hMutex=0;}
+ WaitForSingleObject(spu->s_chan[i].hMutex,2000);
+ ReleaseMutex(spu->s_chan[i].hMutex);
+ if(spu->s_chan[i].hMutex)
+ {CloseHandle(spu->s_chan[i].hMutex);spu->s_chan[i].hMutex=0;}
}
*/
}
@@ -911,33 +874,34 @@ static void RemoveStreams(mips_cpu_context *cpu)
EXPORT_GCC long CALLBACK SPU2open(mips_cpu_context *cpu, void *pDsp)
{
- if(bSPUIsOpen) return 0; // security for some stupid main emus
-
- iUseXA=0; // just small setup
- iVolume=3;
- bEndThread=0;
- bThreadEnded=0;
- spuMemC=(unsigned char *)spuMem;
- memset((void *)s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
- pSpuIrq[0]=0;
- pSpuIrq[1]=0;
- iSPUIRQWait=1;
- dwNewChannel2[0]=0;
- dwNewChannel2[1]=0;
- dwEndChannel2[0]=0;
- dwEndChannel2[1]=0;
- spuCtrl2[0]=0;
- spuCtrl2[1]=0;
- spuStat2[0]=0;
- spuStat2[1]=0;
- spuIrq2[0]=0;
- spuIrq2[1]=0;
- spuAddr2[0]=0xffffffff;
- spuAddr2[1]=0xffffffff;
- spuRvbAddr2[0]=0;
- spuRvbAddr2[1]=0;
- spuRvbAEnd2[0]=0;
- spuRvbAEnd2[1]=0;
+ spu2_state_t *spu = cpu->spu2;
+ if(spu->bSPUIsOpen) return 0; // security for some stupid main emus
+
+ spu->iUseXA=0; // just small setup
+ spu->iVolume=3;
+ spu->bEndThread=0;
+ spu->bThreadEnded=0;
+ spu->spuMemC=(unsigned char *)spu->spuMem;
+ memset((void *)spu->s_chan,0,(MAXCHAN+1)*sizeof(SPUCHAN));
+ spu->pSpuIrq[0]=0;
+ spu->pSpuIrq[1]=0;
+ spu->iSPUIRQWait=1;
+ spu->dwNewChannel2[0]=0;
+ spu->dwNewChannel2[1]=0;
+ spu->dwEndChannel2[0]=0;
+ spu->dwEndChannel2[1]=0;
+ spu->spuCtrl2[0]=0;
+ spu->spuCtrl2[1]=0;
+ spu->spuStat2[0]=0;
+ spu->spuStat2[1]=0;
+ spu->spuIrq2[0]=0;
+ spu->spuIrq2[1]=0;
+ spu->spuAddr2[0]=0xffffffff;
+ spu->spuAddr2[1]=0xffffffff;
+ spu->spuRvbAddr2[0]=0;
+ spu->spuRvbAddr2[1]=0;
+ spu->spuRvbAEnd2[0]=0;
+ spu->spuRvbAEnd2[1]=0;
// ReadConfig(); // read user stuff
@@ -947,7 +911,7 @@ EXPORT_GCC long CALLBACK SPU2open(mips_cpu_context *cpu, void *pDsp)
SetupTimer(cpu); // timer for feeding data
- bSPUIsOpen=1;
+ spu->bSPUIsOpen=1;
return 0;
}
@@ -960,9 +924,10 @@ EXPORT_GCC long CALLBACK SPU2open(mips_cpu_context *cpu, void *pDsp)
EXPORT_GCC void CALLBACK SPU2close(mips_cpu_context *cpu)
{
- if(!bSPUIsOpen) return; // some security
+ spu2_state_t *spu = cpu->spu2;
+ if(!spu->bSPUIsOpen) return; // some security
- bSPUIsOpen=0; // no more open
+ spu->bSPUIsOpen=0; // no more open
RemoveTimer(cpu); // no more feeding
@@ -995,6 +960,7 @@ EXPORT_GCC long CALLBACK SPU2test(void)
// passes a callback that should be called on SPU-IRQ/cdda volume change
////////////////////////////////////////////////////////////////////////
+#if 0
// not used yet
EXPORT_GCC void CALLBACK SPU2irqCallback(void (CALLBACK *callback)(void))
{
@@ -1012,3 +978,4 @@ EXPORT_GCC void CALLBACK SPU2registerCDDAVolume(void (CALLBACK *CDDAVcallback)(u
{
cddavCallback = CDDAVcallback;
}
+#endif