smb3 and addams family hacks
[fceu.git] / mappers / 24and26.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
d97315ac 4 * Copyright (C) 2002 Xodnizel
c62d2810 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#include "mapinc.h"
22
d97315ac 23static void (*sfun[3])(void);
24
c62d2810 25#define vrctemp mapbyte1[0]
c62d2810 26#define VPSG2 mapbyte3
27#define VPSG mapbyte2
28
29static void DoSQV1(void);
30static void DoSQV2(void);
31static void DoSawV(void);
32
33static int swaparoo;
c62d2810 34
35static int acount=0;
36
37static void FP_FASTAPASS(1) KonamiIRQHook(int a)
38{
d97315ac 39 #define LCYCS 341
40// #define LCYCS ((227*2)+1)
c62d2810 41 if(IRQa)
42 {
d97315ac 43 acount+=a*3;
c62d2810 44 if(acount>=LCYCS)
45 {
46 doagainbub:acount-=LCYCS;IRQCount++;
d97315ac 47 if(IRQCount==0x100)
48 {
49 X6502_IRQBegin(FCEU_IQEXT);
50 IRQCount=IRQLatch;
51 }
c62d2810 52 if(acount>=LCYCS) goto doagainbub;
53 }
54 }
55}
56
d97315ac 57static DECLFW(VRC6SW)
c62d2810 58{
d97315ac 59 A&=0xF003;
60 if(A>=0x9000 && A<=0x9002)
61 {
62 VPSG[A&3]=V;
63 if(sfun[0]) sfun[0]();
64 }
65 else if(A>=0xa000 && A<=0xa002)
66 {
67 VPSG[4|(A&3)]=V;
68 if(sfun[1]) sfun[1]();
69 }
70 else if(A>=0xb000 && A<=0xb002)
71 {
72 VPSG2[A&3]=V;
73 if(sfun[2]) sfun[2]();
74 }
c62d2810 75
d97315ac 76}
77
78static DECLFW(Mapper24_write)
79{
80 if(swaparoo)
81 A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2);
82 if(A>=0x9000 && A<=0xb002)
83 {
84 VRC6SW(A,V);
85 return;
86 }
87 A&=0xF003;
88// if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V);
c62d2810 89 switch(A&0xF003)
d97315ac 90 {
91 case 0x8000:ROM_BANK16(0x8000,V);break;
c62d2810 92 case 0xB003:
d97315ac 93 switch(V&0xF)
94 {
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;
99 }
100 break;
101 case 0xC000:ROM_BANK8(0xC000,V);break;
c62d2810 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;
d97315ac 110 case 0xF000:IRQLatch=V;
111 //acount=0;
112 break;
c62d2810 113 case 0xF001:IRQa=V&2;
114 vrctemp=V&1;
d97315ac 115 if(V&2)
116 {
117 IRQCount=IRQLatch;
118 acount=0;
119 }
120 X6502_IRQEnd(FCEU_IQEXT);
c62d2810 121 break;
d97315ac 122 case 0xf002:IRQa=vrctemp;
123 X6502_IRQEnd(FCEU_IQEXT);break;
c62d2810 124 case 0xF003:break;
125 }
126}
127
d97315ac 128static int32 CVBC[3];
129static int32 vcount[3];
130static int32 dcount[2];
c62d2810 131
d97315ac 132static INLINE void DoSQV(int x)
c62d2810 133{
d97315ac 134 int32 V;
135 int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4;
136 int32 start,end;
137
138 start=CVBC[x];
139 end=(SOUNDTS<<16)/soundtsinc;
140 if(end<=start) return;
141 CVBC[x]=end;
142
143 if(VPSG[(x<<2)|0x2]&0x80)
144 {
145 if(VPSG[x<<2]&0x80)
146 {
147 for(V=start;V<end;V++)
148 Wave[V>>4]+=amp;
149 }
150 else
151 {
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++)
155 {
156 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
157 Wave[V>>4]+=amp;
158 vcount[x]-=nesincsize;
159 while(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
c62d2810 160 {
d97315ac 161 vcount[x]+=freq;
162 dcount[x]=(dcount[x]+1)&15;
c62d2810 163 }
d97315ac 164 }
165 }
166 }
c62d2810 167}
c62d2810 168
d97315ac 169static void DoSQV1(void)
170{
171 DoSQV(0);
172}
c62d2810 173
d97315ac 174static void DoSQV2(void)
175{
176 DoSQV(1);
c62d2810 177}
178
179static void DoSawV(void)
180{
181 int V;
182 int32 start,end;
183
184 start=CVBC[2];
4fdfab07 185 end=(SOUNDTS<<16)/soundtsinc;
c62d2810 186 if(end<=start) return;
187 CVBC[2]=end;
188
189 if(VPSG2[2]&0x80)
190 {
d97315ac 191 static int32 saw1phaseacc=0;
c62d2810 192 uint32 freq3;
193 static uint8 b3=0;
194 static int32 phaseacc=0;
195 static uint32 duff=0;
196
197 freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
198
199 for(V=start;V<end;V++)
200 {
d97315ac 201 saw1phaseacc-=nesincsize;
c62d2810 202 if(saw1phaseacc<=0)
203 {
d97315ac 204 int32 t;
c62d2810 205 rea:
206 t=freq3;
d97315ac 207 t<<=18;
c62d2810 208 saw1phaseacc+=t;
209 phaseacc+=VPSG2[0]&0x3f;
210 b3++;
211 if(b3==7)
212 {
213 b3=0;
214 phaseacc=0;
215 }
c0bf6f9f 216 if(saw1phaseacc<=0)
c62d2810 217 goto rea;
d97315ac 218 duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
c62d2810 219 }
220 Wave[V>>4]+=duff;
221 }
222 }
223}
224
d97315ac 225#if 0
226static INLINE void DoSQVHQ(int x)
c62d2810 227{
d97315ac 228 int32 V;
229 int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
c62d2810 230
d97315ac 231 if(VPSG[(x<<2)|0x2]&0x80)
232 {
233 if(VPSG[x<<2]&0x80)
234 {
235 for(V=CVBC[x];V<SOUNDTS;V++)
236 WaveHi[V]+=amp;
237 }
238 else
239 {
240 int32 thresh=(VPSG[x<<2]>>4)&7;
241 for(V=CVBC[x];V<SOUNDTS;V++)
242 {
243 if(dcount[x]>thresh) /* Greater than, not >=. Important. */
244 WaveHi[V]+=amp;
245 vcount[x]--;
246 if(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
247 {
248 vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1;
249 dcount[x]=(dcount[x]+1)&15;
250 }
251 }
252 }
253 }
254 CVBC[x]=SOUNDTS;
c62d2810 255}
256
d97315ac 257static void DoSQV1HQ(void)
258{
259 DoSQVHQ(0);
260}
c62d2810 261
d97315ac 262static void DoSQV2HQ(void)
c62d2810 263{
d97315ac 264 DoSQVHQ(1);
265}
c62d2810 266
d97315ac 267static void DoSawVHQ(void)
268{
269 static uint8 b3=0;
270 static int32 phaseacc=0;
271 int32 V;
272
273 if(VPSG2[2]&0x80)
274 {
275 for(V=CVBC[2];V<SOUNDTS;V++)
c62d2810 276 {
d97315ac 277 WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
278 vcount[2]--;
279 if(vcount[2]<=0)
c62d2810 280 {
d97315ac 281 vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1;
282 phaseacc+=VPSG2[0]&0x3f;
283 b3++;
284 if(b3==7)
285 {
286 b3=0;
287 phaseacc=0;
288 }
289
c62d2810 290 }
291 }
d97315ac 292 }
293 CVBC[2]=SOUNDTS;
c62d2810 294}
d97315ac 295#endif
296
c62d2810 297
d97315ac 298void VRC6Sound(int Count)
c62d2810 299{
d97315ac 300 int x;
c62d2810 301
d97315ac 302 DoSQV1();
303 DoSQV2();
304 DoSawV();
305 for(x=0;x<3;x++)
306 CVBC[x]=Count;
307}
c62d2810 308
d97315ac 309#if 0
310void VRC6SoundHQ(void)
311{
312 DoSQV1HQ();
313 DoSQV2HQ();
314 DoSawVHQ();
315}
316
317void VRC6SyncHQ(int32 ts)
318{
319 int x;
320 for(x=0;x<3;x++) CVBC[x]=ts;
321}
322#endif
323
324static void VRC6_ESI(void)
325{
326 GameExpSound.RChange=VRC6_ESI;
c62d2810 327 GameExpSound.Fill=VRC6Sound;
d97315ac 328 GameExpSound.HiFill=0;//VRC6SoundHQ;
329 GameExpSound.HiSync=0;//VRC6SyncHQ;
330
331 memset(CVBC,0,sizeof(CVBC));
332 memset(vcount,0,sizeof(vcount));
333 memset(dcount,0,sizeof(dcount));
c62d2810 334 if(FSettings.SndRate)
d97315ac 335 {
336#if 0
337 if(FSettings.soundq>=1)
338 {
339 sfun[0]=DoSQV1HQ;
340 sfun[1]=DoSQV2HQ;
341 sfun[2]=DoSawVHQ;
342 }
343 else
344#endif
c62d2810 345 {
d97315ac 346 sfun[0]=DoSQV1;
347 sfun[1]=DoSQV2;
348 sfun[2]=DoSawV;
c62d2810 349 }
d97315ac 350 }
351 else
352 memset(sfun,0,sizeof(sfun));
c62d2810 353}
354
355void Mapper24_init(void)
356{
357 SetWriteHandler(0x8000,0xffff,Mapper24_write);
d97315ac 358 VRC6_ESI();
c62d2810 359 MapIRQHook=KonamiIRQHook;
d97315ac 360 swaparoo=0;
c62d2810 361}
362
363void Mapper26_init(void)
364{
365 SetWriteHandler(0x8000,0xffff,Mapper24_write);
d97315ac 366 VRC6_ESI();
c62d2810 367 MapIRQHook=KonamiIRQHook;
d97315ac 368 swaparoo=1;
c62d2810 369}
370
d97315ac 371void NSFVRC6_Init(void)
372{
373 VRC6_ESI();
374 SetWriteHandler(0x8000,0xbfff,VRC6SW);
375}