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);
103 case 0x0:MIRROR_SET2(1);break;
104 case 0x4:MIRROR_SET2(0);break;
105 case 0x8:onemir(0);break;
106 case 0xC:onemir(1);break;
109 case 0xC000:ROM_BANK8(0xC000,V);
110 X6502_Rebase();break;
111 case 0xD000:VROM_BANK1(0x0000,V);break;
112 case 0xD001:VROM_BANK1(0x0400,V);break;
113 case 0xD002:VROM_BANK1(0x0800,V);break;
114 case 0xD003:VROM_BANK1(0x0c00,V);break;
115 case 0xE000:VROM_BANK1(0x1000,V);break;
116 case 0xE001:VROM_BANK1(0x1400,V);break;
117 case 0xE002:VROM_BANK1(0x1800,V);break;
118 case 0xE003:VROM_BANK1(0x1c00,V);break;
119 case 0xF000:IRQLatch=V;break;
120 case 0xF001:IRQa=V&2;
122 if(V&2) {IRQCount=IRQLatch;}
125 case 0xf002:IRQa=vrctemp;break;
130 static int CVBC[3]={0,0,0};
131 static int32 vcount[2];
133 static void DoSQV1(void)
141 end=(SOUNDTS<<16)/soundtsinc;
142 if(end<=start) return;
150 for(V=start;V<end;V++)
156 freq=(((VPSG[0x2]|((VPSG[0x3]&15)<<8))+1));
157 inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
161 case 0x00:dcycs=inc>>4;break;
162 case 0x10:dcycs=inc>>3;break;
163 case 0x20:dcycs=(inc*3)>>4;break;
164 case 0x30:dcycs=inc>>2;break;
165 case 0x40:dcycs=(inc*5)>>4;break;
166 case 0x50:dcycs=(inc*6)>>4;break;
167 case 0x60:dcycs=(inc*7)>>4;break;
168 case 0x70:dcycs=inc>>1;break;
170 for(V=start;V<end;V++)
175 if(vcount[0]>=inc) vcount[0]-=inc;
180 static void DoSQV2(void)
188 end=(SOUNDTS<<16)/soundtsinc;
189 if(end<=start) return;
197 for(V=start;V<end;V++)
203 freq=(((VPSG[0x6]|((VPSG[0x7]&15)<<8))+1));
204 inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq);
208 case 0x00:dcycs=inc>>4;break;
209 case 0x10:dcycs=inc>>3;break;
210 case 0x20:dcycs=(inc*3)>>4;break;
211 case 0x30:dcycs=inc>>2;break;
212 case 0x40:dcycs=(inc*5)>>4;break;
213 case 0x50:dcycs=(inc*6)>>4;break;
214 case 0x60:dcycs=(inc*7)>>4;break;
215 case 0x70:dcycs=inc>>1;break;
217 for(V=start;V<end;V++)
222 if(vcount[1]>=inc) vcount[1]-=inc;
228 static void DoSawV(void)
234 end=(SOUNDTS<<16)/soundtsinc;
235 if(end<=start) return;
240 static int64 saw1phaseacc=0;
243 static int32 phaseacc=0;
244 static uint32 duff=0;
246 freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
248 for(V=start;V<end;V++)
250 saw1phaseacc-=nesincsizeLL;
258 phaseacc+=VPSG2[0]&0x3f;
267 duff=(((phaseacc>>3)&0x1f)<<4);
274 void VRC6Sound(int Count)
287 void VRC6SoundC(void)
291 if(FSettings.SndRate)
295 for(x=000;x<0x1000;x+=4)
297 SetWriteHandler(0x9000+x,0x9002+x,0);
298 SetWriteHandler(0xa000+x,0xa002+x,0);
299 SetWriteHandler(0xb000+x,0xb002+x,0);
310 GameExpSound.RChange=VRC6SoundC;
311 GameExpSound.Fill=VRC6Sound;
312 if(FSettings.SndRate)
313 for(x=000;x<0x1000;x+=4)
318 SetWriteHandler(a,a,VRC6PSGW90);
319 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGW91);
320 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGW92);
323 SetWriteHandler(a,a,VRC6PSGWA0);
324 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWA1);
325 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWA2);
328 SetWriteHandler(a,a,VRC6PSGWB0);
329 SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWB1);
330 SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWB2);
334 void Mapper24_init(void)
336 SetWriteHandler(0x8000,0xffff,Mapper24_write);
337 if(FSettings.SndRate)
339 GameExpSound.RChange=VRC6SoundC;
340 MapIRQHook=KonamiIRQHook;
344 void Mapper26_init(void)
346 SetWriteHandler(0x8000,0xffff,Mapper24_write);
347 if(FSettings.SndRate)
349 GameExpSound.RChange=VRC6SoundC;
350 MapIRQHook=KonamiIRQHook;