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