diff options
Diffstat (limited to 'plugins/ao/eng_psf/peops2/spu2.c')
-rw-r--r-- | plugins/ao/eng_psf/peops2/spu2.c | 559 |
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 |