merge mappers from FCEU-mm
[fceu.git] / boards / yoko.c
diff --git a/boards/yoko.c b/boards/yoko.c
new file mode 100644 (file)
index 0000000..a83e871
--- /dev/null
@@ -0,0 +1,269 @@
+/* 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