2618db470c5ff0abe20ff907de6b889b1a3b7dbf
[fceu.git] / boards / mmc3.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 1998 BERO\r
5  *  Copyright (C) 2003 Xodnizel\r
6  *  Mapper 12 code Copyright (C) 2003 CaH4e3\r
7  *\r
8  * This program is free software; you can redistribute it and/or modify\r
9  * it under the terms of the GNU General Public License as published by\r
10  * the Free Software Foundation; either version 2 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU General Public License\r
19  * along with this program; if not, write to the Free Software\r
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA\r
21  */\r
22 \r
23 /*  Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118,\r
24     119,165,205,214,215,245,249,250,254\r
25 */\r
26 \r
27 #include "mapinc.h"\r
28 #include "mmc3.h"\r
29 \r
30 uint8 MMC3_cmd;\r
31 uint8 *WRAM;\r
32 uint8 *CHRRAM;\r
33 uint32 CHRRAMSize;\r
34 uint8 DRegBuf[8];\r
35 uint8 EXPREGS[8];    /* For bootleg games, mostly. */\r
36 uint8 A000B,A001B;\r
37 \r
38 #undef IRQCount\r
39 #undef IRQLatch\r
40 #undef IRQa\r
41 uint8 IRQCount,IRQLatch,IRQa;\r
42 uint8 IRQReload;\r
43 \r
44 static SFORMAT MMC3_StateRegs[]=\r
45 {\r
46  {DRegBuf, 8, "REGS"},\r
47  {&MMC3_cmd, 1, "CMD"},\r
48  {&A000B, 1, "A000"},\r
49  {&A001B, 1, "A001"},\r
50  {&IRQReload, 1, "IRQR"},\r
51  {&IRQCount, 1, "IRQC"},\r
52  {&IRQLatch, 1, "IRQL"},\r
53  {&IRQa, 1, "IRQA"},\r
54  {0}\r
55 };\r
56 \r
57 static int mmc3opts=0;\r
58 static int wrams;\r
59 static int isRevB=1;\r
60 \r
61 void (*pwrap)(uint32 A, uint8 V);\r
62 void (*cwrap)(uint32 A, uint8 V);\r
63 void (*mwrap)(uint8 V);\r
64 \r
65 void GenMMC3Power(void);\r
66 void FixMMC3PRG(int V);\r
67 void FixMMC3CHR(int V);\r
68 \r
69 void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);\r
70 \r
71 // ----------------------------------------------------------------------\r
72 // ------------------------- Generic MM3 Code ---------------------------\r
73 // ----------------------------------------------------------------------\r
74 \r
75 void FixMMC3PRG(int V)\r
76 {\r
77  if(V&0x40)\r
78  {\r
79   pwrap(0xC000,DRegBuf[6]);\r
80   pwrap(0x8000,~1);\r
81  }\r
82  else\r
83  {\r
84   pwrap(0x8000,DRegBuf[6]);\r
85   pwrap(0xC000,~1);\r
86  }\r
87  pwrap(0xA000,DRegBuf[7]);\r
88  pwrap(0xE000,~0);\r
89 }\r
90 \r
91 void FixMMC3CHR(int V)\r
92 {\r
93  int cbase=(V&0x80)<<5;\r
94 \r
95  cwrap((cbase^0x000),DRegBuf[0]&(~1));\r
96  cwrap((cbase^0x400),DRegBuf[0]|1);\r
97  cwrap((cbase^0x800),DRegBuf[1]&(~1));\r
98  cwrap((cbase^0xC00),DRegBuf[1]|1);\r
99 \r
100  cwrap(cbase^0x1000,DRegBuf[2]);\r
101  cwrap(cbase^0x1400,DRegBuf[3]);\r
102  cwrap(cbase^0x1800,DRegBuf[4]);\r
103  cwrap(cbase^0x1c00,DRegBuf[5]);\r
104 \r
105  if(mwrap) mwrap(A000B);\r
106 }\r
107 \r
108 void MMC3RegReset(void)\r
109 {\r
110  IRQCount=IRQLatch=IRQa=MMC3_cmd=0;\r
111 \r
112  DRegBuf[0]=0;\r
113  DRegBuf[1]=2;\r
114  DRegBuf[2]=4;\r
115  DRegBuf[3]=5;\r
116  DRegBuf[4]=6;\r
117  DRegBuf[5]=7;\r
118  DRegBuf[6]=0;\r
119  DRegBuf[7]=1;\r
120 \r
121  FixMMC3PRG(0);\r
122  FixMMC3CHR(0);\r
123 }\r
124 \r
125 DECLFW(MMC3_CMDWrite)\r
126 {\r
127 // FCEU_printf("bs %04x %02x\n",A,V);\r
128  switch(A&0xE001)\r
129  {\r
130   case 0x8000:\r
131        if((V&0x40) != (MMC3_cmd&0x40))\r
132           FixMMC3PRG(V);\r
133        if((V&0x80) != (MMC3_cmd&0x80))\r
134           FixMMC3CHR(V);\r
135        MMC3_cmd = V;\r
136        break;\r
137   case 0x8001:\r
138        {\r
139         int cbase=(MMC3_cmd&0x80)<<5;\r
140         DRegBuf[MMC3_cmd&0x7]=V;\r
141         switch(MMC3_cmd&0x07)\r
142         {\r
143          case 0: cwrap((cbase^0x000),V&(~1));\r
144                  cwrap((cbase^0x400),V|1);\r
145                  break;\r
146          case 1: cwrap((cbase^0x800),V&(~1));\r
147                  cwrap((cbase^0xC00),V|1);\r
148                  break;\r
149          case 2: cwrap(cbase^0x1000,V);\r
150                  break;\r
151          case 3: cwrap(cbase^0x1400,V);\r
152                  break;\r
153          case 4: cwrap(cbase^0x1800,V);\r
154                  break;\r
155          case 5: cwrap(cbase^0x1C00,V);\r
156                  break;\r
157          case 6:\r
158                  if(MMC3_cmd&0x40)\r
159                     pwrap(0xC000,V);\r
160                  else\r
161                     pwrap(0x8000,V);\r
162                  break;\r
163          case 7:\r
164                  pwrap(0xA000,V);\r
165                  break;\r
166         }\r
167        }\r
168        break;\r
169   case 0xA000:\r
170        if(mwrap) mwrap(V);\r
171        break;\r
172   case 0xA001:\r
173        A001B=V;\r
174        break;\r
175  }\r
176 }\r
177 \r
178 DECLFW(MMC3_IRQWrite)\r
179 {\r
180 // FCEU_printf("%04x:%04x\n",A,V);\r
181  switch(A&0xE001)\r
182  {\r
183   case 0xC000:IRQLatch=V;break;\r
184   case 0xC001:IRQReload=1;break;\r
185   case 0xE000:X6502_IRQEnd(FCEU_IQEXT);IRQa=0;break;\r
186   case 0xE001:IRQa=1;break;\r
187  }\r
188 }\r
189 \r
190 static void ClockMMC3Counter(void)\r
191 {\r
192  int count = IRQCount;\r
193  if(!count || IRQReload)\r
194  {\r
195     IRQCount = IRQLatch;\r
196     IRQReload = 0;\r
197  }\r
198  else\r
199     IRQCount--;\r
200  if((count|isRevB) && !IRQCount)\r
201  {\r
202     if(IRQa)\r
203     {\r
204        X6502_IRQBegin(FCEU_IQEXT);\r
205     }\r
206  }\r
207 }\r
208 \r
209 static void MMC3_hb(void)\r
210 {\r
211  ClockMMC3Counter();\r
212 }\r
213 \r
214 static void MMC3_hb_KickMasterHack(void)\r
215 {\r
216  if(scanline==238) ClockMMC3Counter();\r
217  ClockMMC3Counter();\r
218 }\r
219 \r
220 static void MMC3_hb_PALStarWarsHack(void)\r
221 {\r
222  if(scanline==240) ClockMMC3Counter();\r
223  ClockMMC3Counter();\r
224 }\r
225 \r
226 void GenMMC3Restore(int version)\r
227 {\r
228  FixMMC3PRG(MMC3_cmd);\r
229  FixMMC3CHR(MMC3_cmd);\r
230 }\r
231 \r
232 static void GENCWRAP(uint32 A, uint8 V)\r
233 {\r
234    setchr1(A,V);    // Business Wars NEEDS THIS for 8K CHR-RAM\r
235 }\r
236 \r
237 static void GENPWRAP(uint32 A, uint8 V)\r
238 {\r
239  setprg8(A,V&0x7F); // [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken\r
240 }\r
241 \r
242 static void GENMWRAP(uint8 V)\r
243 {\r
244  A000B=V;\r
245  setmirror((V&1)^1);\r
246 }\r
247 \r
248 static void GENNOMWRAP(uint8 V)\r
249 {\r
250  A000B=V;\r
251 }\r
252 \r
253 static DECLFW(MBWRAMMMC6)\r
254 {\r
255  WRAM[A&0x3ff]=V;\r
256 }\r
257 \r
258 static DECLFR(MAWRAMMMC6)\r
259 {\r
260  return(WRAM[A&0x3ff]);\r
261 }\r
262 \r
263 void GenMMC3Power(void)\r
264 {\r
265  if(UNIFchrrama) setchr8(0);\r
266 \r
267  SetWriteHandler(0x8000,0xBFFF,MMC3_CMDWrite);\r
268  SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);\r
269  SetReadHandler(0x8000,0xFFFF,CartBR);\r
270  A001B=A000B=0;\r
271  setmirror(1);\r
272  if(mmc3opts&1)\r
273  {\r
274   if(wrams==1024)\r
275   {\r
276    FCEU_CheatAddRAM(1,0x7000,WRAM);\r
277    SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);\r
278    SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);\r
279   }\r
280   else\r
281   {\r
282    FCEU_CheatAddRAM((wrams&0x1fff)>>10,0x6000,WRAM);\r
283    SetWriteHandler(0x6000,0x6000 + ((wrams - 1) & 0x1fff),CartBW);\r
284    SetReadHandler(0x6000,0x6000 + ((wrams - 1) & 0x1fff),CartBR);\r
285    setprg8r(0x10,0x6000,0);\r
286   }\r
287   if(!(mmc3opts&2))\r
288      FCEU_dwmemset(WRAM,0,wrams);\r
289  }\r
290  MMC3RegReset();\r
291  if(CHRRAM)\r
292   FCEU_dwmemset(CHRRAM,0,CHRRAMSize);\r
293 }\r
294 \r
295 static void GenMMC3Close(void)\r
296 {\r
297  if(CHRRAM)\r
298     FCEU_gfree(CHRRAM);\r
299  if(WRAM)\r
300     FCEU_gfree(WRAM);\r
301  CHRRAM=WRAM=NULL;\r
302 }\r
303 \r
304 void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery)\r
305 {\r
306  pwrap=GENPWRAP;\r
307  cwrap=GENCWRAP;\r
308  mwrap=GENMWRAP;\r
309 \r
310  wrams=wram<<10;\r
311 \r
312  PRGmask8[0]&=(prg>>13)-1;\r
313  CHRmask1[0]&=(chr>>10)-1;\r
314  CHRmask2[0]&=(chr>>11)-1;\r
315 \r
316  if(wram)\r
317  {\r
318   mmc3opts|=1;\r
319   WRAM=(uint8*)FCEU_gmalloc(wrams);\r
320   SetupCartPRGMapping(0x10,WRAM,wrams,1);\r
321   AddExState(WRAM, wrams, 0, "MMC3WRAM");\r
322  }\r
323 \r
324  if(battery)\r
325  {\r
326   mmc3opts|=2;\r
327   info->SaveGame[0]=WRAM;\r
328   info->SaveGameLen[0]=wrams;\r
329  }\r
330 \r
331  AddExState(MMC3_StateRegs, ~0, 0, 0);\r
332 \r
333  info->Power=GenMMC3Power;\r
334  info->Reset=MMC3RegReset;\r
335  info->Close=GenMMC3Close;\r
336 \r
337  if(info->CRC32 == 0x5104833e)        // Kick Master\r
338   GameHBIRQHook = MMC3_hb_KickMasterHack;\r
339  else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93\r
340   GameHBIRQHook = MMC3_hb_KickMasterHack;\r
341  else if(info->CRC32 == 0xfcd772eb)    // PAL Star Wars, similar problem as Kick Master.\r
342   GameHBIRQHook = MMC3_hb_PALStarWarsHack;\r
343  else\r
344   GameHBIRQHook=MMC3_hb;\r
345  GameStateRestore=GenMMC3Restore;\r
346 }\r
347 \r
348 // ----------------------------------------------------------------------\r
349 // -------------------------- MMC3 Based Code ---------------------------\r
350 // ----------------------------------------------------------------------\r
351 \r
352 // ---------------------------- Mapper 4 --------------------------------\r
353 \r
354 static int hackm4=0;/* For Karnov, maybe others.  BLAH.  Stupid iNES format.*/\r
355 \r
356 static void M4Power(void)\r
357 {\r
358  GenMMC3Power();\r
359  A000B=(hackm4^1)&1;\r
360  setmirror(hackm4);\r
361 }\r
362 \r
363 void Mapper4_Init(CartInfo *info)\r
364 {\r
365  int ws=8;\r
366 \r
367  if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84))\r
368  {\r
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");\r
370   ws=0;\r
371  }\r
372  GenMMC3_Init(info,512,256,ws,info->battery);\r
373  info->Power=M4Power;\r
374  hackm4=info->mirror;\r
375 }\r
376 \r
377 // ---------------------------- Mapper 12 -------------------------------\r
378 \r
379 static void M12CW(uint32 A, uint8 V)\r
380 {\r
381  setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V);\r
382 }\r
383 \r
384 static DECLFW(M12Write)\r
385 {\r
386  EXPREGS[0]=V&0x01;\r
387  EXPREGS[1]=(V&0x10)>>4;\r
388 }\r
389 \r
390 static void M12Power(void)\r
391 {\r
392  EXPREGS[0]=EXPREGS[1]=0;\r
393  GenMMC3Power();\r
394  SetWriteHandler(0x4100,0x5FFF,M12Write);\r
395 }\r
396 \r
397 void Mapper12_Init(CartInfo *info)\r
398 {\r
399  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
400  cwrap=M12CW;\r
401  isRevB=0;\r
402 \r
403  info->Power=M12Power;\r
404  AddExState(EXPREGS, 2, 0, "EXPR");\r
405 }\r
406 \r
407 // ---------------------------- Mapper 37 -------------------------------\r
408 \r
409 static void M37PW(uint32 A, uint8 V)\r
410 {\r
411   if(EXPREGS[0]!=2)\r
412     V&=0x7;\r
413   else\r
414     V&=0xF;\r
415   V|=EXPREGS[0]<<3;\r
416   setprg8(A,V);\r
417 }\r
418 \r
419 static void M37CW(uint32 A, uint8 V)\r
420 {\r
421   uint32 NV=V;\r
422   NV&=0x7F;\r
423   NV|=EXPREGS[0]<<6;\r
424   setchr1(A,NV);\r
425 }\r
426 \r
427 static DECLFW(M37Write)\r
428 {\r
429   EXPREGS[0]=(V&6)>>1;\r
430   FixMMC3PRG(MMC3_cmd);\r
431   FixMMC3CHR(MMC3_cmd);\r
432 }\r
433 \r
434 static void M37Reset(void)\r
435 {\r
436   EXPREGS[0]=0;\r
437   MMC3RegReset();\r
438 }\r
439 \r
440 static void M37Power(void)\r
441 {\r
442   EXPREGS[0]=0;\r
443   GenMMC3Power();\r
444   SetWriteHandler(0x6000,0x7FFF,M37Write);\r
445 }\r
446 \r
447 void Mapper37_Init(CartInfo *info)\r
448 {\r
449   GenMMC3_Init(info, 512, 256, 8, info->battery);\r
450   pwrap=M37PW;\r
451   cwrap=M37CW;\r
452   info->Power=M37Power;\r
453   info->Reset=M37Reset;\r
454   AddExState(EXPREGS, 1, 0, "EXPR");\r
455 }\r
456 \r
457 // ---------------------------- Mapper 44 -------------------------------\r
458 \r
459 static void M44PW(uint32 A, uint8 V)\r
460 {\r
461  uint32 NV=V;\r
462  if(EXPREGS[0]>=6) NV&=0x1F;\r
463  else NV&=0x0F;\r
464  NV|=EXPREGS[0]<<4;\r
465  setprg8(A,NV);\r
466 }\r
467 \r
468 static void M44CW(uint32 A, uint8 V)\r
469 {\r
470  uint32 NV=V;\r
471  if(EXPREGS[0]<6) NV&=0x7F;\r
472  NV|=EXPREGS[0]<<7;\r
473  setchr1(A,NV);\r
474 }\r
475 \r
476 static DECLFW(M44Write)\r
477 {\r
478  if(A&1)\r
479  {\r
480   EXPREGS[0]=V&7;\r
481   FixMMC3PRG(MMC3_cmd);\r
482   FixMMC3CHR(MMC3_cmd);\r
483  }\r
484  else\r
485   MMC3_CMDWrite(A,V);\r
486 }\r
487 \r
488 static void M44Power(void)\r
489 {\r
490  EXPREGS[0]=0;\r
491  GenMMC3Power();\r
492  SetWriteHandler(0xA000,0xBFFF,M44Write);\r
493 }\r
494 \r
495 void Mapper44_Init(CartInfo *info)\r
496 {\r
497  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
498  cwrap=M44CW;\r
499  pwrap=M44PW;\r
500  info->Power=M44Power;\r
501  AddExState(EXPREGS, 1, 0, "EXPR");\r
502 }\r
503 \r
504 // ---------------------------- Mapper 45 -------------------------------\r
505 \r
506 static void M45CW(uint32 A, uint8 V)\r
507 {\r
508  if(!UNIFchrrama)\r
509  {\r
510    uint32 NV=V;\r
511    if(EXPREGS[2]&8)\r
512       NV&=(1<<((EXPREGS[2]&7)+1))-1;\r
513    else\r
514       if(EXPREGS[2])\r
515          NV&=0; // hack ;( don't know exactly how it should be\r
516    NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);\r
517    setchr1(A,NV);\r
518  }\r
519 }\r
520 \r
521 static void M45PW(uint32 A, uint8 V)\r
522 {\r
523  V&=(EXPREGS[3]&0x3F)^0x3F;\r
524  V|=EXPREGS[1];\r
525  setprg8(A,V);\r
526 }\r
527 \r
528 static DECLFW(M45Write)\r
529 {\r
530  if(EXPREGS[3]&0x40)\r
531  {\r
532   WRAM[A-0x6000]=V;\r
533   return;\r
534  }\r
535  EXPREGS[EXPREGS[4]]=V;\r
536  EXPREGS[4]=(EXPREGS[4]+1)&3;\r
537 // if(!EXPREGS[4]) \r
538 // {\r
539 //   FCEU_printf("CHROR %02x, PRGOR %02x, CHRAND %02x, PRGAND %02x\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);\r
540 //   FCEU_printf("CHR0 %03x, CHR1 %03x, PRG0 %03x, PRG1 %03x\n",\r
541 //               (0x00&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),\r
542 //               (0xFF&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),\r
543 //               (0x00&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]),\r
544 //               (0xFF&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]));\r
545 // }\r
546  FixMMC3PRG(MMC3_cmd);\r
547  FixMMC3CHR(MMC3_cmd);\r
548 }\r
549 \r
550 static void M45Reset(void)\r
551 {\r
552  EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=0;\r
553  MMC3RegReset();\r
554 }\r
555 \r
556 static void M45Power(void)\r
557 {\r
558  setchr8(0);\r
559  GenMMC3Power();\r
560  SetWriteHandler(0x6000,0x7FFF,M45Write);\r
561 }\r
562 \r
563 void Mapper45_Init(CartInfo *info)\r
564 {\r
565  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
566  cwrap=M45CW;\r
567  pwrap=M45PW;\r
568  info->Reset=M45Reset;\r
569  info->Power=M45Power;\r
570  AddExState(EXPREGS, 5, 0, "EXPR");\r
571 }\r
572 \r
573 // ---------------------------- Mapper 47 -------------------------------\r
574 \r
575 static void M47PW(uint32 A, uint8 V)\r
576 {\r
577  V&=0xF;\r
578  V|=EXPREGS[0]<<4;\r
579  setprg8(A,V);\r
580 }\r
581 \r
582 static void M47CW(uint32 A, uint8 V)\r
583 {\r
584  uint32 NV=V;\r
585  NV&=0x7F;\r
586  NV|=EXPREGS[0]<<7;\r
587  setchr1(A,NV);\r
588 }\r
589 \r
590 static DECLFW(M47Write)\r
591 {\r
592  EXPREGS[0]=V&1;\r
593  FixMMC3PRG(MMC3_cmd);\r
594  FixMMC3CHR(MMC3_cmd);\r
595 }\r
596 \r
597 static void M47Power(void)\r
598 {\r
599  EXPREGS[0]=0;\r
600  GenMMC3Power();\r
601  SetWriteHandler(0x6000,0x7FFF,M47Write);\r
602 // SetReadHandler(0x6000,0x7FFF,0);\r
603 }\r
604 \r
605 void Mapper47_Init(CartInfo *info)\r
606 {\r
607  GenMMC3_Init(info, 512, 256, 8, 0);\r
608  pwrap=M47PW;\r
609  cwrap=M47CW;\r
610  info->Power=M47Power;\r
611  AddExState(EXPREGS, 1, 0, "EXPR");\r
612 }\r
613 \r
614 // ---------------------------- Mapper 49 -------------------------------\r
615 \r
616 static void M49PW(uint32 A, uint8 V)\r
617 {\r
618  if(EXPREGS[0]&1)\r
619  {\r
620   V&=0xF;\r
621   V|=(EXPREGS[0]&0xC0)>>2;\r
622   setprg8(A,V);\r
623  }\r
624  else\r
625   setprg32(0x8000,(EXPREGS[0]>>4)&3);\r
626 }\r
627 \r
628 static void M49CW(uint32 A, uint8 V)\r
629 {\r
630  uint32 NV=V;\r
631  NV&=0x7F;\r
632  NV|=(EXPREGS[0]&0xC0)<<1;\r
633  setchr1(A,NV);\r
634 }\r
635 \r
636 static DECLFW(M49Write)\r
637 {\r
638  if(A001B&0x80)\r
639  {\r
640   EXPREGS[0]=V;\r
641   FixMMC3PRG(MMC3_cmd);\r
642   FixMMC3CHR(MMC3_cmd);\r
643  }\r
644 }\r
645 \r
646 static void M49Reset(void)\r
647 {\r
648  EXPREGS[0]=0;\r
649  MMC3RegReset();\r
650 }\r
651 \r
652 static void M49Power(void)\r
653 {\r
654  M49Reset();\r
655  GenMMC3Power();\r
656  SetWriteHandler(0x6000,0x7FFF,M49Write);\r
657  SetReadHandler(0x6000,0x7FFF,0);\r
658 }\r
659 \r
660 void Mapper49_Init(CartInfo *info)\r
661 {\r
662  GenMMC3_Init(info, 512, 256, 0, 0);\r
663  cwrap=M49CW;\r
664  pwrap=M49PW;\r
665  info->Reset=M49Reset;\r
666  info->Power=M49Power;\r
667  AddExState(EXPREGS, 1, 0, "EXPR");\r
668 }\r
669 \r
670 // ---------------------------- Mapper 52 -------------------------------\r
671 \r
672 static void M52PW(uint32 A, uint8 V)\r
673 {\r
674  uint32 NV=V;\r
675  NV&=0x1F^((EXPREGS[0]&8)<<1);\r
676  NV|=((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4;\r
677  setprg8(A,NV);\r
678 }\r
679 \r
680 static void M52CW(uint32 A, uint8 V)\r
681 {\r
682  uint32 NV=V;\r
683  NV&=0xFF^((EXPREGS[0]&0x40)<<1);\r
684  NV|=(((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7;\r
685  setchr1(A,NV);\r
686 }\r
687 \r
688 static DECLFW(M52Write)\r
689 {\r
690  if(EXPREGS[1])\r
691  {\r
692   WRAM[A-0x6000]=V;\r
693   return;\r
694  }\r
695  EXPREGS[1]=1;\r
696  EXPREGS[0]=V;\r
697  FixMMC3PRG(MMC3_cmd);\r
698  FixMMC3CHR(MMC3_cmd);\r
699 }\r
700 \r
701 static void M52Reset(void)\r
702 {\r
703  EXPREGS[0]=EXPREGS[1]=0;\r
704  MMC3RegReset();\r
705 }\r
706 \r
707 static void M52Power(void)\r
708 {\r
709  M52Reset();\r
710  GenMMC3Power();\r
711  SetWriteHandler(0x6000,0x7FFF,M52Write);\r
712 }\r
713 \r
714 void Mapper52_Init(CartInfo *info)\r
715 {\r
716  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
717  cwrap=M52CW;\r
718  pwrap=M52PW;\r
719  info->Reset=M52Reset;\r
720  info->Power=M52Power;\r
721  AddExState(EXPREGS, 2, 0, "EXPR");\r
722 }\r
723 \r
724 // ---------------------------- Mapper 74 -------------------------------\r
725 \r
726 static void M74CW(uint32 A, uint8 V)\r
727 {\r
728   if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes\r
729     setchr1r(0x10,A,V);\r
730   else\r
731     setchr1r(0,A,V);\r
732 }\r
733 \r
734 void Mapper74_Init(CartInfo *info)\r
735 {\r
736  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
737  cwrap=M74CW;\r
738  CHRRAMSize=2048;\r
739  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
740  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
741  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
742 }\r
743 \r
744 // ---------------------------- Mapper 114 ------------------------------\r
745 \r
746 static uint8 cmdin;\r
747 uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};\r
748 \r
749 static void M114PWRAP(uint32 A, uint8 V)\r
750 {\r
751   if(EXPREGS[0]&0x80)\r
752   {\r
753     setprg16(0x8000,EXPREGS[0]&0xF);\r
754     setprg16(0xC000,EXPREGS[0]&0xF);\r
755   }\r
756   else\r
757     setprg8(A,V&0x3F);\r
758 }\r
759 \r
760 static DECLFW(M114Write)\r
761 {\r
762  switch(A&0xE001)\r
763  {\r
764   case 0x8001: MMC3_CMDWrite(0xA000,V); break;\r
765   case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break;\r
766   case 0xC000: if(!cmdin) break; MMC3_CMDWrite(0x8001,V); cmdin=0; break;\r
767   case 0xA001: IRQLatch=V; break;\r
768   case 0xC001: IRQReload=1; break;\r
769   case 0xE000: X6502_IRQEnd(FCEU_IQEXT);IRQa=0; break;\r
770   case 0xE001: IRQa=1; break;\r
771  }\r
772 }\r
773 \r
774 static DECLFW(M114ExWrite)\r
775 {\r
776   if(A<=0x7FFF)\r
777   {\r
778    EXPREGS[0]=V;\r
779    FixMMC3PRG(MMC3_cmd);\r
780   }\r
781 }\r
782 \r
783 static void M114Power(void)\r
784 {\r
785  GenMMC3Power();\r
786  SetWriteHandler(0x8000,0xFFFF,M114Write);\r
787  SetWriteHandler(0x5000,0x7FFF,M114ExWrite);\r
788 }\r
789 \r
790 static void M114Reset(void)\r
791 {\r
792  EXPREGS[0]=0;\r
793  MMC3RegReset();\r
794 }\r
795 \r
796 void Mapper114_Init(CartInfo *info)\r
797 {\r
798  isRevB=0;\r
799  GenMMC3_Init(info, 256, 256, 0, 0);\r
800  pwrap=M114PWRAP;\r
801  info->Power=M114Power;\r
802  info->Reset=M114Reset;\r
803  AddExState(EXPREGS, 1, 0, "EXPR");\r
804  AddExState(&cmdin, 1, 0, "CMDIN");\r
805 }\r
806 \r
807 // ---------------------------- Mapper 115 ------------------------------\r
808 \r
809 static void M115PW(uint32 A, uint8 V)\r
810 {\r
811         //zero 09-apr-2012 - #3515357 - changed to support Bao Qing Tian (mapper 248) which was missing BG gfx. 115 game(s?) seem still to work OK.\r
812         GENPWRAP(A,V);\r
813         if(A==0x8000 && EXPREGS[0]&0x80)\r
814                 setprg16(0x8000,(EXPREGS[0]&0xF));\r
815 }\r
816 \r
817 static void M115CW(uint32 A, uint8 V)\r
818 {\r
819   setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8));\r
820 }\r
821 \r
822 static DECLFW(M115Write)\r
823 {\r
824 // FCEU_printf("%04x:%04x\n",A,V);\r
825  if(A==0x5080) EXPREGS[2]=V;\r
826  if(A==0x6000)\r
827     EXPREGS[0]=V;\r
828  else if(A==0x6001)\r
829     EXPREGS[1]=V;\r
830  FixMMC3PRG(MMC3_cmd);\r
831 }\r
832 \r
833 static DECLFR(M115Read)\r
834 {\r
835  return EXPREGS[2];\r
836 }\r
837 \r
838 static void M115Power(void)\r
839 {\r
840  GenMMC3Power();\r
841  SetWriteHandler(0x4100,0x7FFF,M115Write);\r
842  SetReadHandler(0x5000,0x5FFF,M115Read);\r
843 }\r
844 \r
845 void Mapper115_Init(CartInfo *info)\r
846 {\r
847  GenMMC3_Init(info, 128, 512, 0, 0);\r
848  cwrap=M115CW;\r
849  pwrap=M115PW;\r
850  info->Power=M115Power;\r
851  AddExState(EXPREGS, 2, 0, "EXPR");\r
852 }\r
853 \r
854 // ---------------------------- Mapper 118 ------------------------------\r
855 \r
856 static uint8 PPUCHRBus;\r
857 static uint8 TKSMIR[8];\r
858 \r
859 static void TKSPPU(uint32 A)\r
860 {\r
861  A&=0x1FFF;\r
862  A>>=10;\r
863  PPUCHRBus=A;\r
864  setmirror(MI_0+TKSMIR[A]);\r
865 }\r
866 \r
867 static void TKSWRAP(uint32 A, uint8 V)\r
868 {\r
869  TKSMIR[A>>10]=V>>7;\r
870  setchr1(A,V&0x7F);\r
871  if(PPUCHRBus==(A>>10))\r
872     setmirror(MI_0+(V>>7));\r
873 }\r
874 \r
875 // ---------------------------- Mapper 119 ------------------------------\r
876 \r
877 static void TQWRAP(uint32 A, uint8 V)\r
878 {\r
879  setchr1r((V&0x40)>>2,A,V&0x3F);\r
880 }\r
881 \r
882 void Mapper119_Init(CartInfo *info)\r
883 {\r
884  GenMMC3_Init(info, 512, 64, 0, 0);\r
885  cwrap=TQWRAP;\r
886  CHRRAMSize=8192;\r
887  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
888  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
889 }\r
890 \r
891 // ---------------------------- Mapper 134 ------------------------------\r
892 \r
893 static void M134PW(uint32 A, uint8 V)\r
894 {\r
895   setprg8(A,(V&0x1F)|((EXPREGS[0]&2)<<4));\r
896 }\r
897 \r
898 static void M134CW(uint32 A, uint8 V)\r
899 {\r
900   setchr1(A,(V&0xFF)|((EXPREGS[0]&0x20)<<3));\r
901 }\r
902 \r
903 static DECLFW(M134Write)\r
904 {\r
905   EXPREGS[0]=V;\r
906   FixMMC3CHR(MMC3_cmd);\r
907   FixMMC3PRG(MMC3_cmd);\r
908 }\r
909 \r
910 static void M134Power(void)\r
911 {\r
912  EXPREGS[0]=0;\r
913  GenMMC3Power();\r
914  SetWriteHandler(0x6001,0x6001,M134Write);\r
915 }\r
916 \r
917 static void M134Reset(void)\r
918 {\r
919  EXPREGS[0]=0;\r
920  MMC3RegReset();\r
921 }\r
922 \r
923 void Mapper134_Init(CartInfo *info)\r
924 {\r
925  GenMMC3_Init(info, 256, 256, 0, 0);\r
926  pwrap=M134PW;\r
927  cwrap=M134CW;\r
928  info->Power=M134Power;\r
929  info->Reset=M134Reset;\r
930  AddExState(EXPREGS, 4, 0, "EXPR");\r
931 }\r
932 \r
933 // ---------------------------- Mapper 165 ------------------------------\r
934 \r
935 static void M165CW(uint32 A, uint8 V)\r
936 {\r
937  if(V==0)\r
938     setchr4r(0x10,A,0);\r
939  else\r
940     setchr4(A,V>>2);\r
941 }\r
942 \r
943 static void M165PPUFD(void)\r
944 {\r
945  if(EXPREGS[0]==0xFD)\r
946  {\r
947   M165CW(0x0000,DRegBuf[0]);\r
948   M165CW(0x1000,DRegBuf[2]);\r
949  }\r
950 }\r
951 \r
952 static void M165PPUFE(void)\r
953 {\r
954  if(EXPREGS[0]==0xFE)\r
955  {\r
956   M165CW(0x0000,DRegBuf[1]);\r
957   M165CW(0x1000,DRegBuf[4]);\r
958  }\r
959 }\r
960 \r
961 static void M165CWM(uint32 A, uint8 V)\r
962 {\r
963  if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2))\r
964    M165PPUFD();\r
965  if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4))\r
966    M165PPUFE();\r
967 }\r
968 \r
969 static void M165PPU(uint32 A)\r
970 {\r
971  if((A&0x1FF0)==0x1FD0)\r
972  {\r
973   EXPREGS[0]=0xFD;\r
974   M165PPUFD();\r
975  } else if((A&0x1FF0)==0x1FE0)\r
976  {\r
977   EXPREGS[0]=0xFE;\r
978   M165PPUFE();\r
979  }\r
980 }\r
981 \r
982 static void M165Power(void)\r
983 {\r
984  EXPREGS[0]=0xFD;\r
985  GenMMC3Power();\r
986 }\r
987 \r
988 void Mapper165_Init(CartInfo *info)\r
989 {\r
990  GenMMC3_Init(info, 512, 128, 8, info->battery);\r
991  cwrap=M165CWM;\r
992  PPU_hook=M165PPU;\r
993  info->Power=M165Power;\r
994  CHRRAMSize = 4096;\r
995  CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);\r
996  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
997  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
998  AddExState(EXPREGS, 4, 0, "EXPR");\r
999 }\r
1000 \r
1001 // ---------------------------- Mapper 191 ------------------------------\r
1002 \r
1003 static void M191CW(uint32 A, uint8 V)\r
1004 {\r
1005   setchr1r((V&0x80)>>3,A,V);\r
1006 }\r
1007 \r
1008 void Mapper191_Init(CartInfo *info)\r
1009 {\r
1010  GenMMC3_Init(info, 256, 256, 8, info->battery);\r
1011  cwrap=M191CW;\r
1012  CHRRAMSize=2048;\r
1013  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
1014  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
1015  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
1016 }\r
1017 \r
1018 // ---------------------------- Mapper 192 -------------------------------\r
1019 \r
1020 static void M192CW(uint32 A, uint8 V)\r
1021 {\r
1022   if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese),\r
1023     setchr1r(0x10,A,V);\r
1024   else\r
1025     setchr1r(0,A,V);\r
1026 }\r
1027 \r
1028 void Mapper192_Init(CartInfo *info)\r
1029 {\r
1030  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1031  cwrap=M192CW;\r
1032  CHRRAMSize=4096;\r
1033  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
1034  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
1035  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
1036 }\r
1037 \r
1038 // ---------------------------- Mapper 194 -------------------------------\r
1039 \r
1040 static void M194CW(uint32 A, uint8 V)\r
1041 {\r
1042   if(V<=1) //Dai-2-Ji - Super Robot Taisen (As).nes\r
1043     setchr1r(0x10,A,V);\r
1044   else\r
1045     setchr1r(0,A,V);\r
1046 }\r
1047 \r
1048 void Mapper194_Init(CartInfo *info)\r
1049 {\r
1050  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1051  cwrap=M194CW;\r
1052  CHRRAMSize=2048;\r
1053  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
1054  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
1055  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
1056 }\r
1057 \r
1058 // ---------------------------- Mapper 195 -------------------------------\r
1059 static uint8 *wramtw;\r
1060 static uint16 wramsize;\r
1061 \r
1062 static void M195CW(uint32 A, uint8 V)\r
1063 {\r
1064   if(V<=3) // Crystalis (c).nes, Captain Tsubasa Vol 2 - Super Striker (C)\r
1065     setchr1r(0x10,A,V);\r
1066   else\r
1067     setchr1r(0,A,V);\r
1068 }\r
1069 \r
1070 static void M195Power(void)\r
1071 {\r
1072  GenMMC3Power();\r
1073  setprg4r(0x10,0x5000,0);\r
1074  SetWriteHandler(0x5000,0x5fff,CartBW);\r
1075  SetReadHandler(0x5000,0x5fff,CartBR);\r
1076 }\r
1077 \r
1078 static void M195Close(void)\r
1079 {\r
1080   if(wramtw)\r
1081     FCEU_gfree(wramtw);\r
1082   wramtw=NULL;\r
1083 }\r
1084 \r
1085 void Mapper195_Init(CartInfo *info)\r
1086 {\r
1087  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1088  cwrap=M195CW;\r
1089  info->Power=M195Power;\r
1090  info->Close=M195Close;\r
1091  CHRRAMSize=4096;\r
1092  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
1093  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
1094  wramsize=4096;\r
1095  wramtw=(uint8*)FCEU_gmalloc(wramsize);\r
1096  SetupCartPRGMapping(0x10, wramtw, wramsize, 1);\r
1097  AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");\r
1098  AddExState(wramtw, wramsize, 0, "WRAMTW");\r
1099 }\r
1100 \r
1101 // ---------------------------- Mapper 196 -------------------------------\r
1102 \r
1103 static DECLFW(Mapper196Write)\r
1104 {\r
1105   A=(A&0xFFFE)|((A>>2)&1)|((A>>3)&1)|((A>>1)&1);\r
1106   if(A >= 0xC000)\r
1107    MMC3_IRQWrite(A,V);\r
1108   else\r
1109    MMC3_CMDWrite(A,V);\r
1110 }\r
1111 \r
1112 static void Mapper196Power(void)\r
1113 {\r
1114   GenMMC3Power();\r
1115   SetWriteHandler(0x8000,0xFFFF,Mapper196Write);\r
1116 }\r
1117 \r
1118 void Mapper196_Init(CartInfo *info)\r
1119 {\r
1120   GenMMC3_Init(info, 128, 128, 0, 0);\r
1121   info->Power=Mapper196Power;\r
1122 }\r
1123 \r
1124 // ---------------------------- Mapper 197 -------------------------------\r
1125 \r
1126 static void M197CW(uint32 A, uint8 V)\r
1127 {\r
1128   if(A==0x0000)\r
1129     setchr4(0x0000,V>>1);\r
1130   else if(A==0x1000)\r
1131     setchr2(0x1000,V);\r
1132   else if(A==0x1400)\r
1133     setchr2(0x1800,V);\r
1134 }\r
1135 \r
1136 void Mapper197_Init(CartInfo *info)\r
1137 {\r
1138  GenMMC3_Init(info, 128, 512, 8, 0);\r
1139  cwrap=M197CW;\r
1140 }\r
1141 \r
1142 // ---------------------------- Mapper 198 -------------------------------\r
1143 \r
1144 static void M198PW(uint32 A, uint8 V)\r
1145 {\r
1146   if(V>=0x50) // Tenchi o Kurau II - Shokatsu Koumei Den (J) (C).nes\r
1147     setprg8(A,V&0x4F);\r
1148   else\r
1149     setprg8(A,V);\r
1150 }\r
1151 \r
1152 void Mapper198_Init(CartInfo *info)\r
1153 {\r
1154  GenMMC3_Init(info, 1024, 256, 8, info->battery);\r
1155  pwrap=M198PW;\r
1156  info->Power=M195Power;\r
1157  info->Close=M195Close;\r
1158  wramsize=4096;\r
1159  wramtw=(uint8*)FCEU_gmalloc(wramsize);\r
1160  SetupCartPRGMapping(0x10, wramtw, wramsize, 1);\r
1161  AddExState(wramtw, wramsize, 0, "WRAMTW");\r
1162 }\r
1163 \r
1164 // ---------------------------- Mapper 205 ------------------------------\r
1165 \r
1166 static void M205PW(uint32 A, uint8 V)\r
1167 {\r
1168  if(EXPREGS[0]&2)\r
1169     setprg8(A,(V&0x0f)|((EXPREGS[0]&3)<<4));\r
1170  else\r
1171     setprg8(A,(V&0x1f)|((EXPREGS[0]&3)<<4));\r
1172 }\r
1173 \r
1174 static void M205CW(uint32 A, uint8 V)\r
1175 {\r
1176  setchr1(A,V|((EXPREGS[0]&3)<<7));\r
1177 }\r
1178 \r
1179 static DECLFW(M205Write)\r
1180 {\r
1181  if((A&0x6800)==0x6800) EXPREGS[0]= V;\r
1182  FixMMC3PRG(MMC3_cmd);\r
1183  FixMMC3CHR(MMC3_cmd);\r
1184 }\r
1185 \r
1186 static void M205Reset(void)\r
1187 {\r
1188  EXPREGS[0]=0;\r
1189  MMC3RegReset();\r
1190 }\r
1191 \r
1192 static void M205Power(void)\r
1193 {\r
1194  GenMMC3Power();\r
1195  SetWriteHandler(0x4020,0x7FFF,M205Write);\r
1196 }\r
1197 \r
1198 void Mapper205_Init(CartInfo *info)\r
1199 {\r
1200  GenMMC3_Init(info, 512, 256, 8, 0);\r
1201  pwrap=M205PW;\r
1202  cwrap=M205CW;\r
1203  info->Power=M205Power;\r
1204  info->Reset=M205Reset;\r
1205  AddExState(EXPREGS, 1, 0, "EXPR");\r
1206 }\r
1207 \r
1208 // ---------------------------- Mapper 245 ------------------------------\r
1209 \r
1210 static void M245CW(uint32 A, uint8 V)\r
1211 {\r
1212  if(!UNIFchrrama) // Yong Zhe Dou E Long - Dragon Quest VI (As).nes NEEDS THIS for RAM cart\r
1213   setchr1(A,V&7);\r
1214  EXPREGS[0]=V;\r
1215  FixMMC3PRG(MMC3_cmd);\r
1216 }\r
1217 \r
1218 static void M245PW(uint32 A, uint8 V)\r
1219 {\r
1220  setprg8(A,(V&0x3F)|((EXPREGS[0]&2)<<5));\r
1221 }\r
1222 \r
1223 static void M245Power(void)\r
1224 {\r
1225  EXPREGS[0]=0;\r
1226  GenMMC3Power();\r
1227 }\r
1228 \r
1229 void Mapper245_Init(CartInfo *info)\r
1230 {\r
1231  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1232  cwrap=M245CW;\r
1233  pwrap=M245PW;\r
1234  info->Power=M245Power;\r
1235  AddExState(EXPREGS, 1, 0, "EXPR");\r
1236 }\r
1237 \r
1238 // ---------------------------- Mapper 249 ------------------------------\r
1239 \r
1240 static void M249PW(uint32 A, uint8 V)\r
1241 {\r
1242  if(EXPREGS[0]&0x2)\r
1243  {\r
1244   if(V<0x20)\r
1245    V=(V&1)|((V>>3)&2)|((V>>1)&4)|((V<<2)&8)|((V<<2)&0x10);\r
1246   else\r
1247   {\r
1248    V-=0x20;\r
1249    V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);\r
1250   }\r
1251  }\r
1252  setprg8(A,V);\r
1253 }\r
1254 \r
1255 static void M249CW(uint32 A, uint8 V)\r
1256 {\r
1257  if(EXPREGS[0]&0x2)\r
1258     V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);\r
1259  setchr1(A,V);\r
1260 }\r
1261 \r
1262 static DECLFW(M249Write)\r
1263 {\r
1264  EXPREGS[0]=V;\r
1265  FixMMC3PRG(MMC3_cmd);\r
1266  FixMMC3CHR(MMC3_cmd);\r
1267 }\r
1268 \r
1269 static void M249Power(void)\r
1270 {\r
1271  EXPREGS[0]=0;\r
1272  GenMMC3Power();\r
1273  SetWriteHandler(0x5000,0x5000,M249Write);\r
1274 }\r
1275 \r
1276 void Mapper249_Init(CartInfo *info)\r
1277 {\r
1278  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1279  cwrap=M249CW;\r
1280  pwrap=M249PW;\r
1281  info->Power=M249Power;\r
1282  AddExState(EXPREGS, 1, 0, "EXPR");\r
1283 }\r
1284 \r
1285 // ---------------------------- Mapper 250 ------------------------------\r
1286 \r
1287 static DECLFW(M250Write)\r
1288 {\r
1289  MMC3_CMDWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);\r
1290 }\r
1291 \r
1292 static DECLFW(M250IRQWrite)\r
1293 {\r
1294  MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);\r
1295 }\r
1296 \r
1297 static void M250_Power(void)\r
1298 {\r
1299  GenMMC3Power();\r
1300  SetWriteHandler(0x8000,0xBFFF,M250Write);\r
1301  SetWriteHandler(0xC000,0xFFFF,M250IRQWrite);\r
1302 }\r
1303 \r
1304 void Mapper250_Init(CartInfo *info)\r
1305 {\r
1306  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1307  info->Power=M250_Power;\r
1308 }\r
1309 \r
1310 // ---------------------------- Mapper 254 ------------------------------\r
1311 \r
1312 static DECLFR(MR254WRAM)\r
1313 {\r
1314   if(EXPREGS[0])\r
1315     return WRAM[A-0x6000];\r
1316   else\r
1317     return WRAM[A-0x6000]^EXPREGS[1];\r
1318 }\r
1319 \r
1320 static DECLFW(M254Write)\r
1321 {\r
1322  switch (A) {\r
1323   case 0x8000: EXPREGS[0]=0xff;\r
1324                break;\r
1325   case 0xA001: EXPREGS[1]=V;\r
1326  }\r
1327  MMC3_CMDWrite(A,V);\r
1328 }\r
1329 \r
1330 static void M254_Power(void)\r
1331 {\r
1332  GenMMC3Power();\r
1333  SetWriteHandler(0x8000,0xBFFF,M254Write);\r
1334  SetReadHandler(0x6000,0x7FFF,MR254WRAM);\r
1335 }\r
1336 \r
1337 void Mapper254_Init(CartInfo *info)\r
1338 {\r
1339  GenMMC3_Init(info, 128, 128, 8, info->battery);\r
1340  info->Power=M254_Power;\r
1341  AddExState(EXPREGS, 2, 0, "EXPR");\r
1342 }\r
1343 \r
1344 // ---------------------------- UNIF Boards -----------------------------\r
1345 \r
1346 void TBROM_Init(CartInfo *info)\r
1347 {\r
1348  GenMMC3_Init(info, 64, 64, 0, 0);\r
1349 }\r
1350 \r
1351 void TEROM_Init(CartInfo *info)\r
1352 {\r
1353  GenMMC3_Init(info, 32, 32, 0, 0);\r
1354 }\r
1355 \r
1356 void TFROM_Init(CartInfo *info)\r
1357 {\r
1358  GenMMC3_Init(info, 512, 64, 0, 0);\r
1359 }\r
1360 \r
1361 void TGROM_Init(CartInfo *info)\r
1362 {\r
1363  GenMMC3_Init(info, 512, 0, 0, 0);\r
1364 }\r
1365 \r
1366 void TKROM_Init(CartInfo *info)\r
1367 {\r
1368  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1369 }\r
1370 \r
1371 void TLROM_Init(CartInfo *info)\r
1372 {\r
1373  GenMMC3_Init(info, 512, 256, 0, 0);\r
1374 }\r
1375 \r
1376 void TSROM_Init(CartInfo *info)\r
1377 {\r
1378  GenMMC3_Init(info, 512, 256, 8, 0);\r
1379 }\r
1380 \r
1381 void TLSROM_Init(CartInfo *info)\r
1382 {\r
1383  GenMMC3_Init(info, 512, 256, 8, 0);\r
1384  cwrap=TKSWRAP;\r
1385  mwrap=GENNOMWRAP;\r
1386  PPU_hook=TKSPPU;\r
1387  AddExState(&PPUCHRBus, 1, 0, "PPUC");\r
1388 }\r
1389 \r
1390 void TKSROM_Init(CartInfo *info)\r
1391 {\r
1392  GenMMC3_Init(info, 512, 256, 8, info->battery);\r
1393  cwrap=TKSWRAP;\r
1394  mwrap=GENNOMWRAP;\r
1395  PPU_hook=TKSPPU;\r
1396  AddExState(&PPUCHRBus, 1, 0, "PPUC");\r
1397 }\r
1398 \r
1399 void TQROM_Init(CartInfo *info)\r
1400 {\r
1401  GenMMC3_Init(info, 512, 64, 0, 0);\r
1402  cwrap=TQWRAP;\r
1403  CHRRAMSize=8192;\r
1404  CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);\r
1405  SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);\r
1406 }\r
1407 \r
1408 void HKROM_Init(CartInfo *info)\r
1409 {\r
1410  GenMMC3_Init(info, 512, 512, 1, info->battery);\r
1411 }\r