1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Ben Parnell
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.
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.
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
23 #define vrctemp mapbyte1[0]
24 #define regb000 mapbyte3[0]
25 #define regb001 mapbyte3[1]
26 #define regb002 mapbyte3[2]
27 #define exchstat mapbyte4[0]
28 #define VPSG2 mapbyte3
31 static void DoSQV1(void);
32 static void DoSQV2(void);
33 static void DoSawV(void);
37 static DECLFW(VRC6PSGW90)
41 static DECLFW(VRC6PSGW91)
45 static DECLFW(VRC6PSGW92)
49 static DECLFW(VRC6PSGWA0)
53 static DECLFW(VRC6PSGWA1)
57 static DECLFW(VRC6PSGWA2)
61 static DECLFW(VRC6PSGWB0)
65 static DECLFW(VRC6PSGWB1)
69 static DECLFW(VRC6PSGWB2)
76 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
84 doagainbub:acount-=LCYCS;IRQCount++;
85 if(IRQCount==0x100) {TriggerIRQ();IRQCount=IRQLatch;}
86 if(acount>=LCYCS) goto doagainbub;
91 DECLFW(Mapper24_write)
94 A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
98 case 0x8000:ROM_BANK16(0x8000,V);break;
102 case 0x0:MIRROR_SET2(1);break;
103 case 0x4:MIRROR_SET2(0);break;
104 case 0x8:onemir(0);break;
105 case 0xC:onemir(1);break;
108 case 0xC000:ROM_BANK8(0xC000,V);break;
109 case 0xD000:VROM_BANK1(0x0000,V);break;
110 case 0xD001:VROM_BANK1(0x0400,V);break;
111 case 0xD002:VROM_BANK1(0x0800,V);break;
112 case 0xD003:VROM_BANK1(0x0c00,V);break;
113 case 0xE000:VROM_BANK1(0x1000,V);break;
114 case 0xE001:VROM_BANK1(0x1400,V);break;
115 case 0xE002:VROM_BANK1(0x1800,V);break;
116 case 0xE003:VROM_BANK1(0x1c00,V);break;
117 case 0xF000:IRQLatch=V;break;
118 case 0xF001:IRQa=V&2;
120 if(V&2) {IRQCount=IRQLatch;}
123 case 0xf002:IRQa=vrctemp;break;
128 static int CVBC[3]={0,0,0};
129 static int32 vcount[2];
131 static void DoSQV1(void)
139 end=(timestamp<<16)/soundtsinc;
140 if(end<=start) return;
148 for(V=start;V<end;V++)
154 freq=(((VPSG[0x2]|((VPSG[0x3]&15)<<8))+1));
155 inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
159 case 0x00:dcycs=inc>>4;break;
160 case 0x10:dcycs=inc>>3;break;
161 case 0x20:dcycs=(inc*3)>>4;break;
162 case 0x30:dcycs=inc>>2;break;
163 case 0x40:dcycs=(inc*5)>>4;break;
164 case 0x50:dcycs=(inc*6)>>4;break;
165 case 0x60:dcycs=(inc*7)>>4;break;
166 case 0x70:dcycs=inc>>1;break;
168 for(V=start;V<end;V++)
173 if(vcount[0]>=inc) vcount[0]-=inc;
178 static void DoSQV2(void)
186 end=(timestamp<<16)/soundtsinc;
187 if(end<=start) return;
195 for(V=start;V<end;V++)
201 freq=(((VPSG[0x6]|((VPSG[0x7]&15)<<8))+1));
202 inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
206 case 0x00:dcycs=inc>>4;break;
207 case 0x10:dcycs=inc>>3;break;
208 case 0x20:dcycs=(inc*3)>>4;break;
209 case 0x30:dcycs=inc>>2;break;
210 case 0x40:dcycs=(inc*5)>>4;break;
211 case 0x50:dcycs=(inc*6)>>4;break;
212 case 0x60:dcycs=(inc*7)>>4;break;
213 case 0x70:dcycs=inc>>1;break;
215 for(V=start;V<end;V++)
220 if(vcount[1]>=inc) vcount[1]-=inc;
226 static void DoSawV(void)
232 end=(timestamp<<16)/soundtsinc;
233 if(end<=start) return;
238 static int64 saw1phaseacc=0;
241 static int32 phaseacc=0;
242 static uint32 duff=0;
244 freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
246 for(V=start;V<end;V++)
248 saw1phaseacc-=nesincsizeLL;
256 phaseacc+=VPSG2[0]&0x3f;
265 duff=(((phaseacc>>3)&0x1f)<<4);
272 void VRC6Sound(int Count)
285 void VRC6SoundC(void)
289 if(FSettings.SndRate)
293 for(x=000;x<0x1000;x+=4)
295 SetWriteHandler(0x9000+x,0x9002+x,0);
296 SetWriteHandler(0xa000+x,0xa002+x,0);
297 SetWriteHandler(0xb000+x,0xb002+x,0);
308 GameExpSound.RChange=VRC6SoundC;
309 GameExpSound.Fill=VRC6Sound;
310 if(FSettings.SndRate)
311 for(x=000;x<0x1000;x+=4)
316 SetWriteHandler(a,a,VRC6PSGW90);
317 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGW91);
318 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGW92);
321 SetWriteHandler(a,a,VRC6PSGWA0);
322 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWA1);
323 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWA2);
326 SetWriteHandler(a,a,VRC6PSGWB0);
327 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWB1);
328 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWB2);
332 void Mapper24_init(void)
334 SetWriteHandler(0x8000,0xffff,Mapper24_write);
335 if(FSettings.SndRate)
337 GameExpSound.RChange=VRC6SoundC;
338 MapIRQHook=KonamiIRQHook;
342 void Mapper26_init(void)
344 SetWriteHandler(0x8000,0xffff,Mapper24_write);
345 if(FSettings.SndRate)
347 GameExpSound.RChange=VRC6SoundC;
348 MapIRQHook=KonamiIRQHook;