--- /dev/null
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ * Copyright (C) 2006 CaH4e3\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+ *\r
+ *\r
+ * YOKO mapper, almost the same as 83, TODO: figure out difference\r
+ * Mapper 83 - 30-in-1 mapper, two modes for single game carts, one mode for \r
+ * multigame Dragon Ball Z Party\r
+ *\r
+ * Mortal Kombat 2 YOKO\r
+ * N-CXX(M), XX - ðàçìåðû PRG+CHR, 12 - 128+256, 22 - 256+256, 14 - 128+512\r
+ * \r
+ */\r
+\r
+#include "mapinc.h"\r
+\r
+static uint8 mode, bank, reg[11], low[4], dip, IRQa;\r
+static int32 IRQCount;\r
+static uint8 *WRAM=NULL;\r
+static uint32 WRAMSIZE;\r
+\r
+static uint8 is2kbank, isnot2kbank;\r
+\r
+static SFORMAT StateRegs[]=\r
+{\r
+ {&mode, 1, "MODE"},\r
+ {&bank, 1, "BANK"},\r
+ {&IRQCount, 4, "IRQC"},\r
+ {&IRQa, 1, "IRQA"},\r
+ {reg, 11, "REGS"},\r
+ {low, 4, "LOWR"},\r
+ {&is2kbank, 1, "IS2K"},\r
+ {&isnot2kbank, 1, "NT2K"},\r
+ {0}\r
+};\r
+\r
+static void UNLYOKOSync(void)\r
+{\r
+ setmirror((mode & 1)^1);\r
+ setchr2(0x0000,reg[3]);\r
+ setchr2(0x0800,reg[4]);\r
+ setchr2(0x1000,reg[5]);\r
+ setchr2(0x1800,reg[6]);\r
+ if(mode & 0x10)\r
+ {\r
+ uint32 base = (bank & 8) << 1;\r
+ setprg8(0x8000,(reg[0]&0x0f)|base);\r
+ setprg8(0xA000,(reg[1]&0x0f)|base);\r
+ setprg8(0xC000,(reg[2]&0x0f)|base);\r
+ setprg8(0xE000,0x0f|base);\r
+ }\r
+ else\r
+ {\r
+ if(mode & 8)\r
+ setprg32(0x8000,bank >> 1);\r
+ else\r
+ {\r
+ setprg16(0x8000,bank);\r
+ setprg16(0xC000,~0);\r
+ }\r
+ }\r
+}\r
+\r
+static void M83Sync(void)\r
+{\r
+ switch(mode & 3) // check if it is truth\r
+ {\r
+ case 0: setmirror(MI_V); break;\r
+ case 1: setmirror(MI_H); break;\r
+ case 2: setmirror(MI_0); break;\r
+ case 3: setmirror(MI_1); break;\r
+ }\r
+ if(is2kbank&&!isnot2kbank)\r
+ {\r
+ setchr2(0x0000,reg[0]);\r
+ setchr2(0x0800,reg[1]);\r
+ setchr2(0x1000,reg[6]);\r
+ setchr2(0x1800,reg[7]);\r
+ }\r
+ else\r
+ {\r
+ int x;\r
+ for(x=0;x<8;x++)\r
+ setchr1(x<<10, reg[x] | ((bank&0x30)<<4));\r
+ }\r
+ setprg8r(0x10,0x6000,0);\r
+ if(mode & 0x40)\r
+ {\r
+ setprg16(0x8000,(bank&0x3F)); // DBZ Party [p1]\r
+ setprg16(0xC000,(bank&0x30)|0xF);\r
+ }\r
+ else\r
+ {\r
+ setprg8(0x8000,reg[8]);\r
+ setprg8(0xA000,reg[9]);\r
+ setprg8(0xC000,reg[10]);\r
+ setprg8(0xE000,~0);\r
+ }\r
+}\r
+\r
+static DECLFW(UNLYOKOWrite)\r
+{\r
+ switch(A & 0x8C17)\r
+ {\r
+ case 0x8000: bank=V; UNLYOKOSync(); break;\r
+ case 0x8400: mode=V; UNLYOKOSync(); break;\r
+ case 0x8800: IRQCount&=0xFF00; IRQCount|=V; X6502_IRQEnd(FCEU_IQEXT); break;\r
+ case 0x8801: IRQa=mode&0x80; IRQCount&=0xFF; IRQCount|=V<<8; break;\r
+ case 0x8c00: reg[0]=V; UNLYOKOSync(); break;\r
+ case 0x8c01: reg[1]=V; UNLYOKOSync(); break;\r
+ case 0x8c02: reg[2]=V; UNLYOKOSync(); break;\r
+ case 0x8c10: reg[3]=V; UNLYOKOSync(); break;\r
+ case 0x8c11: reg[4]=V; UNLYOKOSync(); break;\r
+ case 0x8c16: reg[5]=V; UNLYOKOSync(); break;\r
+ case 0x8c17: reg[6]=V; UNLYOKOSync(); break;\r
+ }\r
+}\r
+\r
+static DECLFW(M83Write)\r
+{\r
+ switch(A)\r
+ {\r
+ case 0x8000: is2kbank = 1;\r
+ case 0xB000: // Dragon Ball Z Party [p1] BMC\r
+ case 0xB0FF: // Dragon Ball Z Party [p1] BMC \r
+ case 0xB1FF: bank=V; mode |= 0x40; M83Sync(); break; // Dragon Ball Z Party [p1] BMC\r
+ case 0x8100: mode=V|(mode&0x40); M83Sync(); break;\r
+ case 0x8200: IRQCount&=0xFF00; IRQCount|=V; X6502_IRQEnd(FCEU_IQEXT); break;\r
+ case 0x8201: IRQa=mode&0x80; IRQCount&=0xFF; IRQCount|=V<<8; break;\r
+ case 0x8300: reg[8]=V; mode &= 0xBF; M83Sync(); break;\r
+ case 0x8301: reg[9]=V; mode &= 0xBF; M83Sync(); break;\r
+ case 0x8302: reg[10]=V; mode &= 0xBF; M83Sync(); break;\r
+ case 0x8310: reg[0]=V; M83Sync(); break;\r
+ case 0x8311: reg[1]=V; M83Sync(); break;\r
+ case 0x8312: reg[2]=V; isnot2kbank = 1; M83Sync(); break;\r
+ case 0x8313: reg[3]=V; isnot2kbank = 1; M83Sync(); break;\r
+ case 0x8314: reg[4]=V; isnot2kbank = 1; M83Sync(); break;\r
+ case 0x8315: reg[5]=V; isnot2kbank = 1; M83Sync(); break;\r
+ case 0x8316: reg[6]=V; M83Sync(); break;\r
+ case 0x8317: reg[7]=V; M83Sync(); break;\r
+ }\r
+}\r
+\r
+static DECLFR(UNLYOKOReadDip)\r
+{\r
+ return (X.DB&0xFC)|dip;\r
+}\r
+\r
+static DECLFR(UNLYOKOReadLow)\r
+{\r
+ return low[A & 3];\r
+}\r
+\r
+static DECLFW(UNLYOKOWriteLow)\r
+{\r
+ low[A & 3] = V;\r
+}\r
+\r
+static void UNLYOKOPower(void)\r
+{\r
+ mode = bank = 0;\r
+ dip = 3;\r
+ UNLYOKOSync(); \r
+ SetReadHandler(0x5000,0x53FF,UNLYOKOReadDip);\r
+ SetReadHandler(0x5400,0x5FFF,UNLYOKOReadLow);\r
+ SetWriteHandler(0x5400,0x5FFF,UNLYOKOWriteLow);\r
+ SetReadHandler(0x8000,0xFFFF,CartBR);\r
+ SetWriteHandler(0x8000,0xFFFF,UNLYOKOWrite);\r
+}\r
+\r
+static void M83Power(void)\r
+{\r
+ is2kbank = 0;\r
+ isnot2kbank = 0;\r
+ mode = bank = 0;\r
+ dip = 0;\r
+ M83Sync();\r
+ SetReadHandler(0x5000,0x5000,UNLYOKOReadDip);\r
+ SetReadHandler(0x5100,0x5103,UNLYOKOReadLow);\r
+ SetWriteHandler(0x5100,0x5103,UNLYOKOWriteLow);\r
+ SetReadHandler(0x6000,0x7fff,CartBR);\r
+ SetWriteHandler(0x6000,0x7fff,CartBW); // Pirate Dragon Ball Z Party [p1] used if for saves instead of seraial EEPROM\r
+ SetReadHandler(0x8000,0xffff,CartBR);\r
+ SetWriteHandler(0x8000,0xffff,M83Write);\r
+}\r
+\r
+static void UNLYOKOReset(void)\r
+{\r
+ dip = (dip + 1) & 3;\r
+ mode = bank = 0;\r
+ UNLYOKOSync(); \r
+}\r
+\r
+static void M83Reset(void)\r
+{\r
+ dip ^= 1;\r
+ M83Sync(); \r
+}\r
+\r
+static void M83Close(void)\r
+{\r
+ if(WRAM)\r
+ FCEU_gfree(WRAM);\r
+ WRAM=NULL;\r
+}\r
+\r
+static void FP_FASTAPASS(1) UNLYOKOIRQHook(int a)\r
+{\r
+ if(IRQa)\r
+ {\r
+ IRQCount-=a;\r
+ if(IRQCount<0)\r
+ {\r
+ X6502_IRQBegin(FCEU_IQEXT);\r
+ IRQa=0;\r
+ IRQCount=0xFFFF;\r
+ }\r
+ }\r
+}\r
+\r
+static void UNLYOKOStateRestore(int version)\r
+{\r
+ UNLYOKOSync();\r
+}\r
+\r
+static void M83StateRestore(int version)\r
+{\r
+ M83Sync(); \r
+}\r
+\r
+void UNLYOKO_Init(CartInfo *info)\r
+{\r
+ info->Power=UNLYOKOPower;\r
+ info->Reset=UNLYOKOReset;\r
+ MapIRQHook=UNLYOKOIRQHook;\r
+ GameStateRestore=UNLYOKOStateRestore;\r
+ AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
+\r
+void Mapper83_Init(CartInfo *info)\r
+{\r
+ info->Power=M83Power;\r
+ info->Reset=M83Reset;\r
+ info->Close=M83Close;\r
+ MapIRQHook=UNLYOKOIRQHook;\r
+ GameStateRestore=M83StateRestore;\r
+\r
+ WRAMSIZE=8192;\r
+ WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);\r
+ SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);\r
+ AddExState(WRAM, WRAMSIZE, 0, "WRAM");\r
+\r
+ AddExState(&StateRegs, ~0, 0, 0);\r
+}\r