gpfce patch
[fceu.git] / mbshare / mmc3.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
5 * Copyright (C) 2002 Ben Parnell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22/* Code for emulating iNES mappers 4, 118,119 */
23
24#include "mapinc.h"
25
26#define resetmode mapbyte1[0]
27#define MMC3_cmd mapbyte1[1]
28#define A000B mapbyte1[2]
29#define A001B mapbyte1[3]
30#define DRegBuf mapbyte4
31
32#define PPUCHRBus mapbyte2[0]
33#define TKSMIR mapbyte3
34#define PIRREGS mapbyte2
35
36static void (*pwrap)(uint32 A, uint8 V);
37static void (*cwrap)(uint32 A, uint8 V);
38static void (*mwrap)(uint8 V);
39
40static int mmc3opts=0;
41
42static INLINE void FixMMC3PRG(int V);
43static INLINE void FixMMC3CHR(int V);
44
45static int latched;
46
47static DECLFW(MMC3_IRQWrite)
48{
49 //printf("$%04x:$%02x, %d\n",A,V,scanline);
50 switch(A&0xE001)
51 {
52 case 0xc000:IRQLatch=V;
53 latched=1;
54 if(resetmode)
55 {
56 IRQCount=V;
57 latched=0;
58 //resetmode=0;
59 }
60 break;
61 case 0xc001:IRQCount=IRQLatch;
62 break;
63 case 0xE000:IRQa=0;
64 X6502_IRQEnd(FCEU_IQEXT);
65 resetmode=1;
66 break;
67 case 0xE001:IRQa=1;
68 if(latched)
69 IRQCount=IRQLatch;
70 break;
71 }
72}
73
74static INLINE void FixMMC3PRG(int V)
75{
76 if(V&0x40)
77 {
78 pwrap(0xC000,DRegBuf[6]);
79 pwrap(0x8000,~1);
80 }
81 else
82 {
83 pwrap(0x8000,DRegBuf[6]);
84 pwrap(0xC000,~1);
85 }
86 pwrap(0xA000,DRegBuf[7]);
87 pwrap(0xE000,~0);
88}
89
90static INLINE void FixMMC3CHR(int V)
91{
92 int cbase=(V&0x80)<<5;
93 cwrap((cbase^0x000),DRegBuf[0]&(~1));
94 cwrap((cbase^0x400),DRegBuf[0]|1);
95 cwrap((cbase^0x800),DRegBuf[1]&(~1));
96 cwrap((cbase^0xC00),DRegBuf[1]|1);
97
98 cwrap(cbase^0x1000,DRegBuf[2]);
99 cwrap(cbase^0x1400,DRegBuf[3]);
100 cwrap(cbase^0x1800,DRegBuf[4]);
101 cwrap(cbase^0x1c00,DRegBuf[5]);
102}
103
104static void MMC3RegReset(void)
105{
106 IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
107
108 DRegBuf[0]=0;
109 DRegBuf[1]=2;
110 DRegBuf[2]=4;
111 DRegBuf[3]=5;
112 DRegBuf[4]=6;
113 DRegBuf[5]=7;
114 DRegBuf[6]=0;
115 DRegBuf[7]=1;
116
117 FixMMC3PRG(0);
118 FixMMC3CHR(0);
119}
120
121static DECLFW(Mapper4_write)
122{
123 switch(A&0xE001)
124 {
125 case 0x8000:
126 if((V&0x40) != (MMC3_cmd&0x40))
127 FixMMC3PRG(V);
128 if((V&0x80) != (MMC3_cmd&0x80))
129 FixMMC3CHR(V);
130 MMC3_cmd = V;
131 break;
132
133 case 0x8001:
134 {
135 int cbase=(MMC3_cmd&0x80)<<5;
136 DRegBuf[MMC3_cmd&0x7]=V;
137 switch(MMC3_cmd&0x07)
138 {
139 case 0: cwrap((cbase^0x000),V&(~1));
140 cwrap((cbase^0x400),V|1);
141 break;
142 case 1: cwrap((cbase^0x800),V&(~1));
143 cwrap((cbase^0xC00),V|1);
144 break;
145 case 2: cwrap(cbase^0x1000,V); break;
146 case 3: cwrap(cbase^0x1400,V); break;
147 case 4: cwrap(cbase^0x1800,V); break;
148 case 5: cwrap(cbase^0x1C00,V); break;
149 case 6: if (MMC3_cmd&0x40) pwrap(0xC000,V);
150 else pwrap(0x8000,V);
151 break;
152 case 7: pwrap(0xA000,V);
153 break;
154 }
155 }
156 break;
157
158 case 0xA000:
159 if(mwrap) mwrap(V&1);
160 break;
161 case 0xA001:
162 A001B=V;
163 break;
164 }
165}
166
167static void MMC3_hb(void)
168{
169 resetmode=0;
170 if(IRQCount>=0)
171 {
172 IRQCount--;
173 if(IRQCount<0)
174 {
175 //printf("IRQ: %d\n",scanline);
176 if(IRQa)
177 X6502_IRQBegin(FCEU_IQEXT);
178 }
179 }
180}
181static int isines;
182
183static void genmmc3restore(int version)
184{
185 if(version>=56)
186 {
187 mwrap(A000B&1);
188 FixMMC3PRG(MMC3_cmd);
189 FixMMC3CHR(MMC3_cmd);
190 }
191 else if(isines)
192 iNESStateRestore(version);
193}
194
195static void GENCWRAP(uint32 A, uint8 V)
196{
197 setchr1(A,V);
198}
199
200static void GENPWRAP(uint32 A, uint8 V)
201{
202 setprg8(A,V&0x3F);
203}
204
205static void GENMWRAP(uint8 V)
206{
207 A000B=V;
208 setmirror(V^1);
209}
210
211static void GENNOMWRAP(uint8 V)
212{
213 A000B=V;
214}
215
216static void genmmc3ii(void (*PW)(uint32 A, uint8 V),
217 void (*CW)(uint32 A, uint8 V),
218 void (*MW)(uint8 V))
219{
220 pwrap=GENPWRAP;
221 cwrap=GENCWRAP;
222 mwrap=GENMWRAP;
223 if(PW) pwrap=PW;
224 if(CW) cwrap=CW;
225 if(MW) mwrap=MW;
226 A000B=(Mirroring&1)^1; // For hard-wired mirroring on some MMC3 games.
227 // iNES format needs to die or be extended...
228 mmc3opts=0;
229 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
230 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
231
232 GameHBIRQHook=MMC3_hb;
233 GameStateRestore=genmmc3restore;
234 if(!VROM_size)
235 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
236 isines=1;
237 MMC3RegReset();
238 MapperReset=MMC3RegReset;
239}
240
241void Mapper4_init(void)
242{
243 genmmc3ii(0,0,0);
244}
245
246static void M47PW(uint32 A, uint8 V)
247{
248 V&=0xF;
249 V|=PIRREGS[0]<<4;
250 setprg8(A,V);
251}
252
253static void M47CW(uint32 A, uint8 V)
254{
255 uint32 NV=V;
256 NV&=0x7F;
257 NV|=PIRREGS[0]<<7;
258 setchr1(A,NV);
259}
260
261static DECLFW(M47Write)
262{
263 PIRREGS[0]=V&1;
264 FixMMC3PRG(MMC3_cmd);
265 FixMMC3CHR(MMC3_cmd);
266}
267
268void Mapper47_init(void)
269{
270 genmmc3ii(M47PW,M47CW,0);
271 SetWriteHandler(0x6000,0x7FFF,M47Write);
272 SetReadHandler(0x6000,0x7FFF,0);
273}
274
275static void M44PW(uint32 A, uint8 V)
276{
277 uint32 NV=V;
278 if(PIRREGS[0]>=6) NV&=0x1F;
279 else NV&=0x0F;
280 NV|=PIRREGS[0]<<4;
281 setprg8(A,NV);
282}
283static void M44CW(uint32 A, uint8 V)
284{
285 uint32 NV=V;
286 if(PIRREGS[0]<6) NV&=0x7F;
287 NV|=PIRREGS[0]<<7;
288 setchr1(A,NV);
289}
290
291static DECLFW(Mapper44_write)
292{
293 if(A&1)
294 {
295 PIRREGS[0]=V&7;
296 FixMMC3PRG(MMC3_cmd);
297 FixMMC3CHR(MMC3_cmd);
298 }
299 else
300 Mapper4_write(A,V);
301}
302
303void Mapper44_init(void)
304{
305 genmmc3ii(M44PW,M44CW,0);
306 SetWriteHandler(0xA000,0xBFFF,Mapper44_write);
307}
308
309static void M52PW(uint32 A, uint8 V)
310{
311 uint32 NV=V;
312 NV&=0x1F^((PIRREGS[0]&8)<<1);
313 NV|=((PIRREGS[0]&6)|((PIRREGS[0]>>3)&PIRREGS[0]&1))<<4;
314 setprg8(A,NV);
315}
316
317static void M52CW(uint32 A, uint8 V)
318{
319 uint32 NV=V;
320 NV&=0xFF^((PIRREGS[0]&0x40)<<1);
321 NV|=(((PIRREGS[0]>>3)&4)|((PIRREGS[0]>>1)&2)|((PIRREGS[0]>>6)&(PIRREGS[0]>>4)&1))<<7;
322 setchr1(A,NV);
323}
324
325static DECLFW(Mapper52_write)
326{
327 if(PIRREGS[1])
328 {
329 (WRAM-0x6000)[A]=V;
330 return;
331 }
332 PIRREGS[1]=1;
333 PIRREGS[0]=V;
334 FixMMC3PRG(MMC3_cmd);
335 FixMMC3CHR(MMC3_cmd);
336}
337
338static void M52Reset(void)
339{
340 PIRREGS[0]=PIRREGS[1]=0;
341 MMC3RegReset();
342}
343
344void Mapper52_init(void)
345{
346 genmmc3ii(M52PW,M52CW,0);
347 SetWriteHandler(0x6000,0x7FFF,Mapper52_write);
348 MapperReset=M52Reset;
349}
350
351static void M45CW(uint32 A, uint8 V)
352{
353 uint32 NV=V;
354 if(PIRREGS[2]&8)
355 NV&=(1<<( (PIRREGS[2]&7)+1 ))-1;
356 else
357 NV&=0;
358 NV|=PIRREGS[0]|((PIRREGS[2]&0x10)<<4);
359 setchr1(A,NV);
360}
361
362static void M45PW(uint32 A, uint8 V)
363{
364 V&=(PIRREGS[3]&0x3F)^0x3F;
365 V|=PIRREGS[1];
366 setprg8(A,V);
367}
368
369static DECLFW(Mapper45_write)
370{
371 if(PIRREGS[3]&0x40) return;
372 PIRREGS[PIRREGS[4]]=V;
373 PIRREGS[4]=(PIRREGS[4]+1)&3;
374 FixMMC3PRG(MMC3_cmd);
375 FixMMC3CHR(MMC3_cmd);
376}
377
378static void M45Reset(void)
379{
380 FCEU_dwmemset(PIRREGS,0,5);
381 MMC3RegReset();
382}
383
384void Mapper45_init(void)
385{
386 genmmc3ii(M45PW,M45CW,0);
387 SetWriteHandler(0x6000,0x7FFF,Mapper45_write);
388 SetReadHandler(0x6000,0x7FFF,0);
389 MapperReset=M45Reset;
390}
391static void M49PW(uint32 A, uint8 V)
392{
393 if(PIRREGS[0]&1)
394 {
395 V&=0xF;
396 V|=(PIRREGS[0]&0xC0)>>2;
397 setprg8(A,V);
398 }
399 else
400 setprg32(0x8000,(PIRREGS[0]>>4)&3);
401}
402
403static void M49CW(uint32 A, uint8 V)
404{
405 uint32 NV=V;
406 NV&=0x7F;
407 NV|=(PIRREGS[0]&0xC0)<<1;
408 setchr1(A,NV);
409}
410
411static DECLFW(M49Write)
412{
413 //printf("$%04x:$%02x\n",A,V);
414 if(A001B&0x80)
415 {
416 PIRREGS[0]=V;
417 FixMMC3PRG(MMC3_cmd);
418 FixMMC3CHR(MMC3_cmd);
419 }
420}
421
422static void M49Reset(void)
423{
424 PIRREGS[0]=0;
425 MMC3RegReset();
426}
427
428void Mapper49_init(void)
429{
430 genmmc3ii(M49PW,M49CW,0);
431 SetWriteHandler(0x6000,0x7FFF,M49Write);
432 SetReadHandler(0x6000,0x7FFF,0);
433 MapperReset=M49Reset;
434}
435
436static DECLFW(Mapper250_write)
437{
438 Mapper4_write((A&0xE000)|((A&0x400)>>10),A&0xFF);
439}
440
441static DECLFW(M250_IRQWrite)
442{
443 MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
444}
445
446void Mapper250_init(void)
447{
448 genmmc3ii(0,0,0);
449 SetWriteHandler(0x8000,0xBFFF,Mapper250_write);
450 SetWriteHandler(0xC000,0xFFFF,M250_IRQWrite);
451}
452
453static void FP_FASTAPASS(1) TKSPPU(uint32 A)
454{
455 //static uint8 z;
456 //if(A>=0x2000 || type<0) return;
457 //if(type<0) return;
458 A&=0x1FFF;
459 //if(scanline>=140 && scanline<=200) {setmirror(MI_1);return;}
460 //if(scanline>=140 && scanline<=200)
461 // if(scanline>=190 && scanline<=200) {setmirror(MI_1);return;}
462 // setmirror(MI_1);
463 //printf("$%04x\n",A);
464
465 A>>=10;
466 PPUCHRBus=A;
467 setmirror(MI_0+TKSMIR[A]);
468}
469
470static void TKSWRAP(uint32 A, uint8 V)
471{
472 TKSMIR[A>>10]=V>>7;
473 setchr1(A,V&0x7F);
474 if(PPUCHRBus==(A>>10))
475 setmirror(MI_0+(V>>7));
476}
477
478void Mapper118_init(void)
479{
480 genmmc3ii(0,TKSWRAP,GENNOMWRAP);
481 PPU_hook=TKSPPU;
482}
483
484static void TQWRAP(uint32 A, uint8 V)
485{
486 setchr1r((V&0x40)>>2,A,V&0x3F);
487}
488
489void Mapper119_init(void)
490{
491 genmmc3ii(0,TQWRAP,0);
492 SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
493}
494
495static int wrams;
496
497static void GenMMC3Close(void)
498{
499 UNIFOpenWRAM(UOW_WR,0,1);
500 UNIFWriteWRAM(WRAM,wrams);
501 UNIFCloseWRAM();
502}
503
504static DECLFW(MBWRAM)
505{
506 (WRAM-0x6000)[A]=V;
507}
508
509static DECLFR(MAWRAM)
510{
511 return((WRAM-0x6000)[A]);
512}
513
514static DECLFW(MBWRAMMMC6)
515{
516 WRAM[A&0x3ff]=V;
517}
518
519static DECLFR(MAWRAMMMC6)
520{
521 return(WRAM[A&0x3ff]);
522}
523
524static void GenMMC3Power(void)
525{
526 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
527 SetReadHandler(0x8000,0xFFFF,CartBR);
528 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
529
530 if(mmc3opts&1)
531 {
532 if(wrams==1024)
533 {
534 FCEU_CheatAddRAM(1,0x7000,WRAM);
535 SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
536 SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
537 }
538 else
539 {
540 FCEU_CheatAddRAM(wrams/1024,0x6000,WRAM);
541 SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
542 SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
543 }
544 if(!(mmc3opts&2))
545 FCEU_dwmemset(WRAM,0,wrams);
546 }
547 MMC3RegReset();
548}
549
550void GenMMC3_Init(int prg, int chr, int wram, int battery)
551{
552 pwrap=GENPWRAP;
553 cwrap=GENCWRAP;
554 mwrap=GENMWRAP;
555
556 wrams=wram*1024;
557
558 PRGmask8[0]&=(prg>>13)-1;
559 CHRmask1[0]&=(chr>>10)-1;
560 CHRmask2[0]&=(chr>>11)-1;
561
562 if(wram)
563 {
564 mmc3opts|=1;
565 AddExState(WRAM, wram*1024, 0, "WRAM");
566 }
567
568 if(battery)
569 {
570 mmc3opts|=2;
571 BoardClose=GenMMC3Close;
572
573 UNIFOpenWRAM(UOW_RD,0,1);
574 UNIFReadWRAM(WRAM,wram*1024);
575 UNIFCloseWRAM();
576 }
577
578 if(!chr)
579 {
580 CHRmask1[0]=7;
581 CHRmask2[0]=3;
582 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
583 AddExState(CHRRAM, 8192, 0, "CHRR");
584 }
585 AddExState(mapbyte1, 32, 0, "MPBY");
586 AddExState(&IRQa, 1, 0, "IRQA");
587 AddExState(&IRQCount, 4, 1, "IRQC");
588 AddExState(&IRQLatch, 4, 1, "IQL1");
589
590 BoardPower=GenMMC3Power;
591 BoardReset=MMC3RegReset;
592
593 GameHBIRQHook=MMC3_hb;
594 GameStateRestore=genmmc3restore;
595 isines=0;
596}
597
598// void GenMMC3_Init(int prg, int chr, int wram, int battery)
599
600void TFROM_Init(void)
601{
602 GenMMC3_Init(512, 64, 0, 0);
603}
604
605void TGROM_Init(void)
606{
607 GenMMC3_Init(512, 0, 0, 0);
608}
609
610void TKROM_Init(void)
611{
612 GenMMC3_Init(512, 256, 8, 1);
613}
614
615void TLROM_Init(void)
616{
617 GenMMC3_Init(512, 256, 0, 0);
618}
619
620void TSROM_Init(void)
621{
622 GenMMC3_Init(512, 256, 8, 0);
623}
624
625void TLSROM_Init(void)
626{
627 GenMMC3_Init(512, 256, 8, 0);
628 cwrap=TKSWRAP;
629 mwrap=GENNOMWRAP;
630}
631
632void TKSROM_Init(void)
633{
634 GenMMC3_Init(512, 256, 8, 1);
635 cwrap=TKSWRAP;
636 mwrap=GENNOMWRAP;
637}
638
639void TQROM_Init(void)
640{
641 GenMMC3_Init(512, 64, 0, 0);
642 cwrap=TQWRAP;
643}
644
645/* MMC6 board */
646void HKROM_Init(void)
647{
648 GenMMC3_Init(512, 512, 1, 1);
649}