1 /* FCE Ultra - NES/Famicom Emulator
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
5 * Copyright (C) 2002 Ben Parnell
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.
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.
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
22 /* Code for emulating iNES mappers 4, 118,119 */
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
32 #define PPUCHRBus mapbyte2[0]
33 #define TKSMIR mapbyte3
34 #define PIRREGS mapbyte2
36 static void (*pwrap)(uint32 A, uint8 V);
37 static void (*cwrap)(uint32 A, uint8 V);
38 static void (*mwrap)(uint8 V);
40 static int mmc3opts=0;
42 static INLINE void FixMMC3PRG(int V);
43 static INLINE void FixMMC3CHR(int V);
47 static DECLFW(MMC3_IRQWrite)
49 //printf("$%04x:$%02x, %d\n",A,V,scanline);
52 case 0xc000:IRQLatch=V;
61 case 0xc001:IRQCount=IRQLatch;
64 X6502_IRQEnd(FCEU_IQEXT);
74 static INLINE void FixMMC3PRG(int V)
78 pwrap(0xC000,DRegBuf[6]);
83 pwrap(0x8000,DRegBuf[6]);
86 pwrap(0xA000,DRegBuf[7]);
90 static INLINE void FixMMC3CHR(int V)
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);
98 cwrap(cbase^0x1000,DRegBuf[2]);
99 cwrap(cbase^0x1400,DRegBuf[3]);
100 cwrap(cbase^0x1800,DRegBuf[4]);
101 cwrap(cbase^0x1c00,DRegBuf[5]);
104 static void MMC3RegReset(void)
106 IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
121 static DECLFW(Mapper4_write)
126 if((V&0x40) != (MMC3_cmd&0x40))
128 if((V&0x80) != (MMC3_cmd&0x80))
135 int cbase=(MMC3_cmd&0x80)<<5;
136 DRegBuf[MMC3_cmd&0x7]=V;
137 switch(MMC3_cmd&0x07)
139 case 0: cwrap((cbase^0x000),V&(~1));
140 cwrap((cbase^0x400),V|1);
142 case 1: cwrap((cbase^0x800),V&(~1));
143 cwrap((cbase^0xC00),V|1);
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);
152 case 7: pwrap(0xA000,V);
159 if(mwrap) mwrap(V&1);
167 static void MMC3_hb(void)
175 //printf("IRQ: %d\n",scanline);
177 X6502_IRQBegin(FCEU_IQEXT);
183 static void genmmc3restore(int version)
188 FixMMC3PRG(MMC3_cmd);
189 FixMMC3CHR(MMC3_cmd);
192 iNESStateRestore(version);
195 static void GENCWRAP(uint32 A, uint8 V)
200 static void GENPWRAP(uint32 A, uint8 V)
205 static void GENMWRAP(uint8 V)
211 static void GENNOMWRAP(uint8 V)
216 static void genmmc3ii(void (*PW)(uint32 A, uint8 V),
217 void (*CW)(uint32 A, uint8 V),
226 A000B=(Mirroring&1)^1; // For hard-wired mirroring on some MMC3 games.
227 // iNES format needs to die or be extended...
229 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
230 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
232 GameHBIRQHook=MMC3_hb;
233 GameStateRestore=genmmc3restore;
235 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
238 MapperReset=MMC3RegReset;
241 void Mapper4_init(void)
246 static void M47PW(uint32 A, uint8 V)
253 static void M47CW(uint32 A, uint8 V)
261 static DECLFW(M47Write)
264 FixMMC3PRG(MMC3_cmd);
265 FixMMC3CHR(MMC3_cmd);
268 void Mapper47_init(void)
270 genmmc3ii(M47PW,M47CW,0);
271 SetWriteHandler(0x6000,0x7FFF,M47Write);
272 SetReadHandler(0x6000,0x7FFF,0);
275 static void M44PW(uint32 A, uint8 V)
278 if(PIRREGS[0]>=6) NV&=0x1F;
283 static void M44CW(uint32 A, uint8 V)
286 if(PIRREGS[0]<6) NV&=0x7F;
291 static DECLFW(Mapper44_write)
296 FixMMC3PRG(MMC3_cmd);
297 FixMMC3CHR(MMC3_cmd);
303 void Mapper44_init(void)
305 genmmc3ii(M44PW,M44CW,0);
306 SetWriteHandler(0xA000,0xBFFF,Mapper44_write);
309 static void M52PW(uint32 A, uint8 V)
312 NV&=0x1F^((PIRREGS[0]&8)<<1);
313 NV|=((PIRREGS[0]&6)|((PIRREGS[0]>>3)&PIRREGS[0]&1))<<4;
317 static void M52CW(uint32 A, uint8 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;
325 static DECLFW(Mapper52_write)
334 FixMMC3PRG(MMC3_cmd);
335 FixMMC3CHR(MMC3_cmd);
338 static void M52Reset(void)
340 PIRREGS[0]=PIRREGS[1]=0;
344 void Mapper52_init(void)
346 genmmc3ii(M52PW,M52CW,0);
347 SetWriteHandler(0x6000,0x7FFF,Mapper52_write);
348 MapperReset=M52Reset;
351 static void M45CW(uint32 A, uint8 V)
355 NV&=(1<<( (PIRREGS[2]&7)+1 ))-1;
358 NV|=PIRREGS[0]|((PIRREGS[2]&0x10)<<4);
362 static void M45PW(uint32 A, uint8 V)
364 V&=(PIRREGS[3]&0x3F)^0x3F;
369 static DECLFW(Mapper45_write)
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);
378 static void M45Reset(void)
380 FCEU_dwmemset(PIRREGS,0,5);
384 void Mapper45_init(void)
386 genmmc3ii(M45PW,M45CW,0);
387 SetWriteHandler(0x6000,0x7FFF,Mapper45_write);
388 SetReadHandler(0x6000,0x7FFF,0);
389 MapperReset=M45Reset;
391 static void M49PW(uint32 A, uint8 V)
396 V|=(PIRREGS[0]&0xC0)>>2;
400 setprg32(0x8000,(PIRREGS[0]>>4)&3);
403 static void M49CW(uint32 A, uint8 V)
407 NV|=(PIRREGS[0]&0xC0)<<1;
411 static DECLFW(M49Write)
413 //printf("$%04x:$%02x\n",A,V);
417 FixMMC3PRG(MMC3_cmd);
418 FixMMC3CHR(MMC3_cmd);
422 static void M49Reset(void)
428 void Mapper49_init(void)
430 genmmc3ii(M49PW,M49CW,0);
431 SetWriteHandler(0x6000,0x7FFF,M49Write);
432 SetReadHandler(0x6000,0x7FFF,0);
433 MapperReset=M49Reset;
436 static DECLFW(Mapper250_write)
438 Mapper4_write((A&0xE000)|((A&0x400)>>10),A&0xFF);
441 static DECLFW(M250_IRQWrite)
443 MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
446 void Mapper250_init(void)
449 SetWriteHandler(0x8000,0xBFFF,Mapper250_write);
450 SetWriteHandler(0xC000,0xFFFF,M250_IRQWrite);
453 static void FP_FASTAPASS(1) TKSPPU(uint32 A)
456 //if(A>=0x2000 || type<0) return;
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;}
463 //printf("$%04x\n",A);
467 setmirror(MI_0+TKSMIR[A]);
470 static void TKSWRAP(uint32 A, uint8 V)
474 if(PPUCHRBus==(A>>10))
475 setmirror(MI_0+(V>>7));
478 void Mapper118_init(void)
480 genmmc3ii(0,TKSWRAP,GENNOMWRAP);
484 static void TQWRAP(uint32 A, uint8 V)
486 setchr1r((V&0x40)>>2,A,V&0x3F);
489 void Mapper119_init(void)
491 genmmc3ii(0,TQWRAP,0);
492 SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
497 static void GenMMC3Close(void)
499 UNIFOpenWRAM(UOW_WR,0,1);
500 UNIFWriteWRAM(WRAM,wrams);
504 static DECLFW(MBWRAM)
509 static DECLFR(MAWRAM)
511 return((WRAM-0x6000)[A]);
514 static DECLFW(MBWRAMMMC6)
519 static DECLFR(MAWRAMMMC6)
521 return(WRAM[A&0x3ff]);
524 static void GenMMC3Power(void)
526 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
527 SetReadHandler(0x8000,0xFFFF,CartBR);
528 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
534 FCEU_CheatAddRAM(1,0x7000,WRAM);
535 SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
536 SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
540 FCEU_CheatAddRAM(wrams/1024,0x6000,WRAM);
541 SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
542 SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
545 FCEU_dwmemset(WRAM,0,wrams);
550 void GenMMC3_Init(int prg, int chr, int wram, int battery)
558 PRGmask8[0]&=(prg>>13)-1;
559 CHRmask1[0]&=(chr>>10)-1;
560 CHRmask2[0]&=(chr>>11)-1;
565 AddExState(WRAM, wram*1024, 0, "WRAM");
571 BoardClose=GenMMC3Close;
573 UNIFOpenWRAM(UOW_RD,0,1);
574 UNIFReadWRAM(WRAM,wram*1024);
582 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
583 AddExState(CHRRAM, 8192, 0, "CHRR");
585 AddExState(mapbyte1, 32, 0, "MPBY");
586 AddExState(&IRQa, 1, 0, "IRQA");
587 AddExState(&IRQCount, 4, 1, "IRQC");
588 AddExState(&IRQLatch, 4, 1, "IQL1");
590 BoardPower=GenMMC3Power;
591 BoardReset=MMC3RegReset;
593 GameHBIRQHook=MMC3_hb;
594 GameStateRestore=genmmc3restore;
598 // void GenMMC3_Init(int prg, int chr, int wram, int battery)
600 void TFROM_Init(void)
602 GenMMC3_Init(512, 64, 0, 0);
605 void TGROM_Init(void)
607 GenMMC3_Init(512, 0, 0, 0);
610 void TKROM_Init(void)
612 GenMMC3_Init(512, 256, 8, 1);
615 void TLROM_Init(void)
617 GenMMC3_Init(512, 256, 0, 0);
620 void TSROM_Init(void)
622 GenMMC3_Init(512, 256, 8, 0);
625 void TLSROM_Init(void)
627 GenMMC3_Init(512, 256, 8, 0);
632 void TKSROM_Init(void)
634 GenMMC3_Init(512, 256, 8, 1);
639 void TQROM_Init(void)
641 GenMMC3_Init(512, 64, 0, 0);
646 void HKROM_Init(void)
648 GenMMC3_Init(512, 512, 1, 1);