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