X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=fceu.git;a=blobdiff_plain;f=sound.c;h=af5ce57b4ad37f82a1d40bf22142b14f76532523;hp=8cdde0e6bb3ca065b85c3dcfce32110d5076e107;hb=527b98f6e7965f464c804ee5279855326c78dc6d;hpb=9115e7d2b5e5b8dc00774fe92db97f1d02b2fee1 diff --git a/sound.c b/sound.c index 8cdde0e..af5ce57 100644 --- a/sound.c +++ b/sound.c @@ -38,31 +38,36 @@ #include "fce.h" #include "svga.h" #include "sound.h" +#include "state.h" -uint32 soundtsinc; -uint32 soundtsi; +uint32 Wave[2048+512]; +int32 WaveHi[40000]; // unused +int16 WaveFinalMono[2048+512]; -uint32 Wave[2048]; -int32 WaveFinal[2048]; -int16 WaveFinalMono[2048]; - -EXPSOUND GameExpSound={0,0,0}; +EXPSOUND GameExpSound={0,0,0,0,0,0}; uint8 trimode=0; uint8 tricoop=0; + +static uint8 IRQFrameMode=0; /* $4017 / xx000000 */ uint8 PSG[0x18]; +static uint8 RawDALatch=0; /* $4011 0xxxxxxx */ + +uint8 EnabledChannels=0; /* Byte written to $4015 */ uint8 decvolume[3]; uint8 realvolume[3]; static int32 count[5]; -static int64 sqacc[2]={0,0}; +static int32 sqacc[2]={0,0}; uint8 sqnon=0; +uint32 soundtsoffs=0; + #undef printf uint16 nreg; -int32 lengthcount[4]; +static int32 lengthcount[4]; extern int soundvol; @@ -80,7 +85,10 @@ static const uint32 SNoiseFreqTable[0x10]= }; static uint32 NoiseFreqTable[0x10]; -int64 nesincsizeLL; +int32 nesincsize; +uint32 soundtsinc; +uint32 soundtsi; + static const uint8 NTSCPCMTable[0x10]= { @@ -94,73 +102,58 @@ static const uint8 PALPCMTable[0x10]= // These values are just guessed. 0x58,0x4a,0x41,0x3b,0x31,0x27,0x21,0x19 }; -uint32 PSG_base; +static const uint32 NTSCDMCTable[0x10]= +{ + 428,380,340,320,286,254,226,214, + 190,160,142,128,106, 84 ,72,54 +}; + +/* Previous values for PAL DMC was value - 1, + * I am not certain if this is if FCEU handled + * PAL differently or not, the NTSC values are right, + * so I am assuming that the current value is handled + * the same way NTSC is handled. */ + +static const uint32 PALDMCTable[0x10]= +{ + 398, 354, 316, 298, 276, 236, 210, 198, + 176, 148, 132, 118, 98, 78, 66, 50 +}; // $4010 - Frequency // $4011 - Actual data outputted // $4012 - Address register: $c000 + V*64 // $4013 - Size register: Size in bytes = (V+1)*64 +int32 DMCacc=1; +int32 DMCPeriod=0; +uint8 DMCBitCount=0; -static int64 PCMacc=0; -static int PCMfreq; -int32 PCMIRQCount; -uint8 PCMBitIndex=0; -uint32 PCMAddressIndex=0; -int32 PCMSizeIndex=0; -uint8 PCMBuffer=0; -int vdis=0; +uint8 DMCAddressLatch=0,DMCSizeLatch=0; /* writes to 4012 and 4013 */ +uint8 DMCFormat=0; /* Write to $4010 */ -static void Dummyfunc(void) {}; +static uint32 DMCAddress=0; +static int32 DMCSize=0; +static uint8 DMCShift=0; +static uint8 SIRQStat=0; -static void (*DoNoise)(void)=Dummyfunc; -static void (*DoTriangle)(void)=Dummyfunc; -static void (*DoPCM)(void)=Dummyfunc; -static void (*DoSQ1)(void)=Dummyfunc; -static void (*DoSQ2)(void)=Dummyfunc; +static char DMCHaveDMA=0; +static uint8 DMCDMABuf=0; +char DMCHaveSample=0; -static void CalcDPCMIRQ(void) -{ - uint32 freq; - uint32 honk; - uint32 cycles; +uint32 PSG_base; - if(PAL) - freq=(PALPCMTable[PSG[0x10]&0xF]<<4); - else - freq=(NTSCPCMTable[PSG[0x10]&0xF]<<4); - - cycles=(((PSG[0x13]<<4)+1)); - cycles*=freq/14; - honk=((PSG[0x13]<<4)+1)*freq; - honk-=cycles; - //if(PAL) honk/=107; - //else honk/=(double)113.66666666; - PCMIRQCount=honk*48; - //PCMIRQCount=honk*3; //180; - //if(PAL) PCMIRQCount*=.93; - vdis=0; -} +static void Dummyfunc(int end) {}; -static void PrepDPCM() -{ - PCMAddressIndex=0x4000+(PSG[0x12]<<6); - PCMSizeIndex=(PSG[0x13]<<4)+1; - PCMBitIndex=0; - //PCMBuffer=ARead[0x8000+PCMAddressIndex](0x8000+PCMAddressIndex); - if(PAL) - PCMfreq=PALPCMTable[PSG[0x10]&0xF]; - else - PCMfreq=NTSCPCMTable[PSG[0x10]&0xF]; - PCMacc=(int64)PCMfreq<<50; -} +static void (*DoNoise)(int end)=Dummyfunc; +static void (*DoTriangle)(int end)=Dummyfunc; +static void (*DoPCM)(int end)=Dummyfunc; +static void (*DoSQ1)(int end)=Dummyfunc; +static void (*DoSQ2)(int end)=Dummyfunc; uint8 sweepon[2]={0,0}; int32 curfreq[2]={0,0}; - -uint8 SIRQStat=0; - uint8 SweepCount[2]; uint8 DecCountTo1[3]; @@ -183,23 +176,55 @@ static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr) return(1); } -static DECLFW(Write0x11) +static uint8 DutyCount[2]={0,0}; + +static void LoadDMCPeriod(uint8 V) +{ + if(PAL) + DMCPeriod=PALDMCTable[V]; + else + DMCPeriod=NTSCDMCTable[V]; +} + +static void PrepDPCM() { - DoPCM(); - PSG[0x11]=V&0x7F; + DMCAddress=0x4000+(DMCAddressLatch<<6); + DMCSize=(DMCSizeLatch<<4)+1; } -static uint8 DutyCount[2]={0,0}; +static void SQReload(int x, uint8 V) +{ + if(EnabledChannels&(1<>3)&0x1f]; + sqnon|=1<>4)&7)+1; + DutyCount[x]=0; + sqacc[x]=((int32)curfreq[0]+1)<<18; + + //RectDutyCount[x]=7; + //EnvUnits[x].reloaddec=1; + //reloadfreq[x]=1; +} static DECLFW(Write_PSG) { //if((A>=0x4004 && A<=0x4007) || A==0x4015) - //printf("$%04x:$%02x, %d\n",A,V,timestamp); + //printf("$%04x:$%02x, %d\n",A,V,SOUNDTS); A&=0x1f; switch(A) { case 0x0: - DoSQ1(); + DoSQ1(0); if(V&0x10) realvolume[0]=V&0xF; break; @@ -207,28 +232,16 @@ static DECLFW(Write_PSG) sweepon[0]=V&0x80; break; case 0x2: - DoSQ1(); + DoSQ1(0); curfreq[0]&=0xFF00; curfreq[0]|=V; break; case 0x3: - if(PSG[0x15]&1) - { - DoSQ1(); - lengthcount[0]=lengthtable[(V>>3)&0x1f]; - sqnon|=1; - } - sweepon[0]=PSG[1]&0x80; - curfreq[0]=PSG[0x2]|((V&7)<<8); - decvolume[0]=0xF; - DecCountTo1[0]=(PSG[0]&0xF)+1; - SweepCount[0]=((PSG[0x1]>>4)&7)+1; - DutyCount[0]=0; - sqacc[0]=((int64)curfreq[0]+1)<<50; + SQReload(0,V); break; case 0x4: - DoSQ2(); + DoSQ2(0); if(V&0x10) realvolume[1]=V&0xF; break; @@ -236,27 +249,15 @@ static DECLFW(Write_PSG) sweepon[1]=V&0x80; break; case 0x6: - DoSQ2(); + DoSQ2(0); curfreq[1]&=0xFF00; curfreq[1]|=V; break; case 0x7: - if(PSG[0x15]&2) - { - DoSQ2(); - lengthcount[1]=lengthtable[(V>>3)&0x1f]; - sqnon|=2; - } - sweepon[1]=PSG[0x5]&0x80; - curfreq[1]=PSG[0x6]|((V&7)<<8); - decvolume[1]=0xF; - DecCountTo1[1]=(PSG[0x4]&0xF)+1; - SweepCount[1]=((PSG[0x5]>>4)&7)+1; - DutyCount[1]=0; - sqacc[1]=((int64)curfreq[1]+1)<<50; + SQReload(1,V); break; case 0x8: - DoTriangle(); + DoTriangle(0); if(laster&0x80) { tricoop=V&0x7F; @@ -266,12 +267,12 @@ static DECLFW(Write_PSG) tricoop=0; laster=V&0x80; break; - case 0xa:DoTriangle(); + case 0xa:DoTriangle(0); break; case 0xb: - if(PSG[0x15]&0x4) + if(EnabledChannels&0x4) { - DoTriangle(); + DoTriangle(0); sqnon|=4; lengthcount[2]=lengthtable[(V>>3)&0x1f]; } @@ -279,101 +280,121 @@ static DECLFW(Write_PSG) tricoop=PSG[0x8]&0x7f; trimode=PSG[0x8]&0x80; break; - case 0xC:DoNoise(); + case 0xC:DoNoise(0); if(V&0x10) realvolume[2]=V&0xF; break; - case 0xE:DoNoise();break; + case 0xE:DoNoise(0);break; case 0xF: - if(PSG[0x15]&8) + if(EnabledChannels&8) { - DoNoise(); + DoNoise(0); sqnon|=8; lengthcount[3]=lengthtable[(V>>3)&0x1f]; } decvolume[2]=0xF; DecCountTo1[2]=(PSG[0xC]&0xF)+1; break; - case 0x10:DoPCM(); - if(!(V&0x80)) - X6502_IRQEnd(FCEU_IQDPCM); - break; - case 0x15: - { - int t=V^PSG[0x15]; + } + PSG[A]=V; +} - if(t&1) - DoSQ1(); - if(t&2) - DoSQ2(); - if(t&4) - DoTriangle(); - if(t&8) - DoNoise(); - if(t&0x10) - DoPCM(); - sqnon&=V; - if(V&0x10) +static DECLFW(Write_DMCRegs) +{ + A&=0xF; + + switch(A) + { + case 0x00:DoPCM(0); + LoadDMCPeriod(V&0xF); + + if(SIRQStat&0x80) { - if(!(PSG[0x15]&0x10)) + if(!(V&0x80)) { - PrepDPCM(); - CalcDPCMIRQ(); + X6502_IRQEnd(FCEU_IQDPCM); + SIRQStat&=~0x80; } - else if(vdis) - CalcDPCMIRQ(); + else X6502_IRQBegin(FCEU_IQDPCM); } - else - PCMIRQCount=0; - X6502_IRQEnd(FCEU_IQDPCM); - } - break; - case 0x17: - V&=0xC0; - fcnt=0; - if(V&0x80) - FrameSoundUpdate(); - fhcnt=fhinc; - X6502_IRQEnd(FCEU_IQFCOUNT); - SIRQStat&=~0x40; - break; + DMCFormat=V; + break; + case 0x01:DoPCM(0); + RawDALatch=V&0x7F; + break; + case 0x02:DMCAddressLatch=V;break; + case 0x03:DMCSizeLatch=V;break; } - PSG[A]=V; } -DECLFR(Read_PSG) +static DECLFW(StatusWrite) { - uint8 ret; - if(PSG[0x15]&0x10) - DoPCM(); - ret=(PSG[0x15]&(sqnon|0x10))|SIRQStat; - SIRQStat&=~0x40; - X6502_IRQEnd(/*FCEU_IQDPCM|*/FCEU_IQFCOUNT); - return ret; + int x; + int32 end=(SOUNDTS<<16)/soundtsinc; + int t=V^EnabledChannels; + + if(t&1) + DoSQ1(end); + if(t&2) + DoSQ2(end); + if(t&4) + DoTriangle(end); + if(t&8) + DoNoise(end); + if(t&0x10) + DoPCM(end); + sqnon&=V; + for(x=0;x<4;x++) + if(!(V&(1<0) @@ -381,7 +402,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) lengthcount[2]--; if(lengthcount[2]<=0) { - DoTriangle(); + DoTriangle(0); sqnon&=~4; } } @@ -389,7 +410,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) for(P=0;P<2;P++) { - if(PSG[0x15]&(P+1) && sqnon&(P+1)) + if(EnabledChannels&(P+1) && sqnon&(P+1)) { if(!(PSG[P<<2]&0x20)) { @@ -445,7 +466,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) } } - if(PSG[0x15]&0x8 && sqnon&8) + if(EnabledChannels&0x8 && sqnon&8) { if(!(PSG[0xC]&0x20)) { @@ -466,7 +487,7 @@ static void FASTAPASS(1) FrameSoundStuff(int V) laster=0; if(tricoop) { - if(tricoop==1) DoTriangle(); + if(tricoop==1) DoTriangle(0); tricoop--; } } @@ -522,21 +543,36 @@ void FrameSoundUpdate(void) // Linear counter: Bit 0-6 of $4008 // Length counter: Bit 4-7 of $4003, $4007, $400b, $400f + if(!fcnt && !(IRQFrameMode&0x3)) + { + SIRQStat|=0x40; + X6502_IRQBegin(FCEU_IQFCOUNT); + } + if(fcnt==3) { - if(PSG[0x17]&0x80) + if(IRQFrameMode&0x2) fhcnt+=fhinc; - if(!(PSG[0x17]&0xC0)) - { - SIRQStat|=0x40; - X6502_IRQBegin(FCEU_IQFCOUNT); - } } - //if(SIRQStat&0x40) X6502_IRQBegin(FCEU_IQFCOUNT); FrameSoundStuff(fcnt); fcnt=(fcnt+1)&3; } +static INLINE void tester(void) +{ + if(DMCBitCount==0) + { + if(!DMCHaveDMA) + DMCHaveSample=0; + else + { + DMCHaveSample=1; + DMCShift=DMCDMABuf; + DMCHaveDMA=0; + } + } +} + static uint32 ChannelBC[5]; static uint32 RectAmp[2][8]; @@ -561,113 +597,119 @@ static void FASTAPASS(1) CalcRectAmp(int P) *b=V; } -static void RDoPCM(void) +static INLINE void DMCDMA(void) { - int32 V; - int32 start,end; - int64 freq; - uint32 out=PSG[0x11]<<3; + if(DMCSize && !DMCHaveDMA) + { +#if 0 + X6502_DMR(0x8000+DMCAddress); + X6502_DMR(0x8000+DMCAddress); + X6502_DMR(0x8000+DMCAddress); + DMCDMABuf=X6502_DMR(0x8000+DMCAddress); +#else + X6502_AddCycles(4); + DMCDMABuf=X.DB=ARead[0x8000+DMCAddress](0x8000+DMCAddress); +#endif + DMCHaveDMA=1; + DMCAddress=(DMCAddress+1)&0x7fff; + DMCSize--; + if(!DMCSize) + { + if(DMCFormat&0x40) + PrepDPCM(); + else + { + SIRQStat|=0x80; + if(DMCFormat&0x80) + X6502_IRQBegin(FCEU_IQDPCM); + } + } + } +} - start=ChannelBC[4]; - end=(timestamp<<16)/soundtsinc; - if(end<=start) return; - ChannelBC[4]=end; +void FCEU_SoundCPUHook(int cycles48) +{ + fhcnt-=cycles48; + if(fhcnt<=0) + { + FrameSoundUpdate(); + fhcnt+=fhinc; + } - if(PSG[0x15]&0x10) - { - freq=PCMfreq; - freq<<=50; + DMCDMA(); + DMCacc-=cycles48/48; - for(V=start;V>4]+=PSG[0x11]<<3; - goto endopcmo; - } - } - else - { - PCMBuffer=ARead[0x8000+PCMAddressIndex](0x8000+PCMAddressIndex); - PCMAddressIndex=(PCMAddressIndex+1)&0x7fff; - } - } + while(DMCacc<=0) + { + if(DMCHaveSample) + { + uint8 bah=RawDALatch; + int t=((DMCShift&1)<<2)-2; - { - int t=(((PCMBuffer>>PCMBitIndex)&1)<<2)-2; - uint8 bah=PSG[0x11]; - - PCMacc+=freq; - PSG[0x11]+=t; - if(PSG[0x11]&0x80) - PSG[0x11]=bah; - else - out=PSG[0x11]<<3; - } - PCMBitIndex=(PCMBitIndex+1)&7; - } - Wave[V>>4]+=out; //(PSG[0x11]-64)<<3; - } - } - else + /* Unbelievably ugly hack */ + if(FSettings.SndRate) { - if((end-start)>64) - { - for(V=start;V<=(start|15);V++) - Wave[V>>4]+=out; - out<<=4; - for(V=(start>>4)+1;V<(end>>4);V++) - Wave[V]+=out; - out>>=4; - for(V=end&(~15);V>4]+=out; - } - else - for(V=start;V>4]+=out; + soundtsoffs+=DMCacc; + DoPCM(0); + soundtsoffs-=DMCacc; } - endopcmo:; + RawDALatch+=t; + if(RawDALatch&0x80) + RawDALatch=bah; + } + + DMCacc+=DMCPeriod; + DMCBitCount=(DMCBitCount+1)&7; + DMCShift>>=1; + tester(); + } +} + +static void RDoPCM(int32 end) +{ + int32 V; + int32 start; + + start=ChannelBC[4]; + if(end==0) end=(SOUNDTS<<16)/soundtsinc; + if(end<=start) return; + ChannelBC[4]=end; + + for(V=start;V>4]+=RawDALatch<<3; } -static void RDoSQ1(void) +static void RDoSQ1(int32 end) { int32 V; - int32 start,end; - int64 freq; + int32 start; + int32 freq; - CalcRectAmp(0); start=ChannelBC[0]; - end=(timestamp<<16)/soundtsinc; + if(end==0) end=(SOUNDTS<<16)/soundtsinc; if(end<=start) return; ChannelBC[0]=end; + if(!(EnabledChannels&1 && sqnon&1)) + return; + if(curfreq[0]<8 || curfreq[0]>0x7ff) return; if(!CheckFreq(curfreq[0],PSG[0x1])) return; - if(PSG[0x15]&1 && sqnon&1) + CalcRectAmp(0); + { uint32 out=RectAmp[0][DutyCount[0]]; freq=curfreq[0]+1; { - freq<<=50; + freq<<=18; for(V=start;V>4]+=out; - sqacc[0]-=nesincsizeLL; + sqacc[0]-=nesincsize; if(sqacc[0]<=0) { rea: @@ -678,40 +720,42 @@ static void RDoSQ1(void) DutyCount[0]&=7; out=RectAmp[0][DutyCount[0]]; } - } - } } + } } -static void RDoSQ2(void) +static void RDoSQ2(int32 end) { int32 V; - int32 start,end; - int64 freq; + int32 start; + int32 freq; - CalcRectAmp(1); start=ChannelBC[1]; - end=(timestamp<<16)/soundtsinc; + if(end==0) end=(SOUNDTS<<16)/soundtsinc; if(end<=start) return; ChannelBC[1]=end; + if(!(EnabledChannels&2 && sqnon&2)) + return; + if(curfreq[1]<8 || curfreq[1]>0x7ff) return; if(!CheckFreq(curfreq[1],PSG[0x5])) return; - if(PSG[0x15]&2 && sqnon&2) + CalcRectAmp(1); + { uint32 out=RectAmp[1][DutyCount[1]]; freq=curfreq[1]+1; { - freq<<=50; + freq<<=18; for(V=start;V>4]+=out; - sqacc[1]-=nesincsizeLL; + sqacc[1]-=nesincsize; if(sqacc[1]<=0) { rea: @@ -722,26 +766,25 @@ static void RDoSQ2(void) DutyCount[1]&=7; out=RectAmp[1][DutyCount[1]]; } - } - } } + } } -static void RDoTriangle(void) +static void RDoTriangle(int32 end) { static uint32 tcout=0; int32 V; - int32 start,end; //,freq; - int64 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1)); + int32 start; //,freq; + int32 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1)); start=ChannelBC[2]; - end=(timestamp<<16)/soundtsinc; + if(end==0) end=(SOUNDTS<<16)/soundtsinc; if(end<=start) return; ChannelBC[2]=end; - if(! (PSG[0x15]&0x4 && sqnon&4 && tricoop) ) + if(! (EnabledChannels&0x4 && sqnon&4 && tricoop) ) { // Counter is halted, but we still need to output. for(V=start;V>4]+=tcout; @@ -760,13 +803,13 @@ static void RDoTriangle(void) } else { - static int64 triacc=0; + static int32 triacc=0; static uint8 tc=0; - freq<<=49; + freq<<=17; for(V=start;V>6; + fcnt=0; + if(V&0x2) + FrameSoundUpdate(); + fcnt=1; + fhcnt=fhinc; + X6502_IRQEnd(FCEU_IQFCOUNT); + SIRQStat&=~0x40; + IRQFrameMode=V; } -static int32 WaveNSF[256]; +void SetNESSoundMap(void) +{ + SetWriteHandler(0x4000,0x400F,Write_PSG); + SetWriteHandler(0x4010,0x4013,Write_DMCRegs); + SetWriteHandler(0x4017,0x4017,Write_IRQFM); + + SetWriteHandler(0x4015,0x4015,StatusWrite); + SetReadHandler(0x4015,0x4015,StatusRead); +} int32 highp; // 0 through 65536, 0 = no high pass, 65536 = max high pass int32 lowp; // 0 through 65536, 65536 = max low pass(total attenuation) // 65536 = no low pass -static void FilterSound(uint32 *in, int32 *out, int16 *outMono, int count) +static int32 flt_acc=0, flt_acc2=0; + +static void FilterSound(uint32 *in, int16 *outMono, int count) { - static int64 acc=0, acc2=0; - //int index=0; - //int16* tmp; - //int16* outorig=out; - //int32 prev=-99999; - for(;count;count--,in++)//,out++)//,index++) +// static int min=0, max=0; + int sh=2; + if (soundvol < 5) sh += 5 - soundvol; + + for(;count;count--,in++,outMono++) { - int64 diff; + int32 diff; - diff=((int64)*in<<24)-acc; + diff = *in - flt_acc; - acc+=(diff*highp)>>16; - acc2+=((diff-acc2)*lowp)>>16; + flt_acc += (diff*highp)>>16; + flt_acc2+= (int32) (((int64)((diff-flt_acc2)*lowp))>>16); *in=0; - // don't change the sound here -// *out=(acc2*(int64)FSettings.SoundVolume)>>(24+16); - // volume, 4 times louder by default?? -// *out = acc2 >> 24; - // just a bit louder. Hope it's okay - /* - *out = acc2 >> 22; - if(*out<-32767) *out=-32767; - if(*out>32767) *out=32767; - // go one back - - // do MONO - tmp=(int16 *)(out-1); - // don't do this the first time - if (prev == -99999) continue; - // the middle one should be interpolated - tmp[1]=(int16)((*out + prev) >> 1); - prev = *out; - */ - //outMono[index] = (int16)*out; - *outMono = (int16)(acc2 >> 24); - //if(*outMono<-16384) *outMono=-16384; - //if(*outMono>16384) *outMono=16384; - outMono++; - - // out=((int64)(acc2>>24)*(int64)FSettings.SoundVolume)>>16; //acc2>>24; - + *outMono = flt_acc2*7 >> sh; // * 7 >> 2 = * 1.75 +// if (acc2 < min) { printf("min: %i %04x\n", acc2, acc2); min = acc2; } +// if (acc2 > max) { printf("max: %i %04x\n", acc2, acc2); max = acc2; } } - // do one more } - +static int32 inbuf=0; int FlushEmulateSound(void) { - uint32 end; int x; - + uint32 end; if(!timestamp) return(0); @@ -929,29 +958,17 @@ int FlushEmulateSound(void) goto nosoundo; } - end=(timestamp<<16)/soundtsinc; - DoSQ1(); - DoSQ2(); - DoTriangle(); - DoNoise(); - DoPCM(); + end=(SOUNDTS<<16)/soundtsinc; + DoSQ1(end); + DoSQ2(end); + DoTriangle(end); + DoNoise(end); + DoPCM(end); if(GameExpSound.Fill) GameExpSound.Fill(end&0xF); -// FilterSound(Wave,WaveFinal,end>>4); - FilterSound(Wave,WaveFinal,WaveFinalMono,end>>4); -// printf("count %d, num ints %d\n", end, (end >> 4)); - if(FCEUGameInfo.type==GIT_NSF) - { - printf("IS NSF"); - int x,s=0,si=end/1024; // Only want 1/4 of the output buffer to be displayed - for(x=0;x<256;x++) - { - WaveNSF[x]=WaveFinal[s>>4]; - s+=si; - } - } + FilterSound(Wave,WaveFinalMono,end>>4); if(end&0xF) Wave[0]=Wave[(end>>4)]; @@ -960,41 +977,66 @@ int FlushEmulateSound(void) nosoundo: for(x=0;x<5;x++) ChannelBC[x]=end&0xF; - timestampbase+=timestamp; - timestamp=(soundtsinc*(end&0xF))>>16; - timestampbase-=timestamp; - return(end>>4); + soundtsoffs=(soundtsinc*(end&0xF))>>16; + end>>=4; + inbuf=end; + return(end); } -void GetSoundBuffer(int32 **W) +int GetSoundBuffer(int16 **W) { - *W=WaveNSF; + *W=WaveFinalMono; + return inbuf; } -void PowerSound(void) +void FCEUSND_Power(void) { int x; SetNESSoundMap(); + memset(PSG,0x00,sizeof(PSG)); + FCEUSND_Reset(); - for(x=0;x<0x16;x++) - if(x!=0x14) - BWrite[0x4000+x](0x4000+x,0); - PSG[0x17]=0; //x40; - fhcnt=fhinc; - fcnt=0; - nreg=1; + memset(Wave,0,sizeof(Wave)); + memset(WaveHi,0,sizeof(WaveHi)); + //memset(&EnvUnits,0,sizeof(EnvUnits)); + + for(x=0;x<5;x++) + ChannelBC[x]=0; + soundtsoffs=0; + LoadDMCPeriod(DMCFormat&0xF); } -void ResetSound(void) +void FCEUSND_Reset(void) { int x; for(x=0;x<0x16;x++) if(x!=1 && x!=5 && x!=0x14) BWrite[0x4000+x](0x4000+x,0); - PSG[0x17]=0; + + IRQFrameMode=0x0; fhcnt=fhinc; fcnt=0; nreg=1; + + DMCHaveDMA=DMCHaveSample=0; + SIRQStat=0x00; + + RawDALatch=0x00; + //TriCount=0; + //TriMode=0; + //tristep=0; + EnabledChannels=0; + for(x=0;x<4;x++) + lengthcount[x]=0; + + DMCAddressLatch=0; + DMCSizeLatch=0; + DMCFormat=0; + DMCAddress=0; + DMCSize=0; + DMCShift=0; + DMCacc=1; + DMCBitCount=0; } void SetSoundVariables(void) @@ -1023,7 +1065,8 @@ void SetSoundVariables(void) if(GameExpSound.RChange) GameExpSound.RChange(); - nesincsizeLL=(int64)((int64)562949953421312*(long double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE)); + // nesincsizeLL=(int64)((int64)562949953421312*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE)); + nesincsize=(int32)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16)); // 308845 - 1832727 PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16); for(x=0;x<0x10;x++) @@ -1035,14 +1078,16 @@ void SetSoundVariables(void) NoiseFreqTable[x]=z; } soundtsinc=(uint32)((uint64)(PAL?(long double)PAL_CPU*65536:(long double)NTSC_CPU*65536)/(FSettings.SndRate OVERSAMPLE)); - memset(Wave,0,2048*4); + memset(Wave,0,sizeof(Wave)); for(x=0;x<5;x++) ChannelBC[x]=0; highp=(250<<16)/FSettings.SndRate; // Arbitrary - lowp=((int64)25000<<16)/FSettings.SndRate; // Arbitrary + lowp=(25000<<16)/FSettings.SndRate; // Arbitrary if(highp>(1<<16)) highp=1<<16; if(lowp>(1<<16)) lowp=1<<16; + + flt_acc=flt_acc2=0; } void FixOldSaveStateSFreq(void) @@ -1062,5 +1107,54 @@ void FCEUI_Sound(int Rate) void FCEUI_SetSoundVolume(uint32 volume) { - FSettings.SoundVolume=(volume<<16)/100; + FSettings.SoundVolume=volume; +} + +SFORMAT FCEUSND_STATEINFO[]={ + { &fhcnt, 4|FCEUSTATE_RLSB,"FHCN"}, + { &fcnt, 1, "FCNT"}, + { PSG, 0x10, "PSG"}, + { &EnabledChannels, 1, "ENCH"}, + { &IRQFrameMode, 1, "IQFM"}, + + { decvolume, 3, "DECV"}, + { &sqnon, 1, "SQNO"}, + { &nreg, 2|RLSB, "NREG"}, + { &trimode, 1, "TRIM"}, + { &tricoop, 1, "TRIC"}, + { DecCountTo1, 3,"DCT1"}, + + { sweepon, 2, "SWEE"}, + { &curfreq[0], 4|FCEUSTATE_RLSB,"CRF1"}, + { &curfreq[1], 4|FCEUSTATE_RLSB,"CRF2"}, + { SweepCount, 2,"SWCT"}, + + { &SIRQStat, 1, "SIRQ"}, + + { &DMCacc, 4|FCEUSTATE_RLSB, "5ACC"}, + { &DMCBitCount, 1, "5BIT"}, + { &DMCAddress, 4|FCEUSTATE_RLSB, "5ADD"}, + { &DMCSize, 4|FCEUSTATE_RLSB, "5SIZ"}, + { &DMCShift, 1, "5SHF"}, + + { &DMCHaveDMA, 1, "5HVDM"}, + { &DMCHaveSample, 1, "5HVSP"}, + + { &DMCSizeLatch, 1, "5SZL"}, + { &DMCAddressLatch, 1, "5ADL"}, + { &DMCFormat, 1, "5FMT"}, + { &RawDALatch, 1, "RWDA"}, + { 0, } +}; + +void FCEUSND_SaveState(void) +{ + +} + +void FCEUSND_LoadState(int version) +{ + LoadDMCPeriod(DMCFormat&0xF); + RawDALatch&=0x7F; + DMCAddress&=0x7FFF; }