compat hacks for this old version of fceu
[fceu.git] / boards / mmc3.c
CommitLineData
43725da7 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,165,205,245,249,250,254
25*/
26
27#include "mapinc.h"
28#include "mmc3.h"
29
30uint8 MMC3_cmd;
31uint8 *WRAM;
32uint8 *CHRRAM;
33uint32 CHRRAMSize;
34uint8 DRegBuf[8];
35uint8 EXPREGS[8]; /* For bootleg games, mostly. */
36uint8 A000B,A001B;
37int mmc3opts=0;
38
39#undef IRQCount
40#undef IRQLatch
41#undef IRQa
42uint8 IRQCount,IRQLatch,IRQa;
43uint8 IRQReload;
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 wrams;
59static int isRevB=1;
60
61void (*pwrap)(uint32 A, uint8 V);
62void (*cwrap)(uint32 A, uint8 V);
63void (*mwrap)(uint8 V);
64
65void GenMMC3Power(void);
66void FixMMC3PRG(int V);
67void FixMMC3CHR(int V);
68
69void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
70
71// ----------------------------------------------------------------------
72// ------------------------- Generic MM3 Code ---------------------------
73// ----------------------------------------------------------------------
74
75void FixMMC3PRG(int V)
76{
77 if(V&0x40)
78 {
79 pwrap(0xC000,DRegBuf[6]);
80 pwrap(0x8000,~1);
81 }
82 else
83 {
84 pwrap(0x8000,DRegBuf[6]);
85 pwrap(0xC000,~1);
86 }
87 pwrap(0xA000,DRegBuf[7]);
88 pwrap(0xE000,~0);
89}
90
91void FixMMC3CHR(int V)
92{
93 int cbase=(V&0x80)<<5;
94
95 cwrap((cbase^0x000),DRegBuf[0]&(~1));
96 cwrap((cbase^0x400),DRegBuf[0]|1);
97 cwrap((cbase^0x800),DRegBuf[1]&(~1));
98 cwrap((cbase^0xC00),DRegBuf[1]|1);
99
100 cwrap(cbase^0x1000,DRegBuf[2]);
101 cwrap(cbase^0x1400,DRegBuf[3]);
102 cwrap(cbase^0x1800,DRegBuf[4]);
103 cwrap(cbase^0x1c00,DRegBuf[5]);
104
105 if(mwrap) mwrap(A000B);
106}
107
108void MMC3RegReset(void)
109{
110 IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
111
112 DRegBuf[0]=0;
113 DRegBuf[1]=2;
114 DRegBuf[2]=4;
115 DRegBuf[3]=5;
116 DRegBuf[4]=6;
117 DRegBuf[5]=7;
118 DRegBuf[6]=0;
119 DRegBuf[7]=1;
120
121 FixMMC3PRG(0);
122 FixMMC3CHR(0);
123}
124
125DECLFW(MMC3_CMDWrite)
126{
127// FCEU_printf("bs %04x %02x\n",A,V);
128 switch(A&0xE001)
129 {
130 case 0x8000:
131 if((V&0x40) != (MMC3_cmd&0x40))
132 FixMMC3PRG(V);
133 if((V&0x80) != (MMC3_cmd&0x80))
134 FixMMC3CHR(V);
135 MMC3_cmd = V;
136 break;
137 case 0x8001:
138 {
139 int cbase=(MMC3_cmd&0x80)<<5;
140 DRegBuf[MMC3_cmd&0x7]=V;
141 switch(MMC3_cmd&0x07)
142 {
143 case 0: cwrap((cbase^0x000),V&(~1));
144 cwrap((cbase^0x400),V|1);
145 break;
146 case 1: cwrap((cbase^0x800),V&(~1));
147 cwrap((cbase^0xC00),V|1);
148 break;
149 case 2: cwrap(cbase^0x1000,V);
150 break;
151 case 3: cwrap(cbase^0x1400,V);
152 break;
153 case 4: cwrap(cbase^0x1800,V);
154 break;
155 case 5: cwrap(cbase^0x1C00,V);
156 break;
157 case 6:
158 if(MMC3_cmd&0x40)
159 pwrap(0xC000,V);
160 else
161 pwrap(0x8000,V);
162 break;
163 case 7:
164 pwrap(0xA000,V);
165 break;
166 }
167 }
168 break;
169 case 0xA000:
170 if(mwrap) mwrap(V);
171 break;
172 case 0xA001:
173 A001B=V;
174 break;
175 }
176}
177
178DECLFW(MMC3_IRQWrite)
179{
180// FCEU_printf("%04x:%04x\n",A,V);
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--;
200 if((count|isRevB) && !IRQCount)
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
226void GenMMC3Restore(int version)
227{
228 FixMMC3PRG(MMC3_cmd);
229 FixMMC3CHR(MMC3_cmd);
230}
231
232static void GENCWRAP(uint32 A, uint8 V)
233{
234 setchr1(A,V); // Business Wars NEEDS THIS for 8K CHR-RAM
235}
236
237static void GENPWRAP(uint32 A, uint8 V)
238{
239 setprg8(A,V&0x7F); // [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken
240}
241
242static void GENMWRAP(uint8 V)
243{
244 A000B=V;
245 setmirror((V&1)^1);
246}
247
248static void GENNOMWRAP(uint8 V)
249{
250 A000B=V;
251}
252
253static DECLFW(MBWRAMMMC6)
254{
255 WRAM[A&0x3ff]=V;
256}
257
258static DECLFR(MAWRAMMMC6)
259{
260 return(WRAM[A&0x3ff]);
261}
262
263void GenMMC3Power(void)
264{
265 if(UNIFchrrama) setchr8(0);
266
267 SetWriteHandler(0x8000,0xBFFF,MMC3_CMDWrite);
268 SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
269 SetReadHandler(0x8000,0xFFFF,CartBR);
270 A001B=A000B=0;
271 setmirror(1);
272 if(mmc3opts&1)
273 {
274 if(wrams==1024)
275 {
276 FCEU_CheatAddRAM(1,0x7000,WRAM);
277 SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
278 SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
ebde7d27 279#ifdef ASM_6502
280 // asm code needs pages to be set again..
281 Page[14]=WRAM-0x7000;
282 Page[15]=WRAM-0x7800;
283#endif
43725da7 284 }
285 else
286 {
287 FCEU_CheatAddRAM((wrams&0x1fff)>>10,0x6000,WRAM);
288 SetWriteHandler(0x6000,0x6000 + ((wrams - 1) & 0x1fff),CartBW);
289 SetReadHandler(0x6000,0x6000 + ((wrams - 1) & 0x1fff),CartBR);
290 setprg8r(0x10,0x6000,0);
291 }
292 if(!(mmc3opts&2))
293 FCEU_dwmemset(WRAM,0,wrams);
294 }
295 MMC3RegReset();
296 if(CHRRAM)
297 FCEU_dwmemset(CHRRAM,0,CHRRAMSize);
298}
299
300static void GenMMC3Close(void)
301{
302 if(CHRRAM)
303 FCEU_gfree(CHRRAM);
304 if(WRAM)
305 FCEU_gfree(WRAM);
306 CHRRAM=WRAM=NULL;
307}
308
309void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery)
310{
311 pwrap=GENPWRAP;
312 cwrap=GENCWRAP;
313 mwrap=GENMWRAP;
314
315 wrams=wram<<10;
316
317 PRGmask8[0]&=(prg>>13)-1;
318 CHRmask1[0]&=(chr>>10)-1;
319 CHRmask2[0]&=(chr>>11)-1;
320
321 if(wram)
322 {
323 mmc3opts|=1;
324 WRAM=(uint8*)FCEU_gmalloc(wrams);
325 SetupCartPRGMapping(0x10,WRAM,wrams,1);
326 AddExState(WRAM, wrams, 0, "MRAM");
327 }
328
329 if(battery)
330 {
331 mmc3opts|=2;
332 info->SaveGame[0]=WRAM;
333 info->SaveGameLen[0]=wrams;
334 }
335
336 AddExState(MMC3_StateRegs, ~0, 0, 0);
337
338 info->Power=GenMMC3Power;
339 info->Reset=MMC3RegReset;
340 info->Close=GenMMC3Close;
341
342 if(info->CRC32 == 0x5104833e) // Kick Master
343 GameHBIRQHook = MMC3_hb_KickMasterHack;
344 else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93
345 GameHBIRQHook = MMC3_hb_KickMasterHack;
346 else if(info->CRC32 == 0xfcd772eb) // PAL Star Wars, similar problem as Kick Master.
347 GameHBIRQHook = MMC3_hb_PALStarWarsHack;
348 else
349 GameHBIRQHook=MMC3_hb;
350 GameStateRestore=GenMMC3Restore;
351}
352
353// ----------------------------------------------------------------------
354// -------------------------- MMC3 Based Code ---------------------------
355// ----------------------------------------------------------------------
356
357// ---------------------------- Mapper 4 --------------------------------
358
359static int hackm4=0;/* For Karnov, maybe others. BLAH. Stupid iNES format.*/
360
361static void M4Power(void)
362{
363 GenMMC3Power();
364 A000B=(hackm4^1)&1;
365 setmirror(hackm4);
366}
367
368void Mapper4_Init(CartInfo *info)
369{
370 int ws=8;
371
372 if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84))
373 {
374 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");
375 ws=0;
376 }
377 GenMMC3_Init(info,512,256,ws,info->battery);
378 info->Power=M4Power;
379 hackm4=info->mirror;
380}
381
382// ---------------------------- Mapper 12 -------------------------------
383
384static void M12CW(uint32 A, uint8 V)
385{
386 setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V);
387}
388
389static DECLFW(M12Write)
390{
391 EXPREGS[0]=V&0x01;
392 EXPREGS[1]=(V&0x10)>>4;
393}
394
395static void M12Power(void)
396{
397 EXPREGS[0]=EXPREGS[1]=0;
398 GenMMC3Power();
399 SetWriteHandler(0x4100,0x5FFF,M12Write);
400}
401
402void Mapper12_Init(CartInfo *info)
403{
404 GenMMC3_Init(info, 512, 256, 8, info->battery);
405 cwrap=M12CW;
406 info->Power=M12Power;
407 AddExState(EXPREGS, 2, 0, "EXPR");
408}
409
410// ---------------------------- Mapper 37 -------------------------------
411
412static void M37PW(uint32 A, uint8 V)
413{
414 if(EXPREGS[0]!=2)
415 V&=0x7;
416 else
417 V&=0xF;
418 V|=EXPREGS[0]<<3;
419 setprg8(A,V);
420}
421
422static void M37CW(uint32 A, uint8 V)
423{
424 uint32 NV=V;
425 NV&=0x7F;
426 NV|=EXPREGS[0]<<6;
427 setchr1(A,NV);
428}
429
430static DECLFW(M37Write)
431{
432 EXPREGS[0]=(V&6)>>1;
433 FixMMC3PRG(MMC3_cmd);
434 FixMMC3CHR(MMC3_cmd);
435}
436
437static void M37Reset(void)
438{
439 EXPREGS[0]=0;
440 MMC3RegReset();
441}
442
443static void M37Power(void)
444{
445 EXPREGS[0]=0;
446 GenMMC3Power();
447 SetWriteHandler(0x6000,0x7FFF,M37Write);
448}
449
450void Mapper37_Init(CartInfo *info)
451{
452 GenMMC3_Init(info, 512, 256, 8, info->battery);
453 pwrap=M37PW;
454 cwrap=M37CW;
455 info->Power=M37Power;
456 info->Reset=M37Reset;
457 AddExState(EXPREGS, 1, 0, "EXPR");
458}
459
460// ---------------------------- Mapper 44 -------------------------------
461
462static void M44PW(uint32 A, uint8 V)
463{
464 uint32 NV=V;
465 if(EXPREGS[0]>=6) NV&=0x1F;
466 else NV&=0x0F;
467 NV|=EXPREGS[0]<<4;
468 setprg8(A,NV);
469}
470
471static void M44CW(uint32 A, uint8 V)
472{
473 uint32 NV=V;
474 if(EXPREGS[0]<6) NV&=0x7F;
475 NV|=EXPREGS[0]<<7;
476 setchr1(A,NV);
477}
478
479static DECLFW(M44Write)
480{
481 if(A&1)
482 {
483 EXPREGS[0]=V&7;
484 FixMMC3PRG(MMC3_cmd);
485 FixMMC3CHR(MMC3_cmd);
486 }
487 else
488 MMC3_CMDWrite(A,V);
489}
490
491static void M44Power(void)
492{
493 EXPREGS[0]=0;
494 GenMMC3Power();
495 SetWriteHandler(0xA000,0xBFFF,M44Write);
496}
497
498void Mapper44_Init(CartInfo *info)
499{
500 GenMMC3_Init(info, 512, 256, 8, info->battery);
501 cwrap=M44CW;
502 pwrap=M44PW;
503 info->Power=M44Power;
504 AddExState(EXPREGS, 1, 0, "EXPR");
505}
506
507// ---------------------------- Mapper 45 -------------------------------
508
509static void M45CW(uint32 A, uint8 V)
510{
511 if(!UNIFchrrama)
512 {
513 uint32 NV=V;
514 if(EXPREGS[2]&8)
515 NV&=(1<<((EXPREGS[2]&7)+1))-1;
516 else
517 if(EXPREGS[2])
518 NV&=0; // hack ;( don't know exactly how it should be
519 NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);
520 setchr1(A,NV);
521 }
522}
523
524static void M45PW(uint32 A, uint8 V)
525{
526 V&=(EXPREGS[3]&0x3F)^0x3F;
527 V|=EXPREGS[1];
528 setprg8(A,V);
529}
530
531static DECLFW(M45Write)
532{
533 if(EXPREGS[3]&0x40)
534 {
535 WRAM[A-0x6000]=V;
536 return;
537 }
538 EXPREGS[EXPREGS[4]]=V;
539 EXPREGS[4]=(EXPREGS[4]+1)&3;
540// if(!EXPREGS[4])
541// {
542// FCEU_printf("CHROR %02x, PRGOR %02x, CHRAND %02x, PRGAND %02x\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);
543// FCEU_printf("CHR0 %03x, CHR1 %03x, PRG0 %03x, PRG1 %03x\n",
544// (0x00&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
545// (0xFF&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
546// (0x00&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]),
547// (0xFF&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]));
548// }
549 FixMMC3PRG(MMC3_cmd);
550 FixMMC3CHR(MMC3_cmd);
551}
552
553static DECLFR(M45Read)
554{
555 uint32 addr = 1<<(EXPREGS[5]+4);
556 if(A&(addr|(addr-1)))
557 return X.DB | 1;
558 else
559 return X.DB;
560}
561
562static void M45Reset(void)
563{
564 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=0;
565 EXPREGS[5]++;
566 EXPREGS[5] &= 7;
567 MMC3RegReset();
568}
569
570static void M45Power(void)
571{
572 setchr8(0);
573 GenMMC3Power();
574 EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=EXPREGS[5]=0;
575 SetWriteHandler(0x5000,0x7FFF,M45Write);
576 SetReadHandler(0x5000,0x5FFF,M45Read);
577}
578
579void Mapper45_Init(CartInfo *info)
580{
581 GenMMC3_Init(info, 512, 256, 8, info->battery);
582 cwrap=M45CW;
583 pwrap=M45PW;
584 info->Reset=M45Reset;
585 info->Power=M45Power;
586 AddExState(EXPREGS, 5, 0, "EXPR");
587}
588
589// ---------------------------- Mapper 47 -------------------------------
590
591static void M47PW(uint32 A, uint8 V)
592{
593 V&=0xF;
594 V|=EXPREGS[0]<<4;
595 setprg8(A,V);
596}
597
598static void M47CW(uint32 A, uint8 V)
599{
600 uint32 NV=V;
601 NV&=0x7F;
602 NV|=EXPREGS[0]<<7;
603 setchr1(A,NV);
604}
605
606static DECLFW(M47Write)
607{
608 EXPREGS[0]=V&1;
609 FixMMC3PRG(MMC3_cmd);
610 FixMMC3CHR(MMC3_cmd);
611}
612
613static void M47Power(void)
614{
615 EXPREGS[0]=0;
616 GenMMC3Power();
617 SetWriteHandler(0x6000,0x7FFF,M47Write);
618// SetReadHandler(0x6000,0x7FFF,0);
619}
620
621void Mapper47_Init(CartInfo *info)
622{
623 GenMMC3_Init(info, 512, 256, 8, 0);
624 pwrap=M47PW;
625 cwrap=M47CW;
626 info->Power=M47Power;
627 AddExState(EXPREGS, 1, 0, "EXPR");
628}
629
630// ---------------------------- Mapper 49 -------------------------------
631
632static void M49PW(uint32 A, uint8 V)
633{
634 if(EXPREGS[0]&1)
635 {
636 V&=0xF;
637 V|=(EXPREGS[0]&0xC0)>>2;
638 setprg8(A,V);
639 }
640 else
641 setprg32(0x8000,(EXPREGS[0]>>4)&3);
642}
643
644static void M49CW(uint32 A, uint8 V)
645{
646 uint32 NV=V;
647 NV&=0x7F;
648 NV|=(EXPREGS[0]&0xC0)<<1;
649 setchr1(A,NV);
650}
651
652static DECLFW(M49Write)
653{
654 if(A001B&0x80)
655 {
656 EXPREGS[0]=V;
657 FixMMC3PRG(MMC3_cmd);
658 FixMMC3CHR(MMC3_cmd);
659 }
660}
661
662static void M49Reset(void)
663{
664 EXPREGS[0]=0;
665 MMC3RegReset();
666}
667
668static void M49Power(void)
669{
670 M49Reset();
671 GenMMC3Power();
672 SetWriteHandler(0x6000,0x7FFF,M49Write);
673 SetReadHandler(0x6000,0x7FFF,0);
674}
675
676void Mapper49_Init(CartInfo *info)
677{
678 GenMMC3_Init(info, 512, 256, 0, 0);
679 cwrap=M49CW;
680 pwrap=M49PW;
681 info->Reset=M49Reset;
682 info->Power=M49Power;
683 AddExState(EXPREGS, 1, 0, "EXPR");
684}
685
686// ---------------------------- Mapper 52 -------------------------------
687static void M52PW(uint32 A, uint8 V)
688{
689 uint32 mask = 0x1F^((EXPREGS[0]&8)<<1);
690 uint32 bank = ((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4;
691 setprg8(A, bank|(V & mask));
692}
693
694static void M52CW(uint32 A, uint8 V)
695{
696 uint32 mask = 0xFF^((EXPREGS[0]&0x40)<<1);
697// uint32 bank = (((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7;
698 uint32 bank = (((EXPREGS[0]>>4)&2)|(EXPREGS[0]&4)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7; // actually 256K CHR banks index bits is inverted!
699 setchr1(A, bank|(V & mask));
700}
701
702static DECLFW(M52Write)
703{
704 if(EXPREGS[1])
705 {
706 WRAM[A-0x6000]=V;
707 return;
708 }
709 EXPREGS[1]=V&0x80;
710 EXPREGS[0]=V;
711 FixMMC3PRG(MMC3_cmd);
712 FixMMC3CHR(MMC3_cmd);
713}
714
715static void M52Reset(void)
716{
717 EXPREGS[0]=EXPREGS[1]=0;
718 MMC3RegReset();
719}
720
721static void M52Power(void)
722{
723 M52Reset();
724 GenMMC3Power();
725 SetWriteHandler(0x6000,0x7FFF,M52Write);
726}
727
728void Mapper52_Init(CartInfo *info)
729{
730 GenMMC3_Init(info, 256, 256, 8, info->battery);
731 cwrap=M52CW;
732 pwrap=M52PW;
733 info->Reset=M52Reset;
734 info->Power=M52Power;
735 AddExState(EXPREGS, 2, 0, "EXPR");
736}
737
738// ---------------------------- Mapper 74 -------------------------------
739
740static void M74CW(uint32 A, uint8 V)
741{
742 if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes
743 setchr1r(0x10,A,V);
744 else
745 setchr1r(0,A,V);
746}
747
748void Mapper74_Init(CartInfo *info)
749{
750 GenMMC3_Init(info, 512, 256, 8, info->battery);
751 cwrap=M74CW;
752 CHRRAMSize=2048;
753 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
754 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
755 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
756}
757
758// ---------------------------- Mapper 114 ------------------------------
759
760static uint8 cmdin;
761uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
762
763static void M114PWRAP(uint32 A, uint8 V)
764{
765 if(EXPREGS[0]&0x80)
766 {
767// FCEU_printf("8000-C000:%02X\n",EXPREGS[0]&0xF);
768 setprg16(0x8000,EXPREGS[0]&0xF);
769 setprg16(0xC000,EXPREGS[0]&0xF);
770 }
771 else {
772// FCEU_printf("%04X:%02X\n",A,V&0x3F);
773 setprg8(A,V&0x3F);
774 }
775}
776
777static DECLFW(M114Write)
778{
779 switch(A&0xE001)
780 {
781 case 0x8001: MMC3_CMDWrite(0xA000,V); break;
782 case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break;
783 case 0xC000: if(!cmdin) break; MMC3_CMDWrite(0x8001,V); cmdin=0; break;
784 case 0xA001: IRQLatch=V; break;
785 case 0xC001: IRQReload=1; break;
786 case 0xE000: X6502_IRQEnd(FCEU_IQEXT);IRQa=0; break;
787 case 0xE001: IRQa=1; break;
788 }
789}
790
791static DECLFW(M114ExWrite)
792{
793 if(A<=0x7FFF)
794 {
795 EXPREGS[0]=V;
796 FixMMC3PRG(MMC3_cmd);
797 }
798}
799
800static void M114Power(void)
801{
802 GenMMC3Power();
803 SetWriteHandler(0x8000,0xFFFF,M114Write);
804 SetWriteHandler(0x5000,0x7FFF,M114ExWrite);
805}
806
807static void M114Reset(void)
808{
809 EXPREGS[0]=0;
810 MMC3RegReset();
811}
812
813void Mapper114_Init(CartInfo *info)
814{
815 isRevB=0;
816 GenMMC3_Init(info, 256, 256, 0, 0);
817 pwrap=M114PWRAP;
818 info->Power=M114Power;
819 info->Reset=M114Reset;
820 AddExState(EXPREGS, 1, 0, "EXPR");
821 AddExState(&cmdin, 1, 0, "CMDI");
822}
823
824// ---------------------------- Mapper 115 KN-658 board ------------------------------
825
826static void M115PW(uint32 A, uint8 V)
827{
828 if(EXPREGS[0]&0x80)
829 setprg32(0x8000,(EXPREGS[0]&7)>>1);
830 else
831 setprg8(A,V);
832}
833
834static void M115CW(uint32 A, uint8 V)
835{
836 setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8));
837}
838
839static DECLFW(M115Write)
840{
841// FCEU_printf("%04x:%04x\n",A,V);
842 if(A==0x5080) EXPREGS[2]=V;
843 if(A==0x6000)
844 EXPREGS[0]=V;
845 else if(A==0x6001)
846 EXPREGS[1]=V;
847 FixMMC3PRG(MMC3_cmd);
848}
849
850static DECLFR(M115Read)
851{
852 return EXPREGS[2];
853}
854
855static void M115Power(void)
856{
857 GenMMC3Power();
858 SetWriteHandler(0x4100,0x7FFF,M115Write);
859 SetReadHandler(0x5000,0x5FFF,M115Read);
860}
861
862void Mapper115_Init(CartInfo *info)
863{
864 GenMMC3_Init(info, 128, 512, 0, 0);
865 cwrap=M115CW;
866 pwrap=M115PW;
867 info->Power=M115Power;
868 AddExState(EXPREGS, 2, 0, "EXPR");
869}
870
871// ---------------------------- Mapper 118 ------------------------------
872
873static uint8 PPUCHRBus;
874static uint8 TKSMIR[8];
875
876static void FP_FASTAPASS(1) TKSPPU(uint32 A)
877{
878 A&=0x1FFF;
879 A>>=10;
880 PPUCHRBus=A;
881 setmirror(MI_0+TKSMIR[A]);
882}
883
884static void TKSWRAP(uint32 A, uint8 V)
885{
886 TKSMIR[A>>10]=V>>7;
887 setchr1(A,V&0x7F);
888 if(PPUCHRBus==(A>>10))
889 setmirror(MI_0+(V>>7));
890}
891
892// ---------------------------- Mapper 119 ------------------------------
893
894static void TQWRAP(uint32 A, uint8 V)
895{
896 setchr1r((V&0x40)>>2,A,V&0x3F);
897}
898
899void Mapper119_Init(CartInfo *info)
900{
901 GenMMC3_Init(info, 512, 64, 0, 0);
902 cwrap=TQWRAP;
903 CHRRAMSize=8192;
904 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
905 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
906}
907
908// ---------------------------- Mapper 134 ------------------------------
909
910static void M134PW(uint32 A, uint8 V)
911{
912 setprg8(A,(V&0x1F)|((EXPREGS[0]&2)<<4));
913}
914
915static void M134CW(uint32 A, uint8 V)
916{
917 setchr1(A,(V&0xFF)|((EXPREGS[0]&0x20)<<3));
918}
919
920static DECLFW(M134Write)
921{
922 EXPREGS[0]=V;
923 FixMMC3CHR(MMC3_cmd);
924 FixMMC3PRG(MMC3_cmd);
925}
926
927static void M134Power(void)
928{
929 EXPREGS[0]=0;
930 GenMMC3Power();
931 SetWriteHandler(0x6001,0x6001,M134Write);
932}
933
934static void M134Reset(void)
935{
936 EXPREGS[0]=0;
937 MMC3RegReset();
938}
939
940void Mapper134_Init(CartInfo *info)
941{
942 GenMMC3_Init(info, 256, 256, 0, 0);
943 pwrap=M134PW;
944 cwrap=M134CW;
945 info->Power=M134Power;
946 info->Reset=M134Reset;
947 AddExState(EXPREGS, 4, 0, "EXPR");
948}
949
950// ---------------------------- Mapper 165 ------------------------------
951
952static void M165CW(uint32 A, uint8 V)
953{
954 if(V==0)
955 setchr4r(0x10,A,0);
956 else
957 setchr4(A,V>>2);
958}
959
960static void M165PPUFD(void)
961{
962 if(EXPREGS[0]==0xFD)
963 {
964 M165CW(0x0000,DRegBuf[0]);
965 M165CW(0x1000,DRegBuf[2]);
966 }
967}
968
969static void M165PPUFE(void)
970{
971 if(EXPREGS[0]==0xFE)
972 {
973 M165CW(0x0000,DRegBuf[1]);
974 M165CW(0x1000,DRegBuf[4]);
975 }
976}
977
978static void M165CWM(uint32 A, uint8 V)
979{
980 if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2))
981 M165PPUFD();
982 if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4))
983 M165PPUFE();
984}
985
986static void FP_FASTAPASS(1) M165PPU(uint32 A)
987{
988 if((A&0x1FF0)==0x1FD0)
989 {
990 EXPREGS[0]=0xFD;
991 M165PPUFD();
992 } else if((A&0x1FF0)==0x1FE0)
993 {
994 EXPREGS[0]=0xFE;
995 M165PPUFE();
996 }
997}
998
999static void M165Power(void)
1000{
1001 EXPREGS[0]=0xFD;
1002 GenMMC3Power();
1003}
1004
1005void Mapper165_Init(CartInfo *info)
1006{
1007 GenMMC3_Init(info, 512, 128, 8, info->battery);
1008 cwrap=M165CWM;
1009 PPU_hook=M165PPU;
1010 info->Power=M165Power;
1011 CHRRAMSize = 4096;
1012 CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
1013 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1014 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1015 AddExState(EXPREGS, 4, 0, "EXPR");
1016}
1017
1018// ---------------------------- Mapper 191 ------------------------------
1019
1020static void M191CW(uint32 A, uint8 V)
1021{
1022 setchr1r((V&0x80)>>3,A,V);
1023}
1024
1025void Mapper191_Init(CartInfo *info)
1026{
1027 GenMMC3_Init(info, 256, 256, 8, info->battery);
1028 cwrap=M191CW;
1029 CHRRAMSize=2048;
1030 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1031 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1032 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1033}
1034
1035// ---------------------------- Mapper 192 -------------------------------
1036
1037static void M192CW(uint32 A, uint8 V)
1038{
1039 if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese),
1040 setchr1r(0x10,A,V);
1041 else
1042 setchr1r(0,A,V);
1043}
1044
1045void Mapper192_Init(CartInfo *info)
1046{
1047 GenMMC3_Init(info, 512, 256, 8, info->battery);
1048 cwrap=M192CW;
1049 CHRRAMSize=4096;
1050 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1051 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1052 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1053}
1054
1055// ---------------------------- Mapper 194 -------------------------------
1056
1057static void M194CW(uint32 A, uint8 V)
1058{
1059 if(V<=1) //Dai-2-Ji - Super Robot Taisen (As).nes
1060 setchr1r(0x10,A,V);
1061 else
1062 setchr1r(0,A,V);
1063}
1064
1065void Mapper194_Init(CartInfo *info)
1066{
1067 GenMMC3_Init(info, 512, 256, 8, info->battery);
1068 cwrap=M194CW;
1069 CHRRAMSize=2048;
1070 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1071 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1072 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1073}
1074
1075// ---------------------------- Mapper 195 -------------------------------
1076static uint8 *wramtw;
1077static uint16 wramsize;
1078
1079static void M195CW(uint32 A, uint8 V)
1080{
1081 if(V<=3) // Crystalis (c).nes, Captain Tsubasa Vol 2 - Super Striker (C)
1082 setchr1r(0x10,A,V);
1083 else
1084 setchr1r(0,A,V);
1085}
1086
1087static void M195Power(void)
1088{
1089 GenMMC3Power();
1090 setprg4r(0x10,0x5000,0);
1091 SetWriteHandler(0x5000,0x5fff,CartBW);
1092 SetReadHandler(0x5000,0x5fff,CartBR);
1093}
1094
1095static void M195Close(void)
1096{
1097 if(wramtw)
1098 FCEU_gfree(wramtw);
1099 wramtw=NULL;
1100}
1101
1102void Mapper195_Init(CartInfo *info)
1103{
1104 GenMMC3_Init(info, 512, 256, 8, info->battery);
1105 cwrap=M195CW;
1106 info->Power=M195Power;
1107 info->Close=M195Close;
1108 CHRRAMSize=4096;
1109 CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1110 SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1111 wramsize=4096;
1112 wramtw=(uint8*)FCEU_gmalloc(wramsize);
1113 SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
1114 AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1115 AddExState(wramtw, wramsize, 0, "TRAM");
1116}
1117
1118// ---------------------------- Mapper 196 -------------------------------
1119// MMC3 board with optional command address line connection, allows to
1120// make three-four different wirings to IRQ address lines and separately to
1121// CMD address line, Mali Boss additionally check if wiring are correct for
1122// game
1123
1124static void M196PW(uint32 A, uint8 V)
1125{
1126 if(EXPREGS[0]) // Tenchi o Kurau II - Shokatsu Koumei Den (J) (C).nes
1127 setprg32(0x8000,EXPREGS[1]);
1128 else
1129 setprg8(A,V);
1130}
1131
1132static DECLFW(Mapper196Write)
1133{
1134 if(A >= 0xC000) {
1135 A=(A&0xFFFE)|((A>>2)&1)|((A>>3)&1);
1136 MMC3_IRQWrite(A,V);
1137 }
1138 else {
1139 A=(A&0xFFFE)|((A>>2)&1)|((A>>3)&1)|((A>>1)&1);
1140 MMC3_CMDWrite(A,V);
1141 }
1142}
1143
1144static DECLFW(Mapper196WriteLo)
1145{
1146 EXPREGS[0]=1;
1147 EXPREGS[1]=(V&0xf)|(V>>4);
1148 FixMMC3PRG(MMC3_cmd);
1149}
1150
1151static void Mapper196Power(void)
1152{
1153 GenMMC3Power();
1154 EXPREGS[0] = EXPREGS[1] = 0;
1155 SetWriteHandler(0x6000,0x6FFF,Mapper196WriteLo);
1156 SetWriteHandler(0x8000,0xFFFF,Mapper196Write);
1157}
1158
1159void Mapper196_Init(CartInfo *info)
1160{
1161 GenMMC3_Init(info, 128, 128, 0, 0);
1162 pwrap=M196PW;
1163 info->Power=Mapper196Power;
1164}
1165
1166// ---------------------------- Mapper 197 -------------------------------
1167
1168static void M197CW(uint32 A, uint8 V)
1169{
1170 if(A==0x0000)
1171 setchr4(0x0000,V>>1);
1172 else if(A==0x1000)
1173 setchr2(0x1000,V);
1174 else if(A==0x1400)
1175 setchr2(0x1800,V);
1176}
1177
1178void Mapper197_Init(CartInfo *info)
1179{
1180 GenMMC3_Init(info, 128, 512, 8, 0);
1181 cwrap=M197CW;
1182}
1183
1184// ---------------------------- Mapper 198 -------------------------------
1185
1186static void M198PW(uint32 A, uint8 V)
1187{
1188 if(V>=0x50) // Tenchi o Kurau II - Shokatsu Koumei Den (J) (C).nes
1189 setprg8(A,V&0x4F);
1190 else
1191 setprg8(A,V);
1192}
1193
1194void Mapper198_Init(CartInfo *info)
1195{
1196 GenMMC3_Init(info, 1024, 256, 8, info->battery);
1197 pwrap=M198PW;
1198 info->Power=M195Power;
1199 info->Close=M195Close;
1200 wramsize=4096;
1201 wramtw=(uint8*)FCEU_gmalloc(wramsize);
1202 SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
1203 AddExState(wramtw, wramsize, 0, "TRAM");
1204}
1205
1206// ---------------------------- Mapper 205 ------------------------------
1207// GN-45 BOARD
1208
1209static void M205PW(uint32 A, uint8 V)
1210{
1211