mappers updated to 0.98.16
[fceu.git] / boards / mmc3.c
CommitLineData
d97315ac 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
4 * Copyright (C) 1998 BERO
5 * Copyright (C) 2003 Xodnizel
6 * Mapper 12 code Copyright (C) 2003 CaH4e3
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23/* Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118,
24 119,148,165,205,214,215,245,249,250,254
25*/
26
27#include "mapinc.h"
28#include "mmc3.h"
29
e2d0dd92 30uint8 MMC3_cmd;
31uint8 *WRAM;
32uint8 *CHRRAM;
33uint32 CHRRAMSize;
34uint8 EXPREGS[8]; /* For bootleg games, mostly. */
d97315ac 35
e2d0dd92 36static uint8 A000B,A001B;
37static uint8 DRegBuf[8];
d97315ac 38
39#undef IRQCount
40#undef IRQLatch
41#undef IRQa
e2d0dd92 42uint8 IRQCount,IRQLatch,IRQa;
43uint8 IRQReload;
d97315ac 44
45static SFORMAT MMC3_StateRegs[]=
46{
47 {DRegBuf, 8, "REGS"},
48 {&MMC3_cmd, 1, "CMD"},
49 {&A000B, 1, "A000"},
50 {&A001B, 1, "A001"},
51 {&IRQReload, 1, "IRQR"},
52 {&IRQCount, 1, "IRQC"},
53 {&IRQLatch, 1, "IRQL"},
54 {&IRQa, 1, "IRQA"},
55 {0}
56};
57
58static int mmc3opts=0;
e2d0dd92 59static int wrams;
60static int isRevB=1;
d97315ac 61
62void (*pwrap)(uint32 A, uint8 V);
63void (*cwrap)(uint32 A, uint8 V);
64void (*mwrap)(uint8 V);
65
66void GenMMC3Power(void);
67void FixMMC3PRG(int V);
68void FixMMC3CHR(int V);
69
70void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
71
72// ----------------------------------------------------------------------
73// ------------------------- Generic MM3 Code ---------------------------
74// ----------------------------------------------------------------------
75
76void FixMMC3PRG(int V)
77{
78 if(V&0x40)
79 {
80 pwrap(0xC000,DRegBuf[6]);
81 pwrap(0x8000,~1);
82 }
83 else
84 {
85 pwrap(0x8000,DRegBuf[6]);
86 pwrap(0xC000,~1);
87 }
88 pwrap(0xA000,DRegBuf[7]);
89 pwrap(0xE000,~0);
90}
91
92void FixMMC3CHR(int V)
93{
94 int cbase=(V&0x80)<<5;
95
96 cwrap((cbase^0x000),DRegBuf[0]&(~1));
97 cwrap((cbase^0x400),DRegBuf[0]|1);
98 cwrap((cbase^0x800),DRegBuf[1]&(~1));
99 cwrap((cbase^0xC00),DRegBuf[1]|1);
100
101 cwrap(cbase^0x1000,DRegBuf[2]);
102 cwrap(cbase^0x1400,DRegBuf[3]);
103 cwrap(cbase^0x1800,DRegBuf[4]);
104 cwrap(cbase^0x1c00,DRegBuf[5]);
105}
106
107void MMC3RegReset(void)
108{
109 IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
110
111 DRegBuf[0]=0;
112 DRegBuf[1]=2;
113 DRegBuf[2]=4;
114 DRegBuf[3]=5;
115 DRegBuf[4]=6;
116 DRegBuf[5]=7;
117 DRegBuf[6]=0;
118 DRegBuf[7]=1;
119
120 FixMMC3PRG(0);
121 FixMMC3CHR(0);
122}
123
124DECLFW(MMC3_CMDWrite)
125{
e2d0dd92 126// FCEU_printf("%04x:%04x\n",A,V);
d97315ac 127 switch(A&0xE001)
128 {
129 case 0x8000:
130 if((V&0x40) != (MMC3_cmd&0x40))
131 FixMMC3PRG(V);
132 if((V&0x80) != (MMC3_cmd&0x80))
133 FixMMC3CHR(V);
134 MMC3_cmd = V;
135 break;
136 case 0x8001:
137 {
138 int cbase=(MMC3_cmd&0x80)<<5;
139 DRegBuf[MMC3_cmd&0x7]=V;
140 switch(MMC3_cmd&0x07)
141 {
142 case 0: cwrap((cbase^0x000),V&(~1));
143 cwrap((cbase^0x400),V|1);
144 break;
145 case 1: cwrap((cbase^0x800),V&(~1));
146 cwrap((cbase^0xC00),V|1);
147 break;
148 case 2: cwrap(cbase^0x1000,V);
149 break;
150 case 3: cwrap(cbase^0x1400,V);
151 break;
152 case 4: cwrap(cbase^0x1800,V);
153 break;
154 case 5: cwrap(cbase^0x1C00,V);
155 break;
156 case 6:
157 if(MMC3_cmd&0x40)
158 pwrap(0xC000,V);
159 else
160 pwrap(0x8000,V);
161 break;
162 case 7:
163 pwrap(0xA000,V);
164 break;
165 }
166 }
167 break;
168 case 0xA000:
169 if(mwrap) mwrap(V&1);
170 break;
171 case 0xA001:
172 A001B=V;
e2d0dd92 173 Write_IRQFM(0x4017,0x40);
d97315ac 174 break;
175 }
176}
177
178DECLFW(MMC3_IRQWrite)
179{
e2d0dd92 180// FCEU_printf("%04x:%04x\n",A,V);
d97315ac 181 switch(A&0xE001)
182 {
183 case 0xC000:IRQLatch=V;break;
184 case 0xC001:IRQReload=1;break;
185 case 0xE000:X6502_IRQEnd(FCEU_IQEXT);IRQa=0;break;
186 case 0xE001:IRQa=1;break;
187 }
188}
189
190static void ClockMMC3Counter(void)
191{
192 int count = IRQCount;
193 if(!count || IRQReload)
194 {
195 IRQCount = IRQLatch;
196 IRQReload = 0;
197 }
198 else
199 IRQCount--;
e2d0dd92 200 if((count|isRevB) && !IRQCount)
d97315ac 201 {
202 if(IRQa)
203 {
204 X6502_IRQBegin(FCEU_IQEXT);
205 }
206 }
207}
208
209static void MMC3_hb(void)
210{
211 ClockMMC3Counter();
212}
213
214static void MMC3_hb_KickMasterHack(void)
215{
216 if(scanline==238) ClockMMC3Counter();
217 ClockMMC3Counter();
218}
219
220static void MMC3_hb_PALStarWarsHack(void)
221{
222 if(scanline==240) ClockMMC3Counter();
223 ClockMMC3Counter();
224}
225
e2d0dd92 226void GenMMC3Restore(int version)
d97315ac 227{
228 if(mwrap) mwrap(A000B&1);
229 FixMMC3PRG(MMC3_cmd);
230 FixMMC3CHR(MMC3_cmd);
231}
232
233static void GENCWRAP(uint32 A, uint8 V)
234{
e2d0dd92 235 if(!UNIFchrrama) setchr1(A,V);
d97315ac 236}
237
238static void GENPWRAP(uint32 A, uint8 V)
239{
240 setprg8(A,V&0x3F);
241}
242
243static void GENMWRAP(uint8 V)
244{
245 A000B=V;
246 setmirror(V^1);
247}
248
249static void GENNOMWRAP(uint8 V)
250{
251 A000B=V;
252}
253
254static DECLFW(MBWRAM)
255{
256 WRAM[A-0x6000]=V;
257}
258
259static DECLFR(MAWRAM)
260{
261 return(WRAM[A-0x6000]);
262}
263
264static DECLFW(MBWRAMMMC6)
265{
266 WRAM[A&0x3ff]=V;
267}
268
269static DECLFR(MAWRAMMMC6)
270{
271 return(WRAM[A&0x3ff]);
272}
273
274void GenMMC3Power(void)
275{
e2d0dd92 276 if(UNIFchrrama) setchr8(0);
277
d97315ac 278 SetWriteHandler(0x8000,0xBFFF,MMC3_CMDWrite);
279 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
280 SetReadHandler(0x8000,0xFFFF,CartBR);
281 A001B=A000B=0;
282 setmirror(1);
283 if(mmc3opts&1)
284 {
285 if(wrams==1024)
286 {
287 FCEU_CheatAddRAM(1,0x7000,WRAM);
288 SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
289 SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
290 }
291 else
292 {
293 FCEU_CheatAddRAM(wrams>>10,0x6000,WRAM);
294 SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
295 SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
296 }
297 if(!(mmc3opts&2))
298 FCEU_dwmemset(WRAM,0,wrams);
299 }
300 MMC3RegReset();
301 if(CHRRAM)
302 FCEU_dwmemset(CHRRAM,0,CHRRAMSize);
303}
304
305static void GenMMC3Close(void)
306{
307 if(CHRRAM)
308 FCEU_gfree(CHRRAM);
309 if(WRAM)
310 FCEU_gfree(WRAM);
311 CHRRAM=WRAM=NULL;
312}
313
e2d0dd92 314//static uint16 _a12;
315//static void FP_FASTAPASS(1) MMC3_PPU(uint32 A)
316//{
317// if(A&0x2000)return;
318// if((!_a12)&&(A&0x1000))
319// ClockMMC3Counter();
320// _a12=A&0x1000;
321//}
322
d97315ac 323void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery)
324{
e2d0dd92 325 pwrap=GENPWRAP;
d97315ac 326 cwrap=GENCWRAP;
327 mwrap=GENMWRAP;
328
329 wrams=wram<<10;
330
331 PRGmask8[0]&=(prg>>13)-1;
332 CHRmask1[0]&=(chr>>10)-1;
333 CHRmask2[0]&=(chr>>11)-1;
334
335 if(wram)
336 {
337 mmc3opts|=1;
338 WRAM=(uint8*)FCEU_gmalloc(wrams);
339 AddExState(WRAM, wrams, 0, "WRAM");
340 }
341
342 if(battery)
343 {
344 mmc3opts|=2;
345 info->SaveGame[0]=WRAM;
346 info->SaveGameLen[0]=wrams;
347 }
348
e2d0dd92 349// if(!chr) // duplicated CHR RAM set up
350// {
351// CHRRAM=(uint8*)FCEU_gmalloc(8192);
352// CHRRAMSize=8192;
353// SetupCartCHRMapping(0, CHRRAM, 8192, 1);
354// AddExState(CHRRAM, 8192, 0, "CHRR");
355// }
d97315ac 356
357 AddExState(MMC3_StateRegs, ~0, 0, 0);
358
359 info->Power=GenMMC3Power;
360 info->Reset=MMC3RegReset;
361 info->Close=GenMMC3Close;
362
363 if(info->CRC32 == 0x5104833e) // Kick Master
364 GameHBIRQHook = MMC3_hb_KickMasterHack;
365 else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93
366 GameHBIRQHook = MMC3_hb_KickMasterHack;
367 else if(info->CRC32 == 0xfcd772eb) // PAL Star Wars, similar problem as Kick Master.
368 GameHBIRQHook = MMC3_hb_PALStarWarsHack;
369 else
e2d0dd92 370 GameHBIRQHook=MMC3_hb;
371// PPU_hook=MMC3_PPU;
372 GameStateRestore=GenMMC3Restore;
d97315ac 373}
374
375// ----------------------------------------------------------------------
376// -------------------------- MMC3 Based Code ---------------------------
377// ----------------------------------------------------------------------
378
379// ---------------------------- Mapper 4 --------------------------------
380
381static int hackm4=0;/* For Karnov, maybe others. BLAH. Stupid iNES format.*/
382
383static void M4Power(void)
384{
385 GenMMC3Power();
386 A000B=(hackm4^1)&1;
387 setmirror(hackm4);
388}
389
390void Mapper4_Init(CartInfo *info)
391{
392 int ws=8;
393
394 if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84))
395 {
396 FCEU_printf("Low-G-Man can not work normally in the iNES format.\nThis game has been recognized by its CRC32 value, and the appropriate changes will be made so it will run.\nIf you wish to hack this game, you should use the UNIF format for your hack.\n\n");
397 ws=0;
398 }
399 GenMMC3_Init(info,512,256,ws,info->battery);
400 info->Power=M4Power;
401 hackm4=info->mirror;
402}
403
404// ---------------------------- Mapper 12 -------------------------------
405
406static void M12CW(uint32 A, uint8 V)
407{
408 setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V);
409}
410
411static DECLFW(M12Write)
412{
413 EXPREGS[0]=V&0x01;
414 EXPREGS[1]=(V&0x10)>>4;
415}
416
417static void M12Power(void)
418{
419 EXPREGS[0]=EXPREGS[1]=0;
420 GenMMC3Power();
421 SetWriteHandler(0x4100,0x5FFF,M12Write);
422}
423
424void Mapper12_Init(CartInfo *info)
425{
426 GenMMC3_Init(info, 512, 256, 8, info->battery);
427 cwrap=M12CW;
428 info->Power=M12Power;
429 AddExState(EXPREGS, 2, 0, "EXPR");
430}
431
e2d0dd92 432// ---------------------------- Mapper 37 -------------------------------
433
434static void M37PW(uint32 A, uint8 V)
435{
436 if(EXPREGS[0]!=2)
437 V&=0x7;
438 else
439 V&=0xF;
440 V|=EXPREGS[0]<<3;
441 setprg8(A,V);
442}
443
444static void M37CW(uint32 A, uint8 V)
445{
446 uint32 NV=V;
447 NV&=0x7F;
448 NV|=EXPREGS[0]<<6;
449 setchr1(A,NV);
450}
451
452static DECLFW(M37Write)
453{
454 EXPREGS[0]=(V&6)>>1;
455 FixMMC3PRG(MMC3_cmd);
456 FixMMC3CHR(MMC3_cmd);
457}
458
459static void M37Reset(void)
460{
461 EXPREGS[0]=0;
462 MMC3RegReset();
463}
464
465static void M37Power(void)
466{
467 EXPREGS[0]=0;
468 GenMMC3Power();
469 SetWriteHandler(0x6000,0x7FFF,M37Write);
470}
471
472void Mapper37_Init(CartInfo *info)
473{
474 GenMMC3_Init(info, 512, 256, 8, info->battery);
475 pwrap=M37PW;
476 cwrap=M37CW;
477 info->Power=M37Power;
478 info->Reset=M37Reset;
479 AddExState(EXPREGS, 1, 0, "EXPR");
480}
481
d97315ac 482// ---------------------------- Mapper 44 -------------------------------
483
484static void M44PW(uint32 A, uint8 V)
485{
486 uint32 NV=V;
487 if(EXPREGS[0]>=6) NV&=0x1F;
488 else NV&=0x0F;
489 NV|=EXPREGS[0]<<4;
490 setprg8(A,NV);
491}
492
493static void M44CW(uint32 A, uint8 V)
494{
495 uint32 NV=V;
496 if(EXPREGS[0]<6) NV&=0x7F;
497 NV|=EXPREGS[0]<<7;
498 setchr1(A,NV);
499}
500
501static DECLFW(M44Write)
502{
503 if(A&1)
504 {
505 EXPREGS[0]=V&7;
506 FixMMC3PRG(MMC3_cmd);
507 FixMMC3CHR(MMC3_cmd);
508 }
509 else
510 MMC3_CMDWrite(A,V);
511}
512
513static void M44Power(void)
514{
515 EXPREGS[0]=0;
516 GenMMC3Power();
517 SetWriteHandler(0xA000,0xBFFF,M44Write);
518}
519
520void Mapper44_Init(CartInfo *info)
521{
522 GenMMC3_Init(info, 512, 256, 8, info->battery);
523 cwrap=M44CW;
524 pwrap=M44PW;
525 info->Power=M44Power;
526 AddExState(EXPREGS, 1, 0, "EXPR");
527}
528
529// ---------------------------- Mapper 45 -------------------------------
530
531static void M45CW(uint32 A, uint8 V)
532{
e2d0dd92 533 if(!UNIFchrrama)
534 {
535 uint32 NV=V;
536 if(EXPREGS[2]&8)
537 NV&=(1<<((EXPREGS[2]&7)+1))-1;
538// else
539// NV&=0;
540 NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);
541 setchr1(A,NV);
542 }
d97315ac 543}
544
545static void M45PW(uint32 A, uint8 V)
546{
547 V&=(EXPREGS[3]&0x3F)^0x3F;
548 V|=EXPREGS[1];
549 setprg8(A,V);
550}
551
552static DECLFW(M45Write)
553{
554 if(EXPREGS[3]&0x40)
555 {
556 WRAM[A-0x6000]=V;
557 return;
558 }
559 EXPREGS[EXPREGS[4]]=V;
560 EXPREGS[4]=(EXPREGS[4]+1)&3;
e2d0dd92 561 if(!EXPREGS[4])
562 {
563 FCEU_printf("CHROR %02x, PRGOR %02x, CHRAND %02x, PRGAND %02x\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);
564 FCEU_printf("CHR0 %03x, CHR1 %03x, PRG0 %03x, PRG1 %03x\n",
565 (0x00&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
566 (0xFF&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
567 (0x00&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]),
568 (0xFF&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]));
569 }
d97315ac 570 FixMMC3PRG(MMC3_cmd);
571 FixMMC3CHR(MMC3_cmd);
572}
573
574static void M45Reset(void)
575{
e2d0dd92 576 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=0;
d97315ac 577 MMC3RegReset();
578}
579
580static void M45Power(void)
581{
e2d0dd92 582 setchr8(0);
d97315ac 583 GenMMC3Power();
584 SetWriteHandler(0x6000,0x7FFF,M45Write);
585}
586
587void Mapper45_Init(CartInfo *info)
588{
589 GenMMC3_Init(info, 512, 256, 8, info->battery);
590 cwrap=M45CW;
591 pwrap=M45PW;
592 info->Reset=M45Reset;
593 info->Power=M45Power;
594 AddExState(EXPREGS, 5, 0, "EXPR");
595}
596
597// ---------------------------- Mapper 47 -------------------------------
598
599static void M47PW(uint32 A, uint8 V)
600{
601 V&=0xF;
602 V|=EXPREGS[0]<<4;
603 setprg8(A,V);
604}
605
606static void M47CW(uint32 A, uint8 V)
607{
608 uint32 NV=V;
609 NV&=0x7F;
610 NV|=EXPREGS[0]<<7;
611 setchr1(A,NV);
612}
613
614static DECLFW(M47Write)
615{
616 EXPREGS[0]=V&1;
617 FixMMC3PRG(MMC3_cmd);
618 FixMMC3CHR(MMC3_cmd);
619}
620
621static void M47Power(void)
622{
623 EXPREGS[0]=0;
624 GenMMC3Power();
625 SetWriteHandler(0x6000,0x7FFF,M47Write);
e2d0dd92 626// SetReadHandler(0x6000,0x7FFF,0);
d97315ac 627}
628
629void Mapper47_Init(CartInfo *info)
630{
631 GenMMC3_Init(info, 512, 256, 8, info->battery);
632 pwrap=M47PW;
633 cwrap=M47CW;
634 info->Power=M47Power;
635 AddExState(EXPREGS, 1, 0, "EXPR");
636}
637
638// ---------------------------- Mapper 49 -------------------------------
639
640static void M49PW(uint32 A, uint8 V)
641{
642 if(EXPREGS[0]&1)
643 {
644 V&=0xF;
645 V|=(EXPREGS[0]&0xC0)>>2;
646 setprg8(A,V);
647 }
648 else
649 setprg32(0x8000,(EXPREGS[0]>>4)&3);
650}
651
652static void M49CW(uint32 A, uint8 V)
653{
654 uint32 NV=V;
655 NV&=0x7F;
656 NV|=(EXPREGS[0]&0xC0)<<1;
657 setchr1(A,NV);
658}
659
660static DECLFW(M49Write)
661{
662 if(A001B&0x80)
663 {
664 EXPREGS[0]=V;
665 FixMMC3PRG(MMC3_cmd);
666 FixMMC3CHR(MMC3_cmd);
667 }
668}
669
670static void M49Reset(void)
671{
672 EXPREGS[0]=0;
673 MMC3RegReset();
674}
675
676static void M49Power(void)
677{
678 M49Reset();
679 GenMMC3Power();
680 SetWriteHandler(0x6000,0x7FFF,M49Write);
681 SetReadHandler(0x6000,0x7FFF,0);
682}
683
684void Mapper49_Init(CartInfo *info)
685{
686 GenMMC3_Init(info, 512, 256, 0, 0);
687 cwrap=M49CW;
688 pwrap=M49PW;
689 info->Reset=M49Reset;
690 info->Power=M49Power;
691 AddExState(EXPREGS, 1, 0, "EXPR");
692}
693
694// ---------------------------- Mapper 52 -------------------------------
695
696static void M52PW(uint32 A, uint8 V)
697{
698 uint32 NV=V;
699 NV&=0x1F^((EXPREGS[0]&8)<<1);
700 NV|=((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4;
701 setprg8(A,NV);
702}
703
704static void M52CW(uint32 A, uint8 V)
705{
706 uint32 NV=V;
707 NV&=0xFF^((EXPREGS[0]&0x40)<<1);
708 NV|=(((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7;
709 setchr1(A,NV);
710}
711
712static DECLFW(M52Write)
713{
714 if(EXPREGS[1])
715 {
716 WRAM[A-0x6000]=V;
717 return;
718 }
719 EXPREGS[1]=1;
720 EXPREGS[0]=V;
721 FixMMC3PRG(MMC3_cmd);
722 FixMMC3CHR(MMC3_cmd);
723}
724
725static void M52Reset(void)
726{
727 EXPREGS[0]=EXPREGS[1]=0;
728 MMC3RegReset();
729}
730
731static void M52Power(void)
732{
733 M52Reset();
734 GenMMC3Power();
735 SetWriteHandler(0x6000,0x7FFF,M52Write);
736}
737
738void Mapper52_Init(CartInfo *info)
739{
740 GenMMC3_Init(info, 512, 256, 8, info->battery);
741 cwrap=M52CW;
742 pwrap=M52PW;
743 info->Reset=M52Reset;
744 info->Power=M52Power;
745 AddExState(EXPREGS, 2, 0, "EXPR");
746}
747
748// ---------------------------- Mapper 74 -------------------------------
749
750static void M74CW(uint32 A, uint8 V)
751{
e2d0dd92 752 if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes
753 setchr1r(0x10,A,V);
d97315ac 754 else
e2d0dd92 755 setchr1r(0,A,V);
d97315ac 756}
757
758void Mapper74_Init(CartInfo *info)
759{
760 GenMMC3_Init(info, 512, 256, 8, info->battery);
761 cwrap=M74CW;
e2d0dd92 762 CHRRAMSize=2048;
d97315ac 763 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
764 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
765 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
766}
767
768// ---------------------------- Mapper 114 ------------------------------
769
770static uint8 cmdin;
771uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
772
773static void M114PWRAP(uint32 A, uint8 V)
774{
775 if(EXPREGS[0]&0x80)
776 {
777 setprg16(0x8000,EXPREGS[0]&0xF);
778 setprg16(0xC000,EXPREGS[0]&0xF);
779 }
780 else
781 setprg8(A,V&0x3F);
782}
783
784static DECLFW(M114Write)
785{
786 if(A==0xE003)
787 {
788 IRQa=1;
e2d0dd92 789 IRQLatch=V;
790 IRQReload=1;
d97315ac 791 }
792 else if(A==0xE002)
793 {
794 IRQa=0;
795 X6502_IRQEnd(FCEU_IQEXT);
796 }
797 else switch(A&0xE000)
798 {
799 case 0x8000: setmirror((V&1)^1); break;
800 case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break;
801 case 0xC000: if(!cmdin) break;
802 MMC3_CMDWrite(0x8001,V);
803 cmdin=0;
804 break;
805 }
806}
807
808static DECLFW(M114ExWrite)
809{
810 if(A<=0x7FFF)
811 {
812 EXPREGS[0]=V;
813 FixMMC3PRG(MMC3_cmd);
814 }
815}
816
817static void M114Power(void)
818{
819 GenMMC3Power();
820 SetWriteHandler(0x8000,0xFFFF,M114Write);
821 SetWriteHandler(0x5000,0x7FFF,M114ExWrite);
822}
823
824static void M114Reset(void)
825{
826 EXPREGS[0]=0;
827 MMC3RegReset();
828}
829
830void Mapper114_Init(CartInfo *info)
831{
832 GenMMC3_Init(info, 256, 256, 0, 0);
833 pwrap=M114PWRAP;
834 info->Power=M114Power;
835 info->Reset=M114Reset;
836 AddExState(EXPREGS, 1, 0, "EXPR");
837 AddExState(&cmdin, 1, 0, "CMDIN");
838}
839
840// ---------------------------- Mapper 115 ------------------------------
841
842static void M115PW(uint32 A, uint8 V)
843{
e2d0dd92 844 if(EXPREGS[0]&0x80)
845 setprg32(0x8000,(EXPREGS[0]&7)>>1);
846 else
847 setprg8(A,V);
d97315ac 848}
849
850static void M115CW(uint32 A, uint8 V)
851{
e2d0dd92 852 setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8));
d97315ac 853}
854
855static DECLFW(M115Write)
856{
857 if(A==0x6000)
858 EXPREGS[0]=V;
859 else if(A==0x6001)
860 EXPREGS[1]=V;
861 FixMMC3PRG(MMC3_cmd);
862}
863
864static void M115Power(void)
865{
866 GenMMC3Power();
867 SetWriteHandler(0x4100,0x7FFF,M115Write);
868 SetReadHandler(0x4100,0x7FFF,0);
869}
870
871void Mapper115_Init(CartInfo *info)
872{
873 GenMMC3_Init(info, 128, 512, 0, 0);
874 cwrap=M115CW;
875 pwrap=M115PW;
876 info->Power=M115Power;
877 AddExState(EXPREGS, 2, 0, "EXPR");
878}
879
880// ---------------------------- Mapper 116 ------------------------------
881
882static void M116CW(uint32 A, uint8 V)
883{
e2d0dd92 884// setchr1(A,V|((EXPREGS[0]&0x4)<<6));
885 if(EXPREGS[0]&2)
886 setchr8r(0x10,0);
887 else
888 setchr1(A,V);
d97315ac 889}
890
891static DECLFW(M116Write)
892{
893 EXPREGS[0]=V;
d97315ac 894 FixMMC3CHR(MMC3_cmd);
895}
896
897static void M116Power(void)
898{
899 GenMMC3Power();
900 SetWriteHandler(0x4100,0x4100,M116Write);
901}
902
903void Mapper116_Init(CartInfo *info)
904{
905 GenMMC3_Init(info, 128, 512, 0, 0);
906 cwrap=M116CW;
907 info->Power=M116Power;
e2d0dd92 908 CHRRAM = (uint8*)FCEU_gmalloc(8192);
909 SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
d97315ac 910 AddExState(EXPREGS, 4, 0, "EXPR");
911}
912
913// ---------------------------- Mapper 118 ------------------------------
914
915static uint8 PPUCHRBus;
916static uint8 TKSMIR[8];
917
918static void FP_FASTAPASS(1) TKSPPU(uint32 A)
919{
920 A&=0x1FFF;
921 A>>=10;
922 PPUCHRBus=A;
923 setmirror(MI_0+TKSMIR[A]);
924}
925
926static void TKSWRAP(uint32 A, uint8 V)
927{
928 TKSMIR[A>>10]=V>>7;
929 setchr1(A,V&0x7F);
930 if(PPUCHRBus==(A>>10))
931 setmirror(MI_0+(V>>7));
932}
933
934void Mapper118_Init(CartInfo *info)
935{
936 GenMMC3_Init(info, 512, 256, 8, info->battery);
937 cwrap=TKSWRAP;
938 mwrap=GENNOMWRAP;
939 PPU_hook=TKSPPU;
940 AddExState(&PPUCHRBus, 1, 0, "PPUC");
941}
942
943// ---------------------------- Mapper 119 ------------------------------
944
945static void TQWRAP(uint32 A, uint8 V)
946{
947 setchr1r((V&0x40)>>2,A,V&0x3F);
948}
949
950void Mapper119_Init(CartInfo *info)
951{
952 GenMMC3_Init(info, 512, 64, 0, 0);
953 cwrap=TQWRAP;
954 CHRRAMSize=8192;
955 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
956 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
957}
958
d97315ac 959// ---------------------------- Mapper 165 ------------------------------
960
961static void M165CW(uint32 A, uint8 V)
962{
963 if(V==0)
964 setchr4r(0x10,A,0);
965 else
966 setchr4(A,V>>2);
967}
968
969static void M165PPUFD(void)
970{
971 if(EXPREGS[0]==0xFD)
972 {
973 M165CW(0x0000,DRegBuf[0]);
974 M165CW(0x1000,DRegBuf[2]);
975 }
976}
977
978static void M165PPUFE(void)
979{
980 if(EXPREGS[0]==0xFE)
981 {
982 M165CW(0x0000,DRegBuf[1]);
983 M165CW(0x1000,DRegBuf[4]);
984 }
985}
986
987static void M165CWM(uint32 A, uint8 V)
988{
e2d0dd92 989 if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2))
990 M165PPUFD();
991 if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4))
992 M165PPUFE();
d97315ac 993}
994
995static void FP_FASTAPASS(1) M165PPU(uint32 A)
996{
997 if((A&0x1FF0)==0x1FD0)
998 {
999 EXPREGS[0]=0xFD;
1000 M165PPUFD();
1001 } else if((A&0x1FF0)==0x1FE0)
1002 {
1003 EXPREGS[0]=0xFE;
1004 M165PPUFE();
1005 }
1006}
1007
1008static void M165Power(void)
1009{
1010 EXPREGS[0]=0xFD;
1011 GenMMC3Power();
1012}
1013
1014void Mapper165_Init(CartInfo *info)
1015{
1016 GenMMC3_Init(info, 512, 128, 8, info->battery);
1017 cwrap=M165CWM;
1018 PPU_hook=M165PPU;
1019 info->Power=M165Power;
1020 CHRRAMSize = 4096;
1021 CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
1022 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1023 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1024 AddExState(EXPREGS, 4, 0, "EXPR");
1025}
1026
1027// ---------------------------- Mapper 182 ------------------------------
1028