release r2, update credits
[fceu.git] / sound.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 /********************************************************/
22 /*******                sound.c                         */
23 /*******                                                */
24 /*******  Sound emulation code and waveform synthesis   */
25 /*******  routines.  A few ideas were inspired          */
26 /*******  by code from Marat Fayzullin's EMUlib         */
27 /*******                                                */
28 /********************************************************/
29
30 #include <stdlib.h>
31 #include <stdio.h>
32
33 #include <string.h>
34
35 #include "types.h"
36 #include "x6502.h"
37
38 #include "fce.h"
39 #include "svga.h"
40 #include "sound.h"
41 #include "state.h"
42
43 uint32 Wave[2048+512];
44 int32 WaveHi[40000]; // unused
45 int16 WaveFinalMono[2048+512];
46
47 EXPSOUND GameExpSound={0,0,0,0,0,0};
48
49 uint8 trimode=0;
50 uint8 tricoop=0;
51
52 static uint8 IRQFrameMode=0;    /* $4017 / xx000000 */
53 uint8 PSG[0x18];
54 static uint8 RawDALatch=0;      /* $4011 0xxxxxxx */
55
56 uint8 EnabledChannels=0;                /* Byte written to $4015 */
57
58 uint8 decvolume[3];
59 uint8 realvolume[3];
60
61 static int32 count[5];
62 static int32 sqacc[2]={0,0};
63 uint8 sqnon=0;
64
65 uint32 soundtsoffs=0;
66
67 #undef printf
68 uint16 nreg;
69
70 static int32 lengthcount[4];
71
72 extern int soundvol;
73
74 static const uint8 Slengthtable[0x20]=
75 {
76  0x5,0x7f,0xA,0x1,0x14,0x2,0x28,0x3,0x50,0x4,0x1E,0x5,0x7,0x6,0x0E,0x7,
77  0x6,0x08,0xC,0x9,0x18,0xa,0x30,0xb,0x60,0xc,0x24,0xd,0x8,0xe,0x10,0xf
78 };
79
80 static uint32 lengthtable[0x20];
81
82 static const uint32 SNoiseFreqTable[0x10]=
83 {
84  2,4,8,0x10,0x20,0x30,0x40,0x50,0x65,0x7f,0xbe,0xfe,0x17d,0x1fc,0x3f9,0x7f2
85 };
86 static uint32 NoiseFreqTable[0x10];
87
88 int32 nesincsize;
89 uint32 soundtsinc;
90 uint32 soundtsi;
91
92
93 static const uint8 NTSCPCMTable[0x10]=
94 {
95  0xd6,0xbe,0xaa,0xa0,0x8f,0x7f,0x71,0x6b,
96  0x5f,0x50,0x47,0x40,0x35,0x2a,0x24,0x1b
97 };
98
99 static const uint8 PALPCMTable[0x10]=   // These values are just guessed.
100 {
101  0xc6,0xb0,0x9d,0x94,0x84,0x75,0x68,0x63,
102  0x58,0x4a,0x41,0x3b,0x31,0x27,0x21,0x19
103 };
104
105 static const uint32 NTSCDMCTable[0x10]=
106 {
107  428,380,340,320,286,254,226,214,
108  190,160,142,128,106, 84 ,72,54
109 };
110
111 /* Previous values for PAL DMC was value - 1,
112  * I am not certain if this is if FCEU handled
113  * PAL differently or not, the NTSC values are right,
114  * so I am assuming that the current value is handled
115  * the same way NTSC is handled. */
116
117 static const uint32 PALDMCTable[0x10]=
118 {
119         398, 354, 316, 298, 276, 236, 210, 198,
120         176, 148, 132, 118,  98,  78,  66,  50
121 };
122
123 // $4010        -        Frequency
124 // $4011        -        Actual data outputted
125 // $4012        -        Address register: $c000 + V*64
126 // $4013        -        Size register:  Size in bytes = (V+1)*64
127
128 int32 DMCacc=1;
129 int32 DMCPeriod=0;
130 uint8 DMCBitCount=0;
131
132 uint8 DMCAddressLatch=0,DMCSizeLatch=0; /* writes to 4012 and 4013 */
133 uint8 DMCFormat=0;      /* Write to $4010 */
134
135 static uint32 DMCAddress=0;
136 static int32 DMCSize=0;
137 static uint8 DMCShift=0;
138 static uint8 SIRQStat=0;
139
140 static char DMCHaveDMA=0;
141 static uint8 DMCDMABuf=0;
142 char DMCHaveSample=0;
143
144 uint32 PSG_base;
145
146 static void Dummyfunc(int end) {};
147
148 static void (*DoNoise)(int end)=Dummyfunc;
149 static void (*DoTriangle)(int end)=Dummyfunc;
150 static void (*DoPCM)(int end)=Dummyfunc;
151 static void (*DoSQ1)(int end)=Dummyfunc;
152 static void (*DoSQ2)(int end)=Dummyfunc;
153
154 uint8 sweepon[2]={0,0};
155 int32 curfreq[2]={0,0};
156
157 uint8 SweepCount[2];
158 uint8 DecCountTo1[3];
159
160 uint8 fcnt=0;
161 int32 fhcnt=0;
162 int32 fhinc;
163
164 static uint8 laster;
165
166 /* Instantaneous?  Maybe the new freq value is being calculated all of the time... */
167 static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr)
168 {
169  uint32 mod;
170  if(!(sr&0x8))
171  {
172   mod=cf>>(sr&7);
173   if((mod+cf)&0x800)
174    return(0);
175  }
176  return(1);
177 }
178
179 static uint8 DutyCount[2]={0,0};
180
181 static void LoadDMCPeriod(uint8 V)
182 {
183  if(PAL)
184   DMCPeriod=PALDMCTable[V];
185  else
186   DMCPeriod=NTSCDMCTable[V];
187 }
188
189 static void PrepDPCM()
190 {
191  DMCAddress=0x4000+(DMCAddressLatch<<6);
192  DMCSize=(DMCSizeLatch<<4)+1;
193 }
194
195 static void SQReload(int x, uint8 V)
196 {
197            if(EnabledChannels&(1<<x))
198            {
199             if(x)
200              DoSQ2(0);
201             else
202              DoSQ1(0);
203             lengthcount[x]=lengthtable[(V>>3)&0x1f];
204             sqnon|=1<<x;
205            }
206
207            sweepon[x]=PSG[(x<<2)|1]&0x80;
208            curfreq[x]=PSG[(x<<2)|0x2]|((V&7)<<8);
209            decvolume[x]=0xF;
210            SweepCount[x]=((PSG[(x<<2)|0x1]>>4)&7)+1;
211            DutyCount[x]=0;
212            sqacc[x]=((int32)curfreq[0]+1)<<18;
213
214            //RectDutyCount[x]=7;
215            //EnvUnits[x].reloaddec=1;
216            //reloadfreq[x]=1;
217 }
218
219 static DECLFW(Write_PSG)
220 {
221  //if((A>=0x4004 && A<=0x4007) || A==0x4015)
222   //printf("$%04x:$%02x, %d\n",A,V,SOUNDTS);
223  A&=0x1f;
224  switch(A)
225  {
226   case 0x0:
227            DoSQ1(0);
228            if(V&0x10)
229             realvolume[0]=V&0xF;
230            break;
231   case 0x1:
232            sweepon[0]=V&0x80;
233            break;
234   case 0x2:
235            DoSQ1(0);
236            curfreq[0]&=0xFF00;
237            curfreq[0]|=V;
238            break;
239   case 0x3:
240            SQReload(0,V);
241            break;
242
243   case 0x4:
244            DoSQ2(0);
245            if(V&0x10)
246             realvolume[1]=V&0xF;
247            break;
248   case 0x5:
249           sweepon[1]=V&0x80;
250           break;
251   case 0x6:
252           DoSQ2(0);
253           curfreq[1]&=0xFF00;
254           curfreq[1]|=V;
255           break;
256   case 0x7:
257           SQReload(1,V);
258           break;
259   case 0x8:
260           DoTriangle(0);
261           if(laster&0x80)
262           {
263             tricoop=V&0x7F;
264             trimode=V&0x80;
265           }
266           if(!(V&0x7F))
267            tricoop=0;
268           laster=V&0x80;
269           break;
270   case 0xa:DoTriangle(0);
271            break;
272   case 0xb:
273           if(EnabledChannels&0x4)
274           {
275            DoTriangle(0);
276            sqnon|=4;
277            lengthcount[2]=lengthtable[(V>>3)&0x1f];
278           }
279           laster=0x80;
280           tricoop=PSG[0x8]&0x7f;
281           trimode=PSG[0x8]&0x80;
282           break;
283   case 0xC:DoNoise(0);
284            if(V&0x10)
285             realvolume[2]=V&0xF;
286            break;
287   case 0xE:DoNoise(0);break;
288   case 0xF:
289            if(EnabledChannels&8)
290            {
291             DoNoise(0);
292             sqnon|=8;
293             lengthcount[3]=lengthtable[(V>>3)&0x1f];
294            }
295            decvolume[2]=0xF;
296            DecCountTo1[2]=(PSG[0xC]&0xF)+1;
297            break;
298  }
299  PSG[A]=V;
300 }
301
302 static DECLFW(Write_DMCRegs)
303 {
304  A&=0xF;
305
306  switch(A)
307  {
308   case 0x00:DoPCM(0);
309             LoadDMCPeriod(V&0xF);
310
311             if(SIRQStat&0x80)
312             {
313              if(!(V&0x80))
314              {
315               X6502_IRQEnd(FCEU_IQDPCM);
316               SIRQStat&=~0x80;
317              }
318              else X6502_IRQBegin(FCEU_IQDPCM);
319             }
320             DMCFormat=V;
321             break;
322   case 0x01:DoPCM(0);
323             RawDALatch=V&0x7F;
324             break;
325   case 0x02:DMCAddressLatch=V;break;
326   case 0x03:DMCSizeLatch=V;break;
327  }
328 }
329
330 static DECLFW(StatusWrite)
331 {
332         int x;
333         int32 end=(SOUNDTS<<16)/soundtsinc;
334         int t=V^EnabledChannels;
335
336             if(t&1)
337              DoSQ1(end);
338             if(t&2)
339              DoSQ2(end);
340             if(t&4)
341              DoTriangle(end);
342             if(t&8)
343              DoNoise(end);
344             if(t&0x10)
345              DoPCM(end);
346             sqnon&=V;
347         for(x=0;x<4;x++)
348          if(!(V&(1<<x))) lengthcount[x]=0;   /* Force length counters to 0. */
349
350         if(V&0x10)
351         {
352          if(!DMCSize)
353           PrepDPCM();
354         }
355         else
356         {
357          DMCSize=0;
358         }
359         SIRQStat&=~0x80;
360         X6502_IRQEnd(FCEU_IQDPCM);
361         EnabledChannels=V&0x1F;
362 }
363
364 DECLFR(StatusRead)
365 {
366    //int x;
367    uint8 ret;
368
369    ret=SIRQStat;
370
371    //for(x=0;x<4;x++) ret|=lengthcount[x]?(1<<x):0;
372    ret|=EnabledChannels&sqnon;
373    if(DMCSize) ret|=0x10;
374
375    #ifdef FCEUDEF_DEBUGGER
376    if(!fceuindbg)
377    #endif
378    {
379     SIRQStat&=~0x40;
380     X6502_IRQEnd(FCEU_IQFCOUNT);
381    }
382    return ret;
383 }
384
385 static void FASTAPASS(1) FrameSoundStuff(int V)
386 {
387  int P;
388  uint32 end = (SOUNDTS<<16)/soundtsinc;
389
390  DoSQ1(end);
391  DoSQ2(end);
392  DoNoise(end);
393
394  switch((V&1))
395  {
396   case 1:       /* Envelope decay, linear counter, length counter, freq sweep */
397         if(EnabledChannels&4 && sqnon&4)
398          if(!(PSG[8]&0x80))
399          {
400           if(lengthcount[2]>0)
401           {
402             lengthcount[2]--;
403             if(lengthcount[2]<=0)
404              {
405               DoTriangle(0);
406               sqnon&=~4;
407              }
408            }
409          }
410
411         for(P=0;P<2;P++)
412         {
413          if(EnabledChannels&(P+1) && sqnon&(P+1))
414          {
415           if(!(PSG[P<<2]&0x20))
416           {
417            if(lengthcount[P]>0)
418            {
419             lengthcount[P]--;
420             if(lengthcount[P]<=0)
421              {
422               sqnon&=~(P+1);
423              }
424            }
425           }
426          }
427                 /* Frequency Sweep Code Here */
428                 /* xxxx 0000 */
429                 /* xxxx = hz.  120/(x+1)*/
430           if(sweepon[P])
431           {
432            int32 mod=0;
433
434            if(SweepCount[P]>0) SweepCount[P]--;
435            if(SweepCount[P]<=0)
436            {
437             SweepCount[P]=((PSG[(P<<2)+0x1]>>4)&7)+1; //+1;
438             {
439              if(PSG[(P<<2)+0x1]&0x8)
440              {
441               mod-=(P^1)+((curfreq[P])>>(PSG[(P<<2)+0x1]&7));
442
443               if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
444               {
445                curfreq[P]+=mod;
446               }
447              }
448              else
449              {
450               mod=curfreq[P]>>(PSG[(P<<2)+0x1]&7);
451               if((mod+curfreq[P])&0x800)
452               {
453                sweepon[P]=0;
454                curfreq[P]=0;
455               }
456               else
457               {
458                if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
459                {
460                 curfreq[P]+=mod;
461                }
462               }
463              }
464             }
465            }
466           }
467          }
468
469        if(EnabledChannels&0x8 && sqnon&8)
470         {
471          if(!(PSG[0xC]&0x20))
472          {
473           if(lengthcount[3]>0)
474           {
475            lengthcount[3]--;
476            if(lengthcount[3]<=0)
477            {
478             sqnon&=~8;
479            }
480           }
481          }
482         }
483
484   case 0:       /* Envelope decay + linear counter */
485          if(!trimode)
486          {
487            laster=0;
488            if(tricoop)
489            {
490             if(tricoop==1) DoTriangle(0);
491             tricoop--;
492            }
493          }
494
495         for(P=0;P<2;P++)
496         {
497           if(DecCountTo1[P]>0) DecCountTo1[P]--;
498           if(DecCountTo1[P]<=0)
499           {
500            DecCountTo1[P]=(PSG[P<<2]&0xF)+1;
501            if(decvolume[P] || PSG[P<<2]&0x20)
502            {
503             decvolume[P]--;
504             /* Step from 0 to full volume seems to take twice as long
505                as the other steps.  I don't know if this is the correct
506                way to double its length, though(or if it even matters).
507             */
508             if((PSG[P<<2]&0x20) && (decvolume[P]==0))
509              DecCountTo1[P]<<=1;
510             decvolume[P]&=15;
511            }
512           }
513           if(!(PSG[P<<2]&0x10))
514            realvolume[P]=decvolume[P];
515         }
516
517          if(DecCountTo1[2]>0) DecCountTo1[2]--;
518          if(DecCountTo1[2]<=0)
519          {
520           DecCountTo1[2]=(PSG[0xC]&0xF)+1;
521           if(decvolume[2] || PSG[0xC]&0x20)
522           {
523             decvolume[2]--;
524             /* Step from 0 to full volume seems to take twice as long
525                as the other steps.  I don't know if this is the correct
526                way to double its length, though(or if it even matters).
527             */
528             if((PSG[0xC]&0x20) && (decvolume[2]==0))
529              DecCountTo1[2]<<=1;
530             decvolume[2]&=15;
531           }
532          }
533          if(!(PSG[0xC]&0x10))
534           realvolume[2]=decvolume[2];
535
536         break;
537  }
538
539 }
540
541 void FrameSoundUpdate(void)
542 {
543  // Linear counter:  Bit 0-6 of $4008
544  // Length counter:  Bit 4-7 of $4003, $4007, $400b, $400f
545
546  if(!fcnt && !(IRQFrameMode&0x3))
547  {
548          SIRQStat|=0x40;
549          X6502_IRQBegin(FCEU_IQFCOUNT);
550  }
551
552  if(fcnt==3)
553  {
554         if(IRQFrameMode&0x2)
555          fhcnt+=fhinc;
556  }
557  FrameSoundStuff(fcnt);
558  fcnt=(fcnt+1)&3;
559 }
560
561 static INLINE void tester(void)
562 {
563  if(DMCBitCount==0)
564  {
565   if(!DMCHaveDMA)
566    DMCHaveSample=0;
567   else
568   {
569    DMCHaveSample=1;
570    DMCShift=DMCDMABuf;
571    DMCHaveDMA=0;
572   }
573  }
574 }
575
576 static uint32 ChannelBC[5];
577
578 static uint32 RectAmp[2][8];
579
580 static void FASTAPASS(1) CalcRectAmp(int P)
581 {
582   static int tal[4]={1,2,4,6};
583   int V;
584   int x;
585   uint32 *b=RectAmp[P];
586   int m;
587
588   //if(PSG[P<<2]&0x10)
589    V=realvolume[P]<<4;
590   //V=(PSG[P<<2]&15)<<4;
591   //else
592   // V=decvolume[P]<<4;
593   m=tal[(PSG[P<<2]&0xC0)>>6];
594   for(x=0;x<m;x++,b++)
595    *b=0;
596   for(;x<8;x++,b++)
597    *b=V;
598 }
599
600 static INLINE void DMCDMA(void)
601 {
602   if(DMCSize && !DMCHaveDMA)
603   {
604 #if 0
605    X6502_DMR(0x8000+DMCAddress);
606    X6502_DMR(0x8000+DMCAddress);
607    X6502_DMR(0x8000+DMCAddress);
608    DMCDMABuf=X6502_DMR(0x8000+DMCAddress);
609 #else
610    X6502_AddCycles(4);
611    DMCDMABuf=X.DB=ARead[0x8000+DMCAddress](0x8000+DMCAddress);
612 #endif
613    DMCHaveDMA=1;
614    DMCAddress=(DMCAddress+1)&0x7fff;
615    DMCSize--;
616    if(!DMCSize)
617    {
618     if(DMCFormat&0x40)
619      PrepDPCM();
620     else
621     {
622      SIRQStat|=0x80;
623      if(DMCFormat&0x80)
624       X6502_IRQBegin(FCEU_IQDPCM);
625     }
626    }
627  }
628 }
629
630 void FCEU_SoundCPUHook(int cycles48)
631 {
632  fhcnt-=cycles48;
633  if(fhcnt<=0)
634  {
635   FrameSoundUpdate();
636   fhcnt+=fhinc;
637  }
638
639  DMCDMA();
640  DMCacc-=cycles48/48;
641
642  while(DMCacc<=0)
643  {
644   if(DMCHaveSample)
645   {
646    uint8 bah=RawDALatch;
647    int t=((DMCShift&1)<<2)-2;
648
649    /* Unbelievably ugly hack */
650    if(FSettings.SndRate)
651    {
652     soundtsoffs+=DMCacc;
653     DoPCM(0);
654     soundtsoffs-=DMCacc;
655    }
656    RawDALatch+=t;
657    if(RawDALatch&0x80)
658     RawDALatch=bah;
659   }
660
661   DMCacc+=DMCPeriod;
662   DMCBitCount=(DMCBitCount+1)&7;
663   DMCShift>>=1;
664   tester();
665  }
666 }
667
668 static void RDoPCM(int32 end)
669 {
670  int32 V;
671  int32 start;
672
673  start=ChannelBC[4];
674  if(end==0) end=(SOUNDTS<<16)/soundtsinc;
675  if(end<=start) return;
676  ChannelBC[4]=end;
677
678  for(V=start;V<end;V++)
679   //WaveHi[V]+=(((RawDALatch<<16)/256) * FSettings.PCMVolume)&(~0xFFFF); // TODO get rid of floating calculations to binary. set log volume scaling.
680   Wave[V>>4]+=RawDALatch<<3;
681 }
682
683 static void RDoSQ1(int32 end)
684 {
685    int32 V;
686    int32 start;
687    int32 freq;
688
689    start=ChannelBC[0];
690    if(end==0) end=(SOUNDTS<<16)/soundtsinc;
691    if(end<=start) return;
692    ChannelBC[0]=end;
693
694    if(!(EnabledChannels&1 && sqnon&1))
695     return;
696
697    if(curfreq[0]<8 || curfreq[0]>0x7ff)
698     return;
699    if(!CheckFreq(curfreq[0],PSG[0x1]))
700     return;
701
702    CalcRectAmp(0);
703
704    {
705     uint32 out=RectAmp[0][DutyCount[0]];
706     freq=curfreq[0]+1;
707     {
708       freq<<=18;
709       for(V=start;V<end;V++)
710       {
711        Wave[V>>4]+=out;
712        sqacc[0]-=nesincsize;
713        if(sqacc[0]<=0)
714        {
715         rea:
716         sqacc[0]+=freq;
717         DutyCount[0]++;
718         if(sqacc[0]<=0) goto rea;
719
720         DutyCount[0]&=7;
721         out=RectAmp[0][DutyCount[0]];
722        }
723       }
724     }
725    }
726 }
727
728 static void RDoSQ2(int32 end)
729 {
730    int32 V;
731    int32 start;
732    int32 freq;
733
734    start=ChannelBC[1];
735    if(end==0) end=(SOUNDTS<<16)/soundtsinc;
736    if(end<=start) return;
737    ChannelBC[1]=end;
738
739    if(!(EnabledChannels&2 && sqnon&2))
740     return;
741
742    if(curfreq[1]<8 || curfreq[1]>0x7ff)
743     return;
744    if(!CheckFreq(curfreq[1],PSG[0x5]))
745     return;
746
747    CalcRectAmp(1);
748
749    {
750     uint32 out=RectAmp[1][DutyCount[1]];
751     freq=curfreq[1]+1;
752
753     {
754       freq<<=18;
755       for(V=start;V<end;V++)
756       {
757        Wave[V>>4]+=out;
758        sqacc[1]-=nesincsize;
759        if(sqacc[1]<=0)
760        {
761         rea:
762         sqacc[1]+=freq;
763         DutyCount[1]++;
764         if(sqacc[1]<=0) goto rea;
765
766         DutyCount[1]&=7;
767         out=RectAmp[1][DutyCount[1]];
768        }
769       }
770     }
771    }
772 }
773
774
775 static void RDoTriangle(int32 end)
776 {
777    static uint32 tcout=0;
778    int32 V;
779    int32 start; //,freq;
780    int32 freq=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1));
781
782    start=ChannelBC[2];
783    if(end==0) end=(SOUNDTS<<16)/soundtsinc;
784    if(end<=start) return;
785    ChannelBC[2]=end;
786
787     if(! (EnabledChannels&0x4 && sqnon&4 && tricoop) )
788     {   // Counter is halted, but we still need to output.
789      for(V=start;V<end;V++)
790        Wave[V>>4]+=tcout;
791     }
792     else if(freq<=4) // 55.9Khz - Might be barely audible on a real NES, but
793                // it's too costly to generate audio at this high of a frequency
794                // (55.9Khz * 32 for the stepping).
795                // The same could probably be said for ~27.8Khz, so we'll
796                // take care of that too.  We'll just output the average
797                // value(15/2 - scaled properly for our output format, of course).
798                // We'll also take care of ~18Khz and ~14Khz too, since they should be barely audible.
799                // (Some proof or anything to confirm/disprove this would be nice.).
800     {
801      for(V=start;V<end;V++)
802       Wave[V>>4]+=((0xF<<4)+(0xF<<2))>>1;
803     }
804     else
805     {
806      static int32 triacc=0;
807      static uint8 tc=0;
808
809       freq<<=17;
810       for(V=start;V<end;V++)
811       {
812        triacc-=nesincsize;
813        if(triacc<=0)
814        {
815         rea:
816         triacc+=freq; //t;
817         tc=(tc+1)&0x1F;
818         if(triacc<=0) goto rea;
819
820         tcout=(tc&0xF);
821         if(tc&0x10) tcout^=0xF;
822         tcout=(tcout<<4)+(tcout<<2);
823        }
824        Wave[V>>4]+=tcout;
825       }
826     }
827 }
828
829 static void RDoNoise(int32 end)
830 {
831    int32 inc,V;
832    int32 start;
833
834    start=ChannelBC[3];
835    if(end==0) end=(SOUNDTS<<16)/soundtsinc;
836    if(end<=start) return;
837    ChannelBC[3]=end;
838
839    if(EnabledChannels&0x8 && sqnon&8)
840    {
841       uint32 outo;
842       uint32 amptab[2];
843       uint8 amplitude;
844
845       amplitude=realvolume[2];
846       //if(PSG[0xC]&0x10)
847       // amplitude=(PSG[0xC]&0xF);
848       //else
849       // amplitude=decvolume[2]&0xF;
850
851       inc=NoiseFreqTable[PSG[0xE]&0xF];
852       amptab[0]=((amplitude<<2)+amplitude+amplitude)<<1;
853       amptab[1]=0;
854       outo=amptab[nreg&1];
855
856       if(amplitude)
857       {
858        if(PSG[0xE]&0x80)        // "short" noise
859         for(V=start;V<end;V++)
860         {
861          Wave[V>>4]+=outo;
862          if(count[3]>=inc)
863          {
864           uint8 feedback;
865
866           feedback=((nreg>>8)&1)^((nreg>>14)&1);
867           nreg=(nreg<<1)+feedback;
868           nreg&=0x7fff;
869           outo=amptab[nreg&1];
870           count[3]-=inc;
871          }
872          count[3]+=0x1000;
873         }
874        else
875         for(V=start;V<end;V++)
876         {
877          Wave[V>>4]+=outo;
878          if(count[3]>=inc)
879          {
880           uint8 feedback;
881
882           feedback=((nreg>>13)&1)^((nreg>>14)&1);
883           nreg=(nreg<<1)+feedback;
884           nreg&=0x7fff;
885           outo=amptab[nreg&1];
886           count[3]-=inc;
887          }
888          count[3]+=0x1000;
889         }
890       }
891    }
892 }
893
894 DECLFW(Write_IRQFM)
895 {
896  V=(V&0xC0)>>6;
897  fcnt=0;
898  if(V&0x2)
899   FrameSoundUpdate();
900  fcnt=1;
901  fhcnt=fhinc;
902  X6502_IRQEnd(FCEU_IQFCOUNT);
903  SIRQStat&=~0x40;
904  IRQFrameMode=V;
905 }
906
907 void SetNESSoundMap(void)
908 {
909   SetWriteHandler(0x4000,0x400F,Write_PSG);
910   SetWriteHandler(0x4010,0x4013,Write_DMCRegs);
911   SetWriteHandler(0x4017,0x4017,Write_IRQFM);
912
913   SetWriteHandler(0x4015,0x4015,StatusWrite);
914   SetReadHandler(0x4015,0x4015,StatusRead);
915 }
916
917 int32 highp;                   // 0 through 65536, 0 = no high pass, 65536 = max high pass
918
919 int32 lowp;                    // 0 through 65536, 65536 = max low pass(total attenuation)
920                                 // 65536 = no low pass
921 static int32 flt_acc=0, flt_acc2=0;
922
923 static void FilterSound(uint32 *in, int16 *outMono, int count)
924 {
925 // static int min=0, max=0;
926  int sh=2;
927  if (soundvol < 5) sh += 5 - soundvol;
928
929  for(;count;count--,in++,outMono++)
930  {
931   int32 diff;
932
933   diff = *in - flt_acc;
934
935   flt_acc += (diff*highp)>>16;
936   flt_acc2+= (int32) (((int64)((diff-flt_acc2)*lowp))>>16);
937   *in=0;
938
939   *outMono = flt_acc2*7 >> sh; // * 7 >> 2 = * 1.75
940 //  if (acc2 < min) { printf("min: %i %04x\n", acc2, acc2); min = acc2; }
941 //  if (acc2 > max) { printf("max: %i %04x\n", acc2, acc2); max = acc2; }
942  }
943 }
944
945
946
947 static int32 inbuf=0;
948 int FlushEmulateSound(void)
949 {
950   int x;
951   uint32 end;
952
953   if(!timestamp) return(0);
954
955   if(!FSettings.SndRate || (soundvol == 0))
956   {
957    end=0;
958    goto nosoundo;
959   }
960
961   end=(SOUNDTS<<16)/soundtsinc;
962   DoSQ1(end);
963   DoSQ2(end);
964   DoTriangle(end);
965   DoNoise(end);
966   DoPCM(end);
967
968   if(GameExpSound.Fill)
969    GameExpSound.Fill(end&0xF);
970
971   FilterSound(Wave,WaveFinalMono,end>>4);
972
973   if(end&0xF)
974    Wave[0]=Wave[(end>>4)];
975   Wave[(end>>4)]=0;
976
977   nosoundo:
978   for(x=0;x<5;x++)
979    ChannelBC[x]=end&0xF;
980   soundtsoffs=(soundtsinc*(end&0xF))>>16;
981   end>>=4;
982   inbuf=end;
983   return(end);
984 }
985
986 int GetSoundBuffer(int16 **W)
987 {
988  *W=WaveFinalMono;
989  return inbuf;
990 }
991
992 void FCEUSND_Power(void)
993 {
994         int x;
995
996         SetNESSoundMap();
997         memset(PSG,0x00,sizeof(PSG));
998         FCEUSND_Reset();
999
1000         memset(Wave,0,sizeof(Wave));
1001         memset(WaveHi,0,sizeof(WaveHi));
1002         //memset(&EnvUnits,0,sizeof(EnvUnits));
1003
1004         for(x=0;x<5;x++)
1005          ChannelBC[x]=0;
1006         soundtsoffs=0;
1007         LoadDMCPeriod(DMCFormat&0xF);
1008 }
1009
1010 void FCEUSND_Reset(void)
1011 {
1012         int x;
1013         for(x=0;x<0x16;x++)
1014          if(x!=1 && x!=5 && x!=0x14) BWrite[0x4000+x](0x4000+x,0);
1015
1016         IRQFrameMode=0x0;
1017         fhcnt=fhinc;
1018         fcnt=0;
1019         nreg=1;
1020
1021         DMCHaveDMA=DMCHaveSample=0;
1022         SIRQStat=0x00;
1023
1024         RawDALatch=0x00;
1025         //TriCount=0;
1026         //TriMode=0;
1027         //tristep=0;
1028         EnabledChannels=0;
1029         for(x=0;x<4;x++)
1030          lengthcount[x]=0;
1031
1032         DMCAddressLatch=0;
1033         DMCSizeLatch=0;
1034         DMCFormat=0;
1035         DMCAddress=0;
1036         DMCSize=0;
1037         DMCShift=0;
1038         DMCacc=1;
1039         DMCBitCount=0;
1040 }
1041
1042 void SetSoundVariables(void)
1043 {
1044   int x;
1045
1046   fhinc=PAL?16626:14915;        // *2 CPU clock rate
1047   fhinc*=24;
1048   for(x=0;x<0x20;x++)
1049    lengthtable[x]=Slengthtable[x]<<1;
1050
1051   if(FSettings.SndRate)
1052   {
1053    DoNoise=RDoNoise;
1054    DoTriangle=RDoTriangle;
1055    DoPCM=RDoPCM;
1056    DoSQ1=RDoSQ1;
1057    DoSQ2=RDoSQ2;
1058   }
1059   else
1060   {
1061    DoNoise=DoTriangle=DoPCM=DoSQ1=DoSQ2=Dummyfunc;
1062   }
1063
1064   if(!FSettings.SndRate) return;
1065   if(GameExpSound.RChange)
1066    GameExpSound.RChange();
1067
1068   // nesincsizeLL=(int64)((int64)562949953421312*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE));
1069   nesincsize=(int32)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16)); // 308845 - 1832727
1070   PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16);
1071
1072   for(x=0;x<0x10;x++)
1073   {
1074    long double z;
1075    z=SNoiseFreqTable[x]<<1;
1076    z=(PAL?PAL_CPU:NTSC_CPU)/z;
1077    z=(long double)((uint32)((FSettings.SndRate OVERSAMPLE)<<12))/z;
1078    NoiseFreqTable[x]=z;
1079   }
1080   soundtsinc=(uint32)((uint64)(PAL?(long double)PAL_CPU*65536:(long double)NTSC_CPU*65536)/(FSettings.SndRate OVERSAMPLE));
1081   memset(Wave,0,sizeof(Wave));
1082   for(x=0;x<5;x++)
1083    ChannelBC[x]=0;
1084   highp=(250<<16)/FSettings.SndRate;  // Arbitrary
1085   lowp=(25000<<16)/FSettings.SndRate; // Arbitrary
1086
1087   if(highp>(1<<16)) highp=1<<16;
1088   if(lowp>(1<<16)) lowp=1<<16;
1089
1090   flt_acc=flt_acc2=0;
1091 }
1092
1093 void FixOldSaveStateSFreq(void)
1094 {
1095         int x;
1096         for(x=0;x<2;x++)
1097         {
1098          curfreq[x]=PSG[0x2+(x<<2)]|((PSG[0x3+(x<<2)]&7)<<8);
1099         }
1100 }
1101
1102 void FCEUI_Sound(int Rate)
1103 {
1104  FSettings.SndRate=Rate;
1105  SetSoundVariables();
1106 }
1107
1108 void FCEUI_SetSoundVolume(uint32 volume)
1109 {
1110  FSettings.SoundVolume=volume;
1111 }
1112
1113 SFORMAT FCEUSND_STATEINFO[]={
1114  { &fhcnt, 4|FCEUSTATE_RLSB,"FHCN"},
1115  { &fcnt, 1, "FCNT"},
1116  { PSG, 0x10, "PSG"},
1117  { &EnabledChannels, 1, "ENCH"},
1118  { &IRQFrameMode, 1, "IQFM"},
1119
1120  { decvolume, 3, "DECV"},
1121  { &sqnon, 1, "SQNO"},
1122  { &nreg, 2|RLSB, "NREG"},
1123  { &trimode, 1, "TRIM"},
1124  { &tricoop, 1, "TRIC"},
1125  { DecCountTo1, 3,"DCT1"},
1126
1127  { sweepon, 2, "SWEE"},
1128  { &curfreq[0], 4|FCEUSTATE_RLSB,"CRF1"},
1129  { &curfreq[1], 4|FCEUSTATE_RLSB,"CRF2"},
1130  { SweepCount, 2,"SWCT"},
1131
1132  { &SIRQStat, 1, "SIRQ"},
1133
1134  { &DMCacc, 4|FCEUSTATE_RLSB, "5ACC"},
1135  { &DMCBitCount, 1, "5BIT"},
1136  { &DMCAddress, 4|FCEUSTATE_RLSB, "5ADD"},
1137  { &DMCSize, 4|FCEUSTATE_RLSB, "5SIZ"},
1138  { &DMCShift, 1, "5SHF"},
1139
1140  { &DMCHaveDMA, 1, "5HVDM"},
1141  { &DMCHaveSample, 1, "5HVSP"},
1142
1143  { &DMCSizeLatch, 1, "5SZL"},
1144  { &DMCAddressLatch, 1, "5ADL"},
1145  { &DMCFormat, 1, "5FMT"},
1146  { &RawDALatch, 1, "RWDA"},
1147  { 0, }
1148 };
1149
1150 void FCEUSND_SaveState(void)
1151 {
1152
1153 }
1154
1155 void FCEUSND_LoadState(int version)
1156 {
1157  LoadDMCPeriod(DMCFormat&0xF);
1158  RawDALatch&=0x7F;
1159  DMCAddress&=0x7FFF;
1160 }