1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 2002 Xodnizel
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
26 static void (*sfun[3])(void);
28 #define vrctemp mapbyte1[0]
29 #define VPSG2 mapbyte3
32 static void DoSQV1(void);
33 static void DoSQV2(void);
34 static void DoSawV(void);
40 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
43 // #define LCYCS ((227*2)+1)
49 doagainbub:acount-=LCYCS;IRQCount++;
52 X6502_IRQBegin(FCEU_IQEXT);
55 if(acount>=LCYCS) goto doagainbub;
63 if(A>=0x9000 && A<=0x9002)
66 if(sfun[0]) sfun[0]();
68 else if(A>=0xa000 && A<=0xa002)
71 if(sfun[1]) sfun[1]();
73 else if(A>=0xb000 && A<=0xb002)
76 if(sfun[2]) sfun[2]();
81 static DECLFW(Mapper24_write)
84 A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
85 if(A>=0x9000 && A<=0xb002)
91 // if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V);
94 case 0x8000:ROM_BANK16(0x8000,V);break;
98 case 0x0:MIRROR_SET2(1);break;
99 case 0x4:MIRROR_SET2(0);break;
100 case 0x8:onemir(0);break;
101 case 0xC:onemir(1);break;
104 case 0xC000:ROM_BANK8(0xC000,V);break;
105 case 0xD000:VROM_BANK1(0x0000,V);break;
106 case 0xD001:VROM_BANK1(0x0400,V);break;
107 case 0xD002:VROM_BANK1(0x0800,V);break;
108 case 0xD003:VROM_BANK1(0x0c00,V);break;
109 case 0xE000:VROM_BANK1(0x1000,V);break;
110 case 0xE001:VROM_BANK1(0x1400,V);break;
111 case 0xE002:VROM_BANK1(0x1800,V);break;
112 case 0xE003:VROM_BANK1(0x1c00,V);break;
113 case 0xF000:IRQLatch=V;
116 case 0xF001:IRQa=V&2;
123 X6502_IRQEnd(FCEU_IQEXT);
125 case 0xf002:IRQa=vrctemp;
126 X6502_IRQEnd(FCEU_IQEXT);break;
131 static int32 CVBC[3];
132 static int32 vcount[3];
133 static int32 dcount[2];
135 static INLINE void DoSQV(int x)
138 int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4;
142 end=(SOUNDTS<<16)/soundtsinc;
143 if(end<=start) return;
146 if(VPSG[(x<<2)|0x2]&0x80)
150 for(V=start;V<end;V++)
155 int32 thresh=(VPSG[x<<2]>>4)&7;
156 int32 freq=((VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1)<<17;
157 for(V=start;V<end;V++)
159 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
161 vcount[x]-=nesincsize;
162 while(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
165 dcount[x]=(dcount[x]+1)&15;
172 static void DoSQV1(void)
177 static void DoSQV2(void)
182 static void DoSawV(void)
188 end=(SOUNDTS<<16)/soundtsinc;
189 if(end<=start) return;
194 static int32 saw1phaseacc=0;
197 static int32 phaseacc=0;
198 static uint32 duff=0;
200 freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
202 for(V=start;V<end;V++)
204 saw1phaseacc-=nesincsize;
212 phaseacc+=VPSG2[0]&0x3f;
221 duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
228 static INLINE void DoSQVHQ(int x)
231 int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
233 if(VPSG[(x<<2)|0x2]&0x80)
237 for(V=CVBC[x];V<SOUNDTS;V++)
242 int32 thresh=(VPSG[x<<2]>>4)&7;
243 for(V=CVBC[x];V<SOUNDTS;V++)
245 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
248 if(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
250 vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
251 dcount[x]=(dcount[x]+1)&15;
259 static void DoSQV1HQ(void)
264 static void DoSQV2HQ(void)
269 static void DoSawVHQ(void)
272 static int32 phaseacc=0;
277 for(V=CVBC[2];V<SOUNDTS;V++)
279 WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
283 vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
284 phaseacc+=VPSG2[0]&0x3f;
299 void VRC6Sound(int Count)
310 void VRC6SoundHQ(void)
317 void VRC6SyncHQ(int32 ts)
320 for(x=0;x<3;x++) CVBC[x]=ts;
323 static void VRC6_ESI(void)
325 GameExpSound.RChange=VRC6_ESI;
326 GameExpSound.Fill=VRC6Sound;
327 GameExpSound.HiFill=VRC6SoundHQ;
328 GameExpSound.HiSync=VRC6SyncHQ;
330 memset(CVBC,0,sizeof(CVBC));
331 memset(vcount,0,sizeof(vcount));
332 memset(dcount,0,sizeof(dcount));
333 if(FSettings.SndRate)
335 if(FSettings.soundq>=1)
349 memset(sfun,0,sizeof(sfun));
352 void Mapper24_init(void)
354 SetWriteHandler(0x8000,0xffff,Mapper24_write);
356 MapIRQHook=KonamiIRQHook;
360 void Mapper26_init(void)
362 SetWriteHandler(0x8000,0xffff,Mapper24_write);
364 MapIRQHook=KonamiIRQHook;
368 void NSFVRC6_Init(void)
371 SetWriteHandler(0x8000,0xbfff,VRC6SW);