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
23 static void (*sfun[3])(void);
25 #define vrctemp mapbyte1[0]
26 #define VPSG2 mapbyte3
29 static void DoSQV1(void);
30 static void DoSQV2(void);
31 static void DoSawV(void);
37 static void FP_FASTAPASS(1) KonamiIRQHook(int a)
40 // #define LCYCS ((227*2)+1)
46 doagainbub:acount-=LCYCS;IRQCount++;
49 X6502_IRQBegin(FCEU_IQEXT);
52 if(acount>=LCYCS) goto doagainbub;
60 if(A>=0x9000 && A<=0x9002)
63 if(sfun[0]) sfun[0]();
65 else if(A>=0xa000 && A<=0xa002)
68 if(sfun[1]) sfun[1]();
70 else if(A>=0xb000 && A<=0xb002)
73 if(sfun[2]) sfun[2]();
78 static DECLFW(Mapper24_write)
81 A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
82 if(A>=0x9000 && A<=0xb002)
88 // if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V);
91 case 0x8000:ROM_BANK16(0x8000,V);break;
95 case 0x0:MIRROR_SET2(1);break;
96 case 0x4:MIRROR_SET2(0);break;
97 case 0x8:onemir(0);break;
98 case 0xC:onemir(1);break;
101 case 0xC000:ROM_BANK8(0xC000,V);break;
102 case 0xD000:VROM_BANK1(0x0000,V);break;
103 case 0xD001:VROM_BANK1(0x0400,V);break;
104 case 0xD002:VROM_BANK1(0x0800,V);break;
105 case 0xD003:VROM_BANK1(0x0c00,V);break;
106 case 0xE000:VROM_BANK1(0x1000,V);break;
107 case 0xE001:VROM_BANK1(0x1400,V);break;
108 case 0xE002:VROM_BANK1(0x1800,V);break;
109 case 0xE003:VROM_BANK1(0x1c00,V);break;
110 case 0xF000:IRQLatch=V;
113 case 0xF001:IRQa=V&2;
120 X6502_IRQEnd(FCEU_IQEXT);
122 case 0xf002:IRQa=vrctemp;
123 X6502_IRQEnd(FCEU_IQEXT);break;
128 static int32 CVBC[3];
129 static int32 vcount[3];
130 static int32 dcount[2];
132 static INLINE void DoSQV(int x)
135 int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4;
139 end=(SOUNDTS<<16)/soundtsinc;
140 if(end<=start) return;
143 if(VPSG[(x<<2)|0x2]&0x80)
147 for(V=start;V<end;V++)
152 int32 thresh=(VPSG[x<<2]>>4)&7;
153 int32 freq=((VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1)<<17;
154 for(V=start;V<end;V++)
156 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
158 vcount[x]-=nesincsize;
159 while(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
162 dcount[x]=(dcount[x]+1)&15;
169 static void DoSQV1(void)
174 static void DoSQV2(void)
179 static void DoSawV(void)
185 end=(SOUNDTS<<16)/soundtsinc;
186 if(end<=start) return;
191 static int32 saw1phaseacc=0;
194 static int32 phaseacc=0;
195 static uint32 duff=0;
197 freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
199 for(V=start;V<end;V++)
201 saw1phaseacc-=nesincsize;
209 phaseacc+=VPSG2[0]&0x3f;
218 duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
226 static INLINE void DoSQVHQ(int x)
229 int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
231 if(VPSG[(x<<2)|0x2]&0x80)
235 for(V=CVBC[x];V<SOUNDTS;V++)
240 int32 thresh=(VPSG[x<<2]>>4)&7;
241 for(V=CVBC[x];V<SOUNDTS;V++)
243 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
246 if(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
248 vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
249 dcount[x]=(dcount[x]+1)&15;
257 static void DoSQV1HQ(void)
262 static void DoSQV2HQ(void)
267 static void DoSawVHQ(void)
270 static int32 phaseacc=0;
275 for(V=CVBC[2];V<SOUNDTS;V++)
277 WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
281 vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
282 phaseacc+=VPSG2[0]&0x3f;
298 void VRC6Sound(int Count)
310 void VRC6SoundHQ(void)
317 void VRC6SyncHQ(int32 ts)
320 for(x=0;x<3;x++) CVBC[x]=ts;
324 static void VRC6_ESI(void)
326 GameExpSound.RChange=VRC6_ESI;
327 GameExpSound.Fill=VRC6Sound;
328 GameExpSound.HiFill=0;//VRC6SoundHQ;
329 GameExpSound.HiSync=0;//VRC6SyncHQ;
331 memset(CVBC,0,sizeof(CVBC));
332 memset(vcount,0,sizeof(vcount));
333 memset(dcount,0,sizeof(dcount));
334 if(FSettings.SndRate)
337 if(FSettings.soundq>=1)
352 memset(sfun,0,sizeof(sfun));
355 void Mapper24_init(void)
357 SetWriteHandler(0x8000,0xffff,Mapper24_write);
359 MapIRQHook=KonamiIRQHook;
363 void Mapper26_init(void)
365 SetWriteHandler(0x8000,0xffff,Mapper24_write);
367 MapIRQHook=KonamiIRQHook;
371 void NSFVRC6_Init(void)
374 SetWriteHandler(0x8000,0xbfff,VRC6SW);