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]);
91 static INLINE void FixMMC3CHR(int V)
93 int cbase=(V&0x80)<<5;
94 cwrap((cbase^0x000),DRegBuf[0]&(~1));
95 cwrap((cbase^0x400),DRegBuf[0]|1);
96 cwrap((cbase^0x800),DRegBuf[1]&(~1));
97 cwrap((cbase^0xC00),DRegBuf[1]|1);
99 cwrap(cbase^0x1000,DRegBuf[2]);
100 cwrap(cbase^0x1400,DRegBuf[3]);
101 cwrap(cbase^0x1800,DRegBuf[4]);
102 cwrap(cbase^0x1c00,DRegBuf[5]);
105 static void MMC3RegReset(void)
107 IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
122 static DECLFW(Mapper4_write)
127 if((V&0x40) != (MMC3_cmd&0x40))
129 if((V&0x80) != (MMC3_cmd&0x80))
136 int cbase=(MMC3_cmd&0x80)<<5;
137 DRegBuf[MMC3_cmd&0x7]=V;
138 switch(MMC3_cmd&0x07)
140 case 0: cwrap((cbase^0x000),V&(~1));
141 cwrap((cbase^0x400),V|1);
143 case 1: cwrap((cbase^0x800),V&(~1));
144 cwrap((cbase^0xC00),V|1);
146 case 2: cwrap(cbase^0x1000,V); break;
147 case 3: cwrap(cbase^0x1400,V); break;
148 case 4: cwrap(cbase^0x1800,V); break;
149 case 5: cwrap(cbase^0x1C00,V); break;
150 case 6: if (MMC3_cmd&0x40) pwrap(0xC000,V);
151 else pwrap(0x8000,V);
154 case 7: pwrap(0xA000,V);
162 if(mwrap) mwrap(V&1);
170 static void MMC3_hb(void)
178 //printf("IRQ: %d\n",scanline);
180 X6502_IRQBegin(FCEU_IQEXT);
186 static void genmmc3restore(int version)
191 FixMMC3PRG(MMC3_cmd);
192 FixMMC3CHR(MMC3_cmd);
195 iNESStateRestore(version);
198 static void GENCWRAP(uint32 A, uint8 V)
203 static void GENPWRAP(uint32 A, uint8 V)
208 static void GENMWRAP(uint8 V)
214 static void GENNOMWRAP(uint8 V)
219 static void genmmc3ii(void (*PW)(uint32 A, uint8 V),
220 void (*CW)(uint32 A, uint8 V),
229 A000B=(Mirroring&1)^1; // For hard-wired mirroring on some MMC3 games.
230 // iNES format needs to die or be extended...
232 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
233 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
235 GameHBIRQHook=MMC3_hb;
236 GameStateRestore=genmmc3restore;
238 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
241 MapperReset=MMC3RegReset;
244 void Mapper4_init(void)
249 static void M47PW(uint32 A, uint8 V)
256 static void M47CW(uint32 A, uint8 V)
264 static DECLFW(M47Write)
267 FixMMC3PRG(MMC3_cmd);
268 FixMMC3CHR(MMC3_cmd);
271 void Mapper47_init(void)
273 genmmc3ii(M47PW,M47CW,0);
274 SetWriteHandler(0x6000,0x7FFF,M47Write);
275 SetReadHandler(0x6000,0x7FFF,0);
278 static void M44PW(uint32 A, uint8 V)
281 if(PIRREGS[0]>=6) NV&=0x1F;
286 static void M44CW(uint32 A, uint8 V)
289 if(PIRREGS[0]<6) NV&=0x7F;
294 static DECLFW(Mapper44_write)
299 FixMMC3PRG(MMC3_cmd);
300 FixMMC3CHR(MMC3_cmd);
306 void Mapper44_init(void)
308 genmmc3ii(M44PW,M44CW,0);
309 SetWriteHandler(0xA000,0xBFFF,Mapper44_write);
312 static void M52PW(uint32 A, uint8 V)
315 NV&=0x1F^((PIRREGS[0]&8)<<1);
316 NV|=((PIRREGS[0]&6)|((PIRREGS[0]>>3)&PIRREGS[0]&1))<<4;
320 static void M52CW(uint32 A, uint8 V)
323 NV&=0xFF^((PIRREGS[0]&0x40)<<1);
324 NV|=(((PIRREGS[0]>>3)&4)|((PIRREGS[0]>>1)&2)|((PIRREGS[0]>>6)&(PIRREGS[0]>>4)&1))<<7;
328 static DECLFW(Mapper52_write)
337 FixMMC3PRG(MMC3_cmd);
338 FixMMC3CHR(MMC3_cmd);
341 static void M52Reset(void)
343 PIRREGS[0]=PIRREGS[1]=0;
347 void Mapper52_init(void)
349 genmmc3ii(M52PW,M52CW,0);
350 SetWriteHandler(0x6000,0x7FFF,Mapper52_write);
351 MapperReset=M52Reset;
354 static void M45CW(uint32 A, uint8 V)
358 NV&=(1<<( (PIRREGS[2]&7)+1 ))-1;
361 NV|=PIRREGS[0]|((PIRREGS[2]&0x10)<<4);
365 static void M45PW(uint32 A, uint8 V)
367 V&=(PIRREGS[3]&0x3F)^0x3F;
372 static DECLFW(Mapper45_write)
374 if(PIRREGS[3]&0x40) return;
375 PIRREGS[PIRREGS[4]]=V;
376 PIRREGS[4]=(PIRREGS[4]+1)&3;
377 FixMMC3PRG(MMC3_cmd);
378 FixMMC3CHR(MMC3_cmd);
381 static void M45Reset(void)
383 FCEU_dwmemset(PIRREGS,0,5);
387 void Mapper45_init(void)
389 genmmc3ii(M45PW,M45CW,0);
390 SetWriteHandler(0x6000,0x7FFF,Mapper45_write);
391 SetReadHandler(0x6000,0x7FFF,0);
392 MapperReset=M45Reset;
394 static void M49PW(uint32 A, uint8 V)
399 V|=(PIRREGS[0]&0xC0)>>2;
404 setprg32(0x8000,(PIRREGS[0]>>4)&3);
409 static void M49CW(uint32 A, uint8 V)
413 NV|=(PIRREGS[0]&0xC0)<<1;
417 static DECLFW(M49Write)
419 //printf("$%04x:$%02x\n",A,V);
423 FixMMC3PRG(MMC3_cmd);
424 FixMMC3CHR(MMC3_cmd);
428 static void M49Reset(void)
434 void Mapper49_init(void)
436 genmmc3ii(M49PW,M49CW,0);
437 SetWriteHandler(0x6000,0x7FFF,M49Write);
438 SetReadHandler(0x6000,0x7FFF,0);
439 MapperReset=M49Reset;
442 static DECLFW(Mapper250_write)
444 Mapper4_write((A&0xE000)|((A&0x400)>>10),A&0xFF);
447 static DECLFW(M250_IRQWrite)
449 MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
452 void Mapper250_init(void)
455 SetWriteHandler(0x8000,0xBFFF,Mapper250_write);
456 SetWriteHandler(0xC000,0xFFFF,M250_IRQWrite);
459 static void FP_FASTAPASS(1) TKSPPU(uint32 A)
462 //if(A>=0x2000 || type<0) return;
465 //if(scanline>=140 && scanline<=200) {setmirror(MI_1);return;}
466 //if(scanline>=140 && scanline<=200)
467 // if(scanline>=190 && scanline<=200) {setmirror(MI_1);return;}
469 //printf("$%04x\n",A);
473 setmirror(MI_0+TKSMIR[A]);
476 static void TKSWRAP(uint32 A, uint8 V)
480 if(PPUCHRBus==(A>>10))
481 setmirror(MI_0+(V>>7));
484 void Mapper118_init(void)
486 genmmc3ii(0,TKSWRAP,GENNOMWRAP);
490 static void TQWRAP(uint32 A, uint8 V)
492 setchr1r((V&0x40)>>2,A,V&0x3F);
495 void Mapper119_init(void)
497 genmmc3ii(0,TQWRAP,0);
498 SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
503 static void GenMMC3Close(void)
505 UNIFOpenWRAM(UOW_WR,0,1);
506 UNIFWriteWRAM(WRAM,wrams);
510 static DECLFW(MBWRAM)
515 static DECLFR(MAWRAM)
517 return((WRAM-0x6000)[A]);
520 static DECLFW(MBWRAMMMC6)
525 static DECLFR(MAWRAMMMC6)
527 return(WRAM[A&0x3ff]);
530 static void GenMMC3Power(void)
532 SetWriteHandler(0x8000,0xBFFF,Mapper4_write);
533 SetReadHandler(0x8000,0xFFFF,CartBR);
534 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
540 FCEU_CheatAddRAM(1,0x7000,WRAM);
541 SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
542 SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
546 FCEU_CheatAddRAM(wrams/1024,0x6000,WRAM);
547 SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
548 SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
551 FCEU_dwmemset(WRAM,0,wrams);
556 void GenMMC3_Init(int prg, int chr, int wram, int battery)
564 PRGmask8[0]&=(prg>>13)-1;
565 CHRmask1[0]&=(chr>>10)-1;
566 CHRmask2[0]&=(chr>>11)-1;
571 AddExState(WRAM, wram*1024, 0, "WRAM");
577 BoardClose=GenMMC3Close;
579 UNIFOpenWRAM(UOW_RD,0,1);
580 UNIFReadWRAM(WRAM,wram*1024);
588 SetupCartCHRMapping(0, CHRRAM, 8192, 1);
589 AddExState(CHRRAM, 8192, 0, "CHRR");
591 AddExState(mapbyte1, 32, 0, "MPBY");
592 AddExState(&IRQa, 1, 0, "IRQA");
593 AddExState(&IRQCount, 4, 1, "IRQC");
594 AddExState(&IRQLatch, 4, 1, "IQL1");
596 BoardPower=GenMMC3Power;
597 BoardReset=MMC3RegReset;
599 GameHBIRQHook=MMC3_hb;
600 GameStateRestore=genmmc3restore;
604 // void GenMMC3_Init(int prg, int chr, int wram, int battery)
606 void TFROM_Init(void)
608 GenMMC3_Init(512, 64, 0, 0);
611 void TGROM_Init(void)
613 GenMMC3_Init(512, 0, 0, 0);
616 void TKROM_Init(void)
618 GenMMC3_Init(512, 256, 8, 1);
621 void TLROM_Init(void)
623 GenMMC3_Init(512, 256, 0, 0);
626 void TSROM_Init(void)
628 GenMMC3_Init(512, 256, 8, 0);
631 void TLSROM_Init(void)
633 GenMMC3_Init(512, 256, 8, 0);
638 void TKSROM_Init(void)
640 GenMMC3_Init(512, 256, 8, 1);
645 void TQROM_Init(void)
647 GenMMC3_Init(512, 64, 0, 0);
652 void HKROM_Init(void)
654 GenMMC3_Init(512, 512, 1, 1);