Page[] mappings in mapper code, X.DB update for games with no controls
[fceu.git] / boards / mmc3.c
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
30 uint8 MMC3_cmd;
31 uint8 *WRAM;
32 uint8 *CHRRAM;
33 uint32 CHRRAMSize;
34 uint8 EXPREGS[8];    /* For bootleg games, mostly. */
35
36 static uint8 A000B,A001B;
37 static uint8 DRegBuf[8];
38
39 #undef IRQCount
40 #undef IRQLatch
41 #undef IRQa
42 uint8 IRQCount,IRQLatch,IRQa;
43 uint8 IRQReload;
44
45 static 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
58 static int mmc3opts=0;
59 static int wrams;
60 static int isRevB=1;
61
62 void (*pwrap)(uint32 A, uint8 V);
63 void (*cwrap)(uint32 A, uint8 V);
64 void (*mwrap)(uint8 V);
65
66 void GenMMC3Power(void);
67 void FixMMC3PRG(int V);
68 void FixMMC3CHR(int V);
69
70 void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
71
72 // ----------------------------------------------------------------------
73 // ------------------------- Generic MM3 Code ---------------------------
74 // ----------------------------------------------------------------------
75
76 void 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
92 void 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
107 void 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
124 DECLFW(MMC3_CMDWrite)
125 {
126 // FCEU_printf("%04x:%04x\n",A,V);
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;
173        Write_IRQFM(0x4017,0x40);
174        break;
175  }
176 }
177
178 DECLFW(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
190 static 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
209 static void MMC3_hb(void)
210 {
211  ClockMMC3Counter();
212 }
213
214 static void MMC3_hb_KickMasterHack(void)
215 {
216  if(scanline==238) ClockMMC3Counter();
217  ClockMMC3Counter();
218 }
219
220 static void MMC3_hb_PALStarWarsHack(void)
221 {
222  if(scanline==240) ClockMMC3Counter();
223  ClockMMC3Counter();
224 }
225
226 void GenMMC3Restore(int version)
227 {
228  if(mwrap) mwrap(A000B&1);
229  FixMMC3PRG(MMC3_cmd);
230  FixMMC3CHR(MMC3_cmd);
231 }
232
233 static void GENCWRAP(uint32 A, uint8 V)
234 {
235  if(!UNIFchrrama) setchr1(A,V);
236 }
237
238 static void GENPWRAP(uint32 A, uint8 V)
239 {
240  setprg8(A,V&0x3F);
241 }
242
243 static void GENMWRAP(uint8 V)
244 {
245  A000B=V;
246  setmirror(V^1);
247 }
248
249 static void GENNOMWRAP(uint8 V)
250 {
251  A000B=V;
252 }
253
254 static DECLFW(MBWRAM)
255 {
256   WRAM[A-0x6000]=V;
257 }
258
259 static DECLFR(MAWRAM)
260 {
261  return(WRAM[A-0x6000]);
262 }
263
264 static DECLFW(MBWRAMMMC6)
265 {
266  WRAM[A&0x3ff]=V;
267 }
268
269 static DECLFR(MAWRAMMMC6)
270 {
271  return(WRAM[A&0x3ff]);
272 }
273
274 void GenMMC3Power(void)
275 {
276  if(UNIFchrrama) setchr8(0);
277
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 #ifdef ASM_6502
291    // asm code needs pages to be set again..
292    Page[14]=Page[15]=WRAM-0x7000;
293 #endif
294   }
295   else
296   {
297    FCEU_CheatAddRAM(wrams>>10,0x6000,WRAM);
298    SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
299    SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
300 #ifdef ASM_6502
301    {
302     int addr;
303     for (addr=0x6000; addr < 0x6000+wrams-0x7ff; addr += 0x800)
304     {
305      Page[addr>>11]=WRAM - 0x6000;
306     }
307    }
308 #endif
309   }
310   if(!(mmc3opts&2))
311      FCEU_dwmemset(WRAM,0,wrams);
312  }
313  MMC3RegReset();
314  if(CHRRAM)
315   FCEU_dwmemset(CHRRAM,0,CHRRAMSize);
316 }
317
318 static void GenMMC3Close(void)
319 {
320  if(CHRRAM)
321     FCEU_gfree(CHRRAM);
322  if(WRAM)
323     FCEU_gfree(WRAM);
324  CHRRAM=WRAM=NULL;
325 }
326
327 //static uint16 _a12;
328 //static void FP_FASTAPASS(1) MMC3_PPU(uint32 A)
329 //{
330 //  if(A&0x2000)return;
331 //  if((!_a12)&&(A&0x1000))
332 //    ClockMMC3Counter();
333 //  _a12=A&0x1000;
334 //}
335
336 void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery)
337 {
338  pwrap=GENPWRAP;
339  cwrap=GENCWRAP;
340  mwrap=GENMWRAP;
341
342  wrams=wram<<10;
343
344  PRGmask8[0]&=(prg>>13)-1;
345  CHRmask1[0]&=(chr>>10)-1;
346  CHRmask2[0]&=(chr>>11)-1;
347
348  if(wram)
349  {
350   mmc3opts|=1;
351   WRAM=(uint8*)FCEU_gmalloc(wrams);
352   AddExState(WRAM, wrams, 0, "WRAM");
353  }
354
355  if(battery)
356  {
357   mmc3opts|=2;
358   info->SaveGame[0]=WRAM;
359   info->SaveGameLen[0]=wrams;
360  }
361
362 // if(!chr) // duplicated CHR RAM set up
363 // {
364 //  CHRRAM=(uint8*)FCEU_gmalloc(8192);
365 //  CHRRAMSize=8192;
366 //  SetupCartCHRMapping(0, CHRRAM, 8192, 1);
367 //  AddExState(CHRRAM, 8192, 0, "CHRR");
368 // }
369
370  AddExState(MMC3_StateRegs, ~0, 0, 0);
371
372  info->Power=GenMMC3Power;
373  info->Reset=MMC3RegReset;
374  info->Close=GenMMC3Close;
375
376  if(info->CRC32 == 0x5104833e)        // Kick Master
377   GameHBIRQHook = MMC3_hb_KickMasterHack;
378  else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93
379   GameHBIRQHook = MMC3_hb_KickMasterHack;
380  else if(info->CRC32 == 0xfcd772eb)    // PAL Star Wars, similar problem as Kick Master.
381   GameHBIRQHook = MMC3_hb_PALStarWarsHack;
382  else
383  GameHBIRQHook=MMC3_hb;
384 // PPU_hook=MMC3_PPU;
385  GameStateRestore=GenMMC3Restore;
386 }
387
388 // ----------------------------------------------------------------------
389 // -------------------------- MMC3 Based Code ---------------------------
390 // ----------------------------------------------------------------------
391
392 // ---------------------------- Mapper 4 --------------------------------
393
394 static int hackm4=0;/* For Karnov, maybe others.  BLAH.  Stupid iNES format.*/
395
396 static void M4Power(void)
397 {
398  GenMMC3Power();
399  A000B=(hackm4^1)&1;
400  setmirror(hackm4);
401 }
402
403 void Mapper4_Init(CartInfo *info)
404 {
405  int ws=8;
406
407  if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84))
408  {
409   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");
410   ws=0;
411  }
412  GenMMC3_Init(info,512,256,ws,info->battery);
413  info->Power=M4Power;
414  hackm4=info->mirror;
415 }
416
417 // ---------------------------- Mapper 12 -------------------------------
418
419 static void M12CW(uint32 A, uint8 V)
420 {
421  setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V);
422 }
423
424 static DECLFW(M12Write)
425 {
426  EXPREGS[0]=V&0x01;
427  EXPREGS[1]=(V&0x10)>>4;
428 }
429
430 static void M12Power(void)
431 {
432  EXPREGS[0]=EXPREGS[1]=0;
433  GenMMC3Power();
434  SetWriteHandler(0x4100,0x5FFF,M12Write);
435 }
436
437 void Mapper12_Init(CartInfo *info)
438 {
439  GenMMC3_Init(info, 512, 256, 8, info->battery);
440  cwrap=M12CW;
441  info->Power=M12Power;
442  AddExState(EXPREGS, 2, 0, "EXPR");
443 }
444
445 // ---------------------------- Mapper 37 -------------------------------
446
447 static void M37PW(uint32 A, uint8 V)
448 {
449   if(EXPREGS[0]!=2)
450     V&=0x7;
451   else
452     V&=0xF;
453   V|=EXPREGS[0]<<3;
454   setprg8(A,V);
455 }
456
457 static void M37CW(uint32 A, uint8 V)
458 {
459   uint32 NV=V;
460   NV&=0x7F;
461   NV|=EXPREGS[0]<<6;
462   setchr1(A,NV);
463 }
464
465 static DECLFW(M37Write)
466 {
467   EXPREGS[0]=(V&6)>>1;
468   FixMMC3PRG(MMC3_cmd);
469   FixMMC3CHR(MMC3_cmd);
470 }
471
472 static void M37Reset(void)
473 {
474   EXPREGS[0]=0;
475   MMC3RegReset();
476 }
477
478 static void M37Power(void)
479 {
480   EXPREGS[0]=0;
481   GenMMC3Power();
482   SetWriteHandler(0x6000,0x7FFF,M37Write);
483 }
484
485 void Mapper37_Init(CartInfo *info)
486 {
487   GenMMC3_Init(info, 512, 256, 8, info->battery);
488   pwrap=M37PW;
489   cwrap=M37CW;
490   info->Power=M37Power;
491   info->Reset=M37Reset;
492   AddExState(EXPREGS, 1, 0, "EXPR");
493 }
494
495 // ---------------------------- Mapper 44 -------------------------------
496
497 static void M44PW(uint32 A, uint8 V)
498 {
499  uint32 NV=V;
500  if(EXPREGS[0]>=6) NV&=0x1F;
501  else NV&=0x0F;
502  NV|=EXPREGS[0]<<4;
503  setprg8(A,NV);
504 }
505
506 static void M44CW(uint32 A, uint8 V)
507 {
508  uint32 NV=V;
509  if(EXPREGS[0]<6) NV&=0x7F;
510  NV|=EXPREGS[0]<<7;
511  setchr1(A,NV);
512 }
513
514 static DECLFW(M44Write)
515 {
516  if(A&1)
517  {
518   EXPREGS[0]=V&7;
519   FixMMC3PRG(MMC3_cmd);
520   FixMMC3CHR(MMC3_cmd);
521  }
522  else
523   MMC3_CMDWrite(A,V);
524 }
525
526 static void M44Power(void)
527 {
528  EXPREGS[0]=0;
529  GenMMC3Power();
530  SetWriteHandler(0xA000,0xBFFF,M44Write);
531 }
532
533 void Mapper44_Init(CartInfo *info)
534 {
535  GenMMC3_Init(info, 512, 256, 8, info->battery);
536  cwrap=M44CW;
537  pwrap=M44PW;
538  info->Power=M44Power;
539  AddExState(EXPREGS, 1, 0, "EXPR");
540 }
541
542 // ---------------------------- Mapper 45 -------------------------------
543
544 static void M45CW(uint32 A, uint8 V)
545 {
546  if(!UNIFchrrama)
547  {
548    uint32 NV=V;
549    if(EXPREGS[2]&8)
550       NV&=(1<<((EXPREGS[2]&7)+1))-1;
551 //   else
552 //      NV&=0;
553    NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);
554    setchr1(A,NV);
555  }
556 }
557
558 static void M45PW(uint32 A, uint8 V)
559 {
560  V&=(EXPREGS[3]&0x3F)^0x3F;
561  V|=EXPREGS[1];
562  setprg8(A,V);
563 }
564
565 static DECLFW(M45Write)
566 {
567  if(EXPREGS[3]&0x40)
568  {
569   WRAM[A-0x6000]=V;
570   return;
571  }
572  EXPREGS[EXPREGS[4]]=V;
573  EXPREGS[4]=(EXPREGS[4]+1)&3;
574  if(!EXPREGS[4])
575  {
576    FCEU_printf("CHROR %02x, PRGOR %02x, CHRAND %02x, PRGAND %02x\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);
577    FCEU_printf("CHR0 %03x, CHR1 %03x, PRG0 %03x, PRG1 %03x\n",
578                (0x00&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
579                (0xFF&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
580                (0x00&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]),
581                (0xFF&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]));
582  }
583  FixMMC3PRG(MMC3_cmd);
584  FixMMC3CHR(MMC3_cmd);
585 }
586
587 static void M45Reset(void)
588 {
589  EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=0;
590  MMC3RegReset();
591 }
592
593 static void M45Power(void)
594 {
595  setchr8(0);
596  GenMMC3Power();
597  SetWriteHandler(0x6000,0x7FFF,M45Write);
598 }
599
600 void Mapper45_Init(CartInfo *info)
601 {
602  GenMMC3_Init(info, 512, 256, 8, info->battery);
603  cwrap=M45CW;
604  pwrap=M45PW;
605  info->Reset=M45Reset;
606  info->Power=M45Power;
607  AddExState(EXPREGS, 5, 0, "EXPR");
608 }
609
610 // ---------------------------- Mapper 47 -------------------------------
611
612 static void M47PW(uint32 A, uint8 V)
613 {
614  V&=0xF;
615  V|=EXPREGS[0]<<4;
616  setprg8(A,V);
617 }
618
619 static void M47CW(uint32 A, uint8 V)
620 {
621  uint32 NV=V;
622  NV&=0x7F;
623  NV|=EXPREGS[0]<<7;
624  setchr1(A,NV);
625 }
626
627 static DECLFW(M47Write)
628 {
629  EXPREGS[0]=V&1;
630  FixMMC3PRG(MMC3_cmd);
631  FixMMC3CHR(MMC3_cmd);
632 }
633
634 static void M47Power(void)
635 {
636  EXPREGS[0]=0;
637  GenMMC3Power();
638  SetWriteHandler(0x6000,0x7FFF,M47Write);
639 // SetReadHandler(0x6000,0x7FFF,0);
640 }
641
642 void Mapper47_Init(CartInfo *info)
643 {
644  GenMMC3_Init(info, 512, 256, 8, info->battery);
645  pwrap=M47PW;
646  cwrap=M47CW;
647  info->Power=M47Power;
648  AddExState(EXPREGS, 1, 0, "EXPR");
649 }
650
651 // ---------------------------- Mapper 49 -------------------------------
652
653 static void M49PW(uint32 A, uint8 V)
654 {
655  if(EXPREGS[0]&1)
656  {
657   V&=0xF;
658   V|=(EXPREGS[0]&0xC0)>>2;
659   setprg8(A,V);
660  }
661  else
662   setprg32(0x8000,(EXPREGS[0]>>4)&3);
663 }
664
665 static void M49CW(uint32 A, uint8 V)
666 {
667  uint32 NV=V;
668  NV&=0x7F;
669  NV|=(EXPREGS[0]&0xC0)<<1;
670  setchr1(A,NV);
671 }
672
673 static DECLFW(M49Write)
674 {
675  if(A001B&0x80)
676  {
677   EXPREGS[0]=V;
678   FixMMC3PRG(MMC3_cmd);
679   FixMMC3CHR(MMC3_cmd);
680  }
681 }
682
683 static void M49Reset(void)
684 {
685  EXPREGS[0]=0;
686  MMC3RegReset();
687 }
688
689 static void M49Power(void)
690 {
691  M49Reset();
692  GenMMC3Power();
693  SetWriteHandler(0x6000,0x7FFF,M49Write);
694  SetReadHandler(0x6000,0x7FFF,0);
695 }
696
697 void Mapper49_Init(CartInfo *info)
698 {
699  GenMMC3_Init(info, 512, 256, 0, 0);
700  cwrap=M49CW;
701  pwrap=M49PW;
702  info->Reset=M49Reset;
703  info->Power=M49Power;
704  AddExState(EXPREGS, 1, 0, "EXPR");
705 }
706
707 // ---------------------------- Mapper 52 -------------------------------
708
709 static void M52PW(uint32 A, uint8 V)
710 {
711  uint32 NV=V;
712  NV&=0x1F^((EXPREGS[0]&8)<<1);
713  NV|=((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4;
714  setprg8(A,NV);
715 }
716
717 static void M52CW(uint32 A, uint8 V)
718 {
719  uint32 NV=V;
720  NV&=0xFF^((EXPREGS[0]&0x40)<<1);
721  NV|=(((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7;
722  setchr1(A,NV);
723 }
724
725 static DECLFW(M52Write)
726 {
727  if(EXPREGS[1])
728  {
729   WRAM[A-0x6000]=V;
730   return;
731  }
732  EXPREGS[1]=1;
733  EXPREGS[0]=V;
734  FixMMC3PRG(MMC3_cmd);
735  FixMMC3CHR(MMC3_cmd);
736 }
737
738 static void M52Reset(void)
739 {
740  EXPREGS[0]=EXPREGS[1]=0;
741  MMC3RegReset();
742 }
743
744 static void M52Power(void)
745 {
746  M52Reset();
747  GenMMC3Power();
748  SetWriteHandler(0x6000,0x7FFF,M52Write);
749 }
750
751 void Mapper52_Init(CartInfo *info)
752 {
753  GenMMC3_Init(info, 512, 256, 8, info->battery);
754  cwrap=M52CW;
755  pwrap=M52PW;
756  info->Reset=M52Reset;
757  info->Power=M52Power;
758  AddExState(EXPREGS, 2, 0, "EXPR");
759 }
760
761 // ---------------------------- Mapper 74 -------------------------------
762
763 static void M74CW(uint32 A, uint8 V)
764 {
765   if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes
766     setchr1r(0x10,A,V);
767   else
768     setchr1r(0,A,V);
769 }
770
771 void Mapper74_Init(CartInfo *info)
772 {
773  GenMMC3_Init(info, 512, 256, 8, info->battery);
774  cwrap=M74CW;
775  CHRRAMSize=2048;
776  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
777  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
778  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
779 }
780
781 // ---------------------------- Mapper 114 ------------------------------
782
783 static uint8 cmdin;
784 uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
785
786 static void M114PWRAP(uint32 A, uint8 V)
787 {
788   if(EXPREGS[0]&0x80)
789   {
790     setprg16(0x8000,EXPREGS[0]&0xF);
791     setprg16(0xC000,EXPREGS[0]&0xF);
792   }
793   else
794     setprg8(A,V&0x3F);
795 }
796
797 static DECLFW(M114Write)
798 {
799  if(A==0xE003)
800  {
801   IRQa=1;
802   IRQLatch=V;
803   IRQReload=1;
804  }
805  else if(A==0xE002)
806  {
807   IRQa=0;
808   X6502_IRQEnd(FCEU_IQEXT);
809  }
810  else switch(A&0xE000)
811  {
812   case 0x8000: setmirror((V&1)^1); break;
813   case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break;
814   case 0xC000: if(!cmdin) break;
815                MMC3_CMDWrite(0x8001,V);
816                cmdin=0;
817                break;
818  }
819 }
820
821 static DECLFW(M114ExWrite)
822 {
823   if(A<=0x7FFF)
824   {
825    EXPREGS[0]=V;
826    FixMMC3PRG(MMC3_cmd);
827   }
828 }
829
830 static void M114Power(void)
831 {
832  GenMMC3Power();
833  SetWriteHandler(0x8000,0xFFFF,M114Write);
834  SetWriteHandler(0x5000,0x7FFF,M114ExWrite);
835 }
836
837 static void M114Reset(void)
838 {
839  EXPREGS[0]=0;
840  MMC3RegReset();
841 }
842
843 void Mapper114_Init(CartInfo *info)
844 {
845  GenMMC3_Init(info, 256, 256, 0, 0);
846  pwrap=M114PWRAP;
847  info->Power=M114Power;
848  info->Reset=M114Reset;
849  AddExState(EXPREGS, 1, 0, "EXPR");
850  AddExState(&cmdin, 1, 0, "CMDIN");
851 }
852
853 // ---------------------------- Mapper 115 ------------------------------
854
855 static void M115PW(uint32 A, uint8 V)
856 {
857   if(EXPREGS[0]&0x80)
858     setprg32(0x8000,(EXPREGS[0]&7)>>1);
859   else
860     setprg8(A,V);
861 }
862
863 static void M115CW(uint32 A, uint8 V)
864 {
865   setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8));
866 }
867
868 static DECLFW(M115Write)
869 {
870  if(A==0x6000)
871     EXPREGS[0]=V;
872  else if(A==0x6001)
873     EXPREGS[1]=V;
874  FixMMC3PRG(MMC3_cmd);
875 }
876
877 static void M115Power(void)
878 {
879  GenMMC3Power();
880  SetWriteHandler(0x4100,0x7FFF,M115Write);
881  SetReadHandler(0x4100,0x7FFF,0);
882 }
883
884 void Mapper115_Init(CartInfo *info)
885 {
886  GenMMC3_Init(info, 128, 512, 0, 0);
887  cwrap=M115CW;
888  pwrap=M115PW;
889  info->Power=M115Power;
890  AddExState(EXPREGS, 2, 0, "EXPR");
891 }
892
893 // ---------------------------- Mapper 116 ------------------------------
894
895 static void M116CW(uint32 A, uint8 V)
896 {
897 // setchr1(A,V|((EXPREGS[0]&0x4)<<6));
898  if(EXPREGS[0]&2)
899     setchr8r(0x10,0);
900  else
901     setchr1(A,V);
902 }
903
904 static DECLFW(M116Write)
905 {
906  EXPREGS[0]=V;
907  FixMMC3CHR(MMC3_cmd);
908 }
909
910 static void M116Power(void)
911 {
912  GenMMC3Power();
913  SetWriteHandler(0x4100,0x4100,M116Write);
914 }
915
916 void Mapper116_Init(CartInfo *info)
917 {
918  GenMMC3_Init(info, 128, 512, 0, 0);
919  cwrap=M116CW;
920  info->Power=M116Power;
921  CHRRAM = (uint8*)FCEU_gmalloc(8192);
922  SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
923  AddExState(EXPREGS, 4, 0, "EXPR");
924 }
925
926 // ---------------------------- Mapper 118 ------------------------------
927
928 static uint8 PPUCHRBus;
929 static uint8 TKSMIR[8];
930
931 static void FP_FASTAPASS(1) TKSPPU(uint32 A)
932 {
933  A&=0x1FFF;
934  A>>=10;
935  PPUCHRBus=A;
936  setmirror(MI_0+TKSMIR[A]);
937 }
938
939 static void TKSWRAP(uint32 A, uint8 V)
940 {
941  TKSMIR[A>>10]=V>>7;
942  setchr1(A,V&0x7F);
943  if(PPUCHRBus==(A>>10))
944     setmirror(MI_0+(V>>7));
945 }
946
947 void Mapper118_Init(CartInfo *info)
948 {
949  GenMMC3_Init(info, 512, 256, 8, info->battery);
950  cwrap=TKSWRAP;
951  mwrap=GENNOMWRAP;
952  PPU_hook=TKSPPU;
953  AddExState(&PPUCHRBus, 1, 0, "PPUC");
954 }
955
956 // ---------------------------- Mapper 119 ------------------------------
957
958 static void TQWRAP(uint32 A, uint8 V)
959 {
960  setchr1r((V&0x40)>>2,A,V&0x3F);
961 }
962
963 void Mapper119_Init(CartInfo *info)
964 {
965  GenMMC3_Init(info, 512, 64, 0, 0);
966  cwrap=TQWRAP;
967  CHRRAMSize=8192;
968  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
969  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
970 }
971
972 // ---------------------------- Mapper 165 ------------------------------
973
974 static void M165CW(uint32 A, uint8 V)
975 {
976  if(V==0)
977     setchr4r(0x10,A,0);
978  else
979     setchr4(A,V>>2);
980 }
981
982 static void M165PPUFD(void)
983 {
984  if(EXPREGS[0]==0xFD)
985  {
986   M165CW(0x0000,DRegBuf[0]);
987   M165CW(0x1000,DRegBuf[2]);
988  }
989 }
990
991 static void M165PPUFE(void)
992 {
993  if(EXPREGS[0]==0xFE)
994  {
995   M165CW(0x0000,DRegBuf[1]);
996   M165CW(0x1000,DRegBuf[4]);
997  }
998 }
999
1000 static void M165CWM(uint32 A, uint8 V)
1001 {
1002  if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2))
1003    M165PPUFD();
1004  if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4))
1005    M165PPUFE();
1006 }
1007
1008 static void FP_FASTAPASS(1) M165PPU(uint32 A)
1009 {
1010  if((A&0x1FF0)==0x1FD0)
1011  {
1012   EXPREGS[0]=0xFD;
1013   M165PPUFD();
1014  } else if((A&0x1FF0)==0x1FE0)
1015  {
1016   EXPREGS[0]=0xFE;
1017   M165PPUFE();
1018  }
1019 }
1020
1021 static void M165Power(void)
1022 {
1023  EXPREGS[0]=0xFD;
1024  GenMMC3Power();
1025 }
1026
1027 void Mapper165_Init(CartInfo *info)
1028 {
1029  GenMMC3_Init(info, 512, 128, 8, info->battery);
1030  cwrap=M165CWM;
1031  PPU_hook=M165PPU;
1032  info->Power=M165Power;
1033  CHRRAMSize = 4096;
1034  CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
1035  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1036  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1037  AddExState(EXPREGS, 4, 0, "EXPR");
1038 }
1039
1040 // ---------------------------- Mapper 182 ------------------------------
1041 // Ã²Ã Ã¡Ã«Ã¨Ã¶Ã  Ã¯Ã¥Ã°Ã¬Ã³Ã²Ã Ã¶Ã¨ Ã Ã­Ã Ã«Ã®Ã£Ã¨Ã·Ã­Ã  114 Ã¬Ã Ã¯Ã¯Ã¥Ã°Ã³, Ã°Ã¥Ã£Ã¨Ã±Ã²Ã°Ã» Ã¬Ã Ã¯Ã¯Ã¥Ã°Ã  Ã£Ã®Ã°Ã Ã§Ã¤Ã® Ã±Ã«Ã®Ã¦Ã­Ã¥Ã¥,
1042 // Ã·Ã¥Ã¬ Ã¨Ã±Ã¯Ã®Ã«Ã¼Ã§Ã³Ã¾Ã²Ã±Ã¿ Ã§Ã¤Ã¥Ã±Ã¼, ÃµÃ®Ã²Ã¿ Ã¢Ã±Ã¥ Ã¯Ã°Ã¥ÃªÃ°Ã Ã±Ã­Ã® Ã°Ã Ã¡Ã®Ã²Ã Ã¥Ã².
1043
1044 //static uint8 m182_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
1045 static DECLFW(M182Write)
1046 {
1047  switch(A&0xF003)
1048  {
1049   case 0x8001: setmirror((V&1)^1); break;
1050   case 0xA000: MMC3_CMDWrite(0x8000,m114_perm[V&7]); break;
1051   case 0xC000: MMC3_CMDWrite(0x8001,V); break;
1052   case 0xE003: if(V)
1053                {
1054                  IRQLatch=V;
1055                  IRQReload=1;
1056                  IRQa=1;
1057                }
1058                X6502_IRQEnd(FCEU_IQEXT);
1059                break;
1060  }
1061 }
1062
1063 static void M182Power(void)
1064 {
1065  GenMMC3Power();
1066  SetWriteHandler(0x8000,0xFFFF,M182Write);
1067 }
1068
1069 void Mapper182_Init(CartInfo *info)
1070 {
1071  GenMMC3_Init(info, 256, 256, 0, 0);
1072  info->Power=M182Power;
1073 }
1074
1075 // ---------------------------- Mapper 191 ------------------------------
1076
1077 static void M191CW(uint32 A, uint8 V)
1078 {
1079   setchr1r((V&0x80)>>3,A,V);
1080 }
1081
1082 void Mapper191_Init(CartInfo *info)
1083 {
1084  GenMMC3_Init(info, 256, 256, 8, info->battery);
1085  cwrap=M191CW;
1086  CHRRAMSize=2048;
1087  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1088  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1089  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1090 }
1091
1092 // ---------------------------- Mapper 192 -------------------------------
1093
1094 static void M192CW(uint32 A, uint8 V)
1095 {
1096   if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese),
1097     setchr1r(0x10,A,V);
1098   else
1099     setchr1r(0,A,V);
1100 }
1101
1102 void Mapper192_Init(CartInfo *info)
1103 {
1104  GenMMC3_Init(info, 512, 256, 8, info->battery);
1105  cwrap=M192CW;
1106  CHRRAMSize=4096;
1107  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1108  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1109  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1110 }
1111
1112 // ---------------------------- Mapper 194 -------------------------------
1113
1114 static void M194CW(uint32 A, uint8 V)
1115 {
1116   if(V<=1) //Dai-2-Ji - Super Robot Taisen (As).nes
1117     setchr1r(0x10,A,V);
1118   else
1119     setchr1r(0,A,V);
1120 }
1121
1122 void Mapper194_Init(CartInfo *info)
1123 {
1124  GenMMC3_Init(info, 512, 256, 8, info->battery);
1125  cwrap=M194CW;
1126  CHRRAMSize=2048;
1127  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1128  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1129  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1130 }
1131
1132 // ---------------------------- Mapper 198 -------------------------------
1133
1134 static uint8 *wramtw;
1135 static uint16 wramsize;
1136 static void M198CW(uint32 A, uint8 V)
1137 {
1138   if(V<=3) // Crystalis (c).nes, Captain Tsubasa Vol 2 - Super Striker (C)
1139     setchr1r(0x10,A,V);
1140   else
1141     setchr1r(0,A,V);
1142 }
1143
1144 static void M198Power(void)
1145 {
1146  GenMMC3Power();
1147  setprg4r(0x10,0x5000,0);
1148  SetWriteHandler(0x5000,0x5fff,CartBW);
1149  SetReadHandler(0x5000,0x5fff,CartBR);
1150 }
1151
1152 static void M198Close(void)
1153 {
1154   if(wramtw)
1155     FCEU_gfree(wramtw);
1156   wramtw=NULL;
1157 }
1158
1159 void Mapper198_Init(CartInfo *info)
1160 {
1161  GenMMC3_Init(info, 512, 256, 8, info->battery);
1162  cwrap=M198CW;
1163  info->Power=M198Power;
1164  info->Close=M198Close;
1165  CHRRAMSize=4096;
1166  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1167  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1168  wramsize=4096;
1169  wramtw=(uint8*)FCEU_gmalloc(wramsize);
1170  SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
1171  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1172  AddExState(wramtw, wramsize, 0, "WRAMTW");
1173 }
1174
1175 // ---------------------------- Mapper 199 -------------------------------
1176
1177 static uint8 *wramtw;
1178 static uint16 wramsize;
1179 static void M199PW(uint32 A, uint8 V)
1180 {
1181   if(V>=0x50)
1182     setprg8(A,V&0x4F);
1183   else
1184     setprg8(A,V);
1185 }
1186
1187 void Mapper199_Init(CartInfo *info)
1188 {
1189  GenMMC3_Init(info, 1024, 256, 8, info->battery);
1190  pwrap=M199PW;
1191  info->Power=M198Power;
1192  info->Close=M198Close;
1193  wramsize=4096;
1194  wramtw=(uint8*)FCEU_gmalloc(wramsize);
1195  SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
1196  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
1197  AddExState(wramtw, wramsize, 0, "WRAMTW");
1198 }
1199
1200 // ---------------------------- Mapper 205 ------------------------------
1201
1202 static void M205PW(uint32 A, uint8 V)
1203 {
1204  if(EXPREGS[0]&2)
1205     setprg8(A,(V&0x0f)|((EXPREGS[0]&3)<<4));
1206  else
1207     setprg8(A,(V&0x1f)|((EXPREGS[0]&3)<<4));
1208 }
1209
1210 static void M205CW(uint32 A, uint8 V)
1211 {
1212  setchr1(A,V|((EXPREGS[0]&3)<<7));
1213 }
1214
1215 static DECLFW(M205Write)
1216 {
1217  if((A&0x6800)==0x6800) EXPREGS[0]= V;
1218  FixMMC3PRG(MMC3_cmd);
1219  FixMMC3CHR(MMC3_cmd);
1220 }
1221
1222 static void M205Reset(void)
1223 {
1224  EXPREGS[0]=0;
1225  MMC3RegReset();
1226 }
1227
1228 static void M205Power(void)
1229 {
1230  GenMMC3Power();
1231  SetWriteHandler(0x4020,0x7FFF,M205Write);
1232 }
1233
1234 void Mapper205_Init(CartInfo *info)
1235 {
1236  GenMMC3_Init(info, 512, 256, 8, 0);
1237  pwrap=M205PW;
1238  cwrap=M205CW;
1239  info->Power=M205Power;
1240  info->Reset=M205Reset;
1241  AddExState(EXPREGS, 1, 0, "EXPR");
1242 }
1243
1244 // ---------------------------- Mapper 215 ------------------------------
1245
1246 static uint8 m215_perm[8] = {0, 2, 5, 3, 6, 1, 7, 4};
1247
1248 static void M215CW(uint32 A, uint8 V)
1249 {
1250  if(EXPREGS[1]&0x04)
1251    setchr1(A,V|0x100);
1252  else
1253    setchr1(A,(V&0x7F)|((EXPREGS[1]&0x10)<<3));
1254 }
1255
1256 static void M215PW(uint32 A, uint8 V)
1257 {
1258  if(EXPREGS[0]&0x80)
1259  {
1260    setprg16(0x8000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10));
1261    setprg16(0xC000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10));
1262  }
1263  else if(EXPREGS[1]&0x08)
1264         setprg8(A,(V&0x1F)|0x20);
1265       else
1266         setprg8(A,(V&0x0F)|(EXPREGS[1]&0x10));
1267 }
1268
1269 static DECLFW(M215Write)
1270 {
1271  if(!(EXPREGS[2]))
1272  {
1273   if(A >= 0xc000)
1274    MMC3_IRQWrite(A,V);
1275   else
1276    MMC3_CMDWrite(A,V);
1277  }
1278  else switch(A&0xE001)
1279  {
1280   case 0xC001: IRQLatch=V; break;
1281   case 0xA001: IRQReload=1; break;
1282   case 0xE001: IRQa=1; break;
1283   case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break;
1284   case 0xC000: setmirror(((V|(V>>7))&1)^1); break;
1285   case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m215_perm[V&7])); cmdin=1; break;
1286   case 0x8001: if(!cmdin) break;
1287                MMC3_CMDWrite(0x8001,V);
1288                cmdin=0;
1289                break;
1290  }
1291 }
1292
1293 static DECLFW(M215ExWrite)
1294 {
1295  switch(A)
1296  {
1297   case 0x5000:
1298        EXPREGS[0]=V;
1299        FixMMC3PRG(MMC3_cmd);
1300        break;
1301   case 0x5001:
1302        EXPREGS[1]=V;
1303        FixMMC3CHR(MMC3_cmd);
1304        break;
1305   case 0x5007:
1306        EXPREGS[2]=V;
1307        MMC3RegReset();
1308        break;
1309  }
1310 }
1311
1312 static void M215Power(void)
1313 {
1314  EXPREGS[0]=0;
1315  EXPREGS[1]=0xFF;
1316  EXPREGS[2]=4;
1317  GenMMC3Power();
1318  SetWriteHandler(0x8000,0xFFFF,M215Write);
1319  SetWriteHandler(0x5000,0x7FFF,M215ExWrite);
1320 }
1321
1322 void Mapper215_Init(CartInfo *info)
1323 {
1324  GenMMC3_Init(info, 256, 256, 0, 0);
1325  cwrap=M215CW;
1326  pwrap=M215PW;
1327  info->Power=M215Power;
1328  AddExState(EXPREGS, 3, 0, "EXPR");
1329  AddExState(&cmdin, 1, 0, "CMDIN");
1330 }
1331
1332 // ---------------------------- Mapper 217 ------------------------------
1333
1334 static uint8 m217_perm[8] = {0, 6, 3, 7, 5, 2, 4, 1};
1335
1336 static void M217CW(uint32 A, uint8 V)
1337 {
1338  if(EXPREGS[1]&0x08)
1339    setchr1(A,V|((EXPREGS[1]&3)<<8));
1340  else
1341    setchr1(A,(V&0x7F)|((EXPREGS[1]&3)<<8)|((EXPREGS[1]&0x10)<<3));
1342 }
1343
1344 static void M217PW(uint32 A, uint8 V)
1345 {
1346  if(EXPREGS[0]&0x80)
1347  {
1348    setprg16(0x8000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4));
1349    setprg16(0xC000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4));
1350  }
1351  else if(EXPREGS[1]&0x08)
1352         setprg8(A,(V&0x1F)|((EXPREGS[1]&3)<<5));
1353       else
1354         setprg8(A,(V&0x0F)|((EXPREGS[1]&3)<<5)|(EXPREGS[1]&0x10));
1355 }
1356
1357 static DECLFW(M217Write)
1358 {
1359  if(!EXPREGS[2])
1360  {
1361   if(A >= 0xc000)
1362     MMC3_IRQWrite(A, V);
1363   else
1364     MMC3_CMDWrite(A,V);
1365  }
1366  else switch(A&0xE001)
1367  {
1368    case 0x8000: IRQCount=V; break;
1369    case 0xE000: X6502_IRQEnd(FCEU_IQEXT);IRQa=0; break;
1370    case 0xC001: IRQa=1; break;
1371    case 0xA001: setmirror((V&1)^1); break;
1372    case 0x8001: MMC3_CMDWrite(0x8000,(V&0xC0)|(m217_perm[V&7])); cmdin=1; break;
1373    case 0xA000: if(!cmdin) break;
1374                 MMC3_CMDWrite(0x8001,V);
1375                 cmdin=0;
1376                 break;
1377  }
1378 }
1379
1380 static DECLFW(M217ExWrite)
1381 {
1382  switch(A)
1383  {
1384   case 0x5000:
1385        EXPREGS[0]=V;
1386        FixMMC3PRG(MMC3_cmd);
1387        break;
1388   case 0x5001:
1389        EXPREGS[1]=V;
1390        FixMMC3PRG(MMC3_cmd);
1391        break;
1392   case 0x5007:
1393        EXPREGS[2]=V;
1394        break;
1395  }
1396 }
1397
1398 static void M217Power(void)
1399 {
1400  EXPREGS[0]=0;
1401  EXPREGS[1]=0xFF;
1402  EXPREGS[2]=3;
1403  GenMMC3Power();
1404  SetWriteHandler(0x8000,0xFFFF,M217Write);
1405  SetWriteHandler(0x5000,0x7FFF,M217ExWrite);
1406 }
1407
1408 void Mapper217_Init(CartInfo *info)
1409 {
1410  GenMMC3_Init(info, 256, 256, 0, 0);
1411  cwrap=M217CW;
1412  pwrap=M217PW;
1413  info->Power=M217Power;
1414  AddExState(EXPREGS, 3, 0, "EXPR");
1415  AddExState(&cmdin, 1, 0, "CMDIN");
1416 }
1417
1418 // ---------------------------- Mapper 245 ------------------------------
1419
1420 static void M245CW(uint32 A, uint8 V)
1421 {
1422  setchr1(A,V&7);
1423  EXPREGS[0]=V;
1424  FixMMC3PRG(MMC3_cmd);
1425 }
1426
1427 static void M245PW(uint32 A, uint8 V)
1428 {
1429  setprg8(A,(V&0x3F)|((EXPREGS[0]&2)<<5));
1430 }
1431
1432 static void M245Power(void)
1433 {
1434  EXPREGS[0]=0;
1435  GenMMC3Power();
1436 }
1437
1438 void Mapper245_Init(CartInfo *info)
1439 {
1440  GenMMC3_Init(info, 512, 256, 8, info->battery);
1441  cwrap=M245CW;
1442  pwrap=M245PW;
1443  info->Power=M245Power;
1444  AddExState(EXPREGS, 1, 0, "EXPR");
1445 }
1446
1447 // ---------------------------- Mapper 249 ------------------------------
1448
1449 static void M249PW(uint32 A, uint8 V)
1450 {
1451  if(EXPREGS[0]&0x2)
1452  {
1453   if(V<0x20)
1454    V=(V&1)|((V>>3)&2)|((V>>1)&4)|((V<<2)&8)|((V<<2)&0x10);
1455   else
1456   {
1457    V-=0x20;
1458    V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);
1459   }
1460  }
1461  setprg8(A,V);
1462 }
1463
1464 static void M249CW(uint32 A, uint8 V)
1465 {
1466  if(EXPREGS[0]&0x2)
1467     V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);
1468  setchr1(A,V);
1469 }
1470
1471 static DECLFW(M249Write)
1472 {
1473  EXPREGS[0]=V;
1474  FixMMC3PRG(MMC3_cmd);
1475  FixMMC3CHR(MMC3_cmd);
1476 }
1477
1478 static void M249Power(void)
1479 {
1480  EXPREGS[0]=0;
1481  GenMMC3Power();
1482  SetWriteHandler(0x5000,0x5000,M249Write);
1483 }
1484
1485 void Mapper249_Init(CartInfo *info)
1486 {
1487  GenMMC3_Init(info, 512, 256, 8, info->battery);
1488  cwrap=M249CW;
1489  pwrap=M249PW;
1490  info->Power=M249Power;
1491  AddExState(EXPREGS, 1, 0, "EXPR");
1492 }
1493
1494 // ---------------------------- Mapper 250 ------------------------------
1495
1496 static DECLFW(M250Write)
1497 {
1498  MMC3_CMDWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
1499 }
1500
1501 static DECLFW(M250IRQWrite)
1502 {
1503  MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
1504 }
1505
1506 static void M250_Power(void)
1507 {
1508  GenMMC3Power();
1509  SetWriteHandler(0x8000,0xBFFF,M250Write);
1510  SetWriteHandler(0xC000,0xFFFF,M250IRQWrite);
1511 }
1512
1513 void Mapper250_Init(CartInfo *info)
1514 {
1515  GenMMC3_Init(info, 512, 256, 8, info->battery);
1516  info->Power=M250_Power;
1517 }
1518
1519 // ---------------------------- Mapper 254 ------------------------------
1520
1521 static DECLFR(MR254WRAM)
1522 {
1523   if(EXPREGS[0])
1524     return WRAM[A-0x6000];
1525   else
1526     return WRAM[A-0x6000]^EXPREGS[1];
1527 }
1528
1529 static DECLFW(M254Write)
1530 {
1531  switch (A) {
1532   case 0x8000: EXPREGS[0]=0xff;
1533                break;
1534   case 0xA001: EXPREGS[1]=V;
1535  }
1536  MMC3_CMDWrite(A,V);
1537 }
1538
1539 static void M254_Power(void)
1540 {
1541  GenMMC3Power();
1542  SetWriteHandler(0x8000,0xBFFF,M254Write);
1543  SetReadHandler(0x6000,0x7FFF,MR254WRAM);
1544 #ifdef ASM_6502
1545    // hrrr.. can't handle those evil xors here..
1546    Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;
1547 #endif
1548 }
1549
1550 void Mapper254_Init(CartInfo *info)
1551 {
1552  GenMMC3_Init(info, 128, 128, 8, info->battery);
1553  info->Power=M254_Power;
1554  AddExState(EXPREGS, 2, 0, "EXPR");
1555 }
1556
1557 // ---------------------------- UNIF Boards -----------------------------
1558
1559 void TEROM_Init(CartInfo *info)
1560 {
1561  GenMMC3_Init(info, 32, 32, 0, 0);
1562 }
1563
1564 void TFROM_Init(CartInfo *info)
1565 {
1566  GenMMC3_Init(info, 512, 64, 0, 0);
1567 }
1568
1569 void TGROM_Init(CartInfo *info)
1570 {
1571  GenMMC3_Init(info, 512, 0, 0, 0);
1572 }
1573
1574 void TKROM_Init(CartInfo *info)
1575 {
1576  GenMMC3_Init(info, 512, 256, 8, info->battery);
1577 }
1578
1579 void TLROM_Init(CartInfo *info)
1580 {
1581  GenMMC3_Init(info, 512, 256, 0, 0);
1582 }
1583
1584 void TSROM_Init(CartInfo *info)
1585 {
1586  GenMMC3_Init(info, 512, 256, 8, 0);
1587 }
1588
1589 void TLSROM_Init(CartInfo *info)
1590 {
1591  GenMMC3_Init(info, 512, 256, 8, 0);
1592  cwrap=TKSWRAP;
1593  mwrap=GENNOMWRAP;
1594  PPU_hook=TKSPPU;
1595  AddExState(&PPUCHRBus, 1, 0, "PPUC");
1596 }
1597
1598 void TKSROM_Init(CartInfo *info)
1599 {
1600  GenMMC3_Init(info, 512, 256, 8, info->battery);
1601  cwrap=TKSWRAP;
1602  mwrap=GENNOMWRAP;
1603  PPU_hook=TKSPPU;
1604  AddExState(&PPUCHRBus, 1, 0, "PPUC");
1605 }
1606
1607 void TQROM_Init(CartInfo *info)
1608 {
1609  GenMMC3_Init(info, 512, 64, 0, 0);
1610  cwrap=TQWRAP;
1611  CHRRAMSize=8192;
1612  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
1613  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
1614 }
1615
1616 void HKROM_Init(CartInfo *info)
1617 {
1618  GenMMC3_Init(info, 512, 512, 1, info->battery);
1619 }