updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
authornotaz <notasas@gmail.com>
Mon, 30 Apr 2007 14:16:20 +0000 (14:16 +0000)
committernotaz <notasas@gmail.com>
Mon, 30 Apr 2007 14:16:20 +0000 (14:16 +0000)
git-svn-id: file:///home/notaz/opt/svn/fceu@117 be3aeb3a-fb24-0410-a615-afba39da0efa

170 files changed:
Makefile.base
boards/112.c [new file with mode: 0644]
boards/164.c [new file with mode: 0644]
boards/183.c [new file with mode: 0644]
boards/186.c [new file with mode: 0644]
boards/8157.c [new file with mode: 0644]
boards/8237.c [new file with mode: 0644]
boards/90.c [new file with mode: 0644]
boards/Makefile
boards/addrlatch.c [new file with mode: 0644]
boards/bonza.c [new file with mode: 0644]
boards/datalatch.c [new file with mode: 0644]
boards/deirom.c [new file with mode: 0644]
boards/dream.c [new file with mode: 0644]
boards/h2288.c
boards/karaoke.c [new file with mode: 0644]
boards/konami-qtai.c [new file with mode: 0644]
boards/malee.c
boards/mapinc.h
boards/mmc1.c [new file with mode: 0644]
boards/mmc3.c [new file with mode: 0644]
boards/mmc3.h [new file with mode: 0644]
boards/mmc5.c [new file with mode: 0644]
boards/n106.c [new file with mode: 0644]
boards/novel.c
boards/sachen.c
boards/simple.c [deleted file]
boards/subor.c [new file with mode: 0644]
boards/super24.c
boards/supervision.c
boards/tengen.c [new file with mode: 0644]
cart.c
cart.h
driver.h
drivers/gp2x/main.c
fce.c
fce.h
fds.c
fds.h
file.h
general.c
general.h
git.h
ines-bad.h [new file with mode: 0644]
ines-correct.h [new file with mode: 0644]
ines.c
ines.h
input.c
input.h
mappers/105.c [deleted file]
mappers/113.c
mappers/117.c
mappers/15.c
mappers/151.c
mappers/16.c
mappers/17.c
mappers/18.c
mappers/180.c
mappers/182.c [deleted file]
mappers/183.c [new file with mode: 0644]
mappers/187.c [new file with mode: 0644]
mappers/189.c
mappers/19.c [deleted file]
mappers/193.c [new file with mode: 0644]
mappers/200.c [new file with mode: 0644]
mappers/201.c [new file with mode: 0644]
mappers/202.c [new file with mode: 0644]
mappers/203.c [new file with mode: 0644]
mappers/204.c [new file with mode: 0644]
mappers/208.c [new file with mode: 0644]
mappers/21.c
mappers/211.c [new file with mode: 0644]
mappers/212.c [new file with mode: 0644]
mappers/213.c [new file with mode: 0644]
mappers/214.c [new file with mode: 0644]
mappers/215.c [new file with mode: 0644]
mappers/217.c [new file with mode: 0644]
mappers/22.c
mappers/225.c
mappers/226.c
mappers/227.c
mappers/228.c
mappers/229.c
mappers/23.c
mappers/230.c [new file with mode: 0644]
mappers/231.c [new file with mode: 0644]
mappers/232.c
mappers/234.c
mappers/235.c [new file with mode: 0644]
mappers/240.c
mappers/241.c [new file with mode: 0644]
mappers/242.c
mappers/244.c [new file with mode: 0644]
mappers/246.c
mappers/248.c [deleted file]
mappers/24and26.c
mappers/25.c
mappers/255.c [new file with mode: 0644]
mappers/27.c [new file with mode: 0644]
mappers/32.c
mappers/33.c
mappers/40.c
mappers/41.c
mappers/42.c
mappers/43.c
mappers/46.c
mappers/50.c [moved from mappers/112.c with 50% similarity]
mappers/51.c
mappers/57.c [moved from mappers/249.c with 64% similarity]
mappers/58.c [new file with mode: 0644]
mappers/59.c [new file with mode: 0644]
mappers/6.c
mappers/60.c [new file with mode: 0644]
mappers/61.c [moved from mappers/245.c with 58% similarity]
mappers/62.c [new file with mode: 0644]
mappers/64.c [deleted file]
mappers/65.c
mappers/67.c
mappers/68.c
mappers/69.c
mappers/71.c
mappers/72.c
mappers/73.c
mappers/75.c
mappers/76.c
mappers/77.c
mappers/79.c
mappers/8.c
mappers/80.c
mappers/82.c
mappers/83.c
mappers/85.c
mappers/86.c
mappers/88.c
mappers/89.c
mappers/90.c [deleted file]
mappers/91.c [new file with mode: 0644]
mappers/92.c
mappers/95.c
mappers/97.c
mappers/99.c
mappers/Makefile
mappers/emu2413.c [new file with mode: 0644]
mappers/emu2413.h [new file with mode: 0644]
mappers/emutypes.h [new file with mode: 0644]
mappers/fmopl.c [deleted file]
mappers/fmopl.h [deleted file]
mappers/mapinc.h
mappers/mapshare.h [deleted file]
mappers/mmc2and4.c
mappers/simple.c
mappers/vrc7snd.c [deleted file]
mappers/vrc7tone.h [new file with mode: 0644]
md5.c [new file with mode: 0644]
md5.h [new file with mode: 0644]
memory.h
nsf.c
nsf.h
sound.c
sound.h
state.c
state.h
svga.c
svga.h
unif.c
unif.h
video.c
vsuni.c [new file with mode: 0644]
vsuni.h [new file with mode: 0644]
x6502.h

index 734b1b1..af0e348 100644 (file)
@@ -1,11 +1,11 @@
 CFLAGS  = -Wall  ${TFLAGS}
-OBJECTS = fce.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o
+OBJECTS = fce.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o md5.o vsuni.o
 # x6502.o
 
 fceu:          fceu2
 include        mappers/Makefile
 include boards/Makefile
-include mbshare/Makefile
+#include mbshare/Makefile
 include input/Makefile
 
 fceu2:         ${OBJECTS} ${MOBJS} ${MUOBJS} ${MUSOBJS} ${INPOBJS} ${OBJDRIVER}
diff --git a/boards/112.c b/boards/112.c
new file mode 100644 (file)
index 0000000..a58cf5c
--- /dev/null
@@ -0,0 +1,89 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 reg[8];
+static uint8 mirror, cmd;
+static uint8 *WRAM=NULL;
+static SFORMAT StateRegs[]=
+{
+  {&cmd, 1, "CMD"},
+  {&mirror, 1, "MIRR"},
+  {reg, 8, "REGS"},
+  {0}
+};
+
+static void Sync(void)
+{
+  setmirror(mirror^1);
+  setprg8(0x8000,reg[0]);
+  setprg8(0xA000,reg[1]);
+  setchr2(0x0000,reg[2]>>1);
+  setchr2(0x0800,reg[3]>>1);
+  setchr1(0x1000,reg[4]);
+  setchr1(0x1400,reg[5]);
+  setchr1(0x1800,reg[6]);
+  setchr1(0x1C00,reg[7]);
+}
+
+static DECLFW(M112Write)
+{
+  switch(A)
+  {
+    case 0xe000: mirror=V&1; Sync(); ;break;
+    case 0x8000: cmd=V&7; break;
+    case 0xa000: reg[cmd]=V; Sync(); break;
+  }
+}
+
+static void M112Close(void)
+{
+  if(WRAM)
+    FCEU_gfree(WRAM);
+  WRAM = NULL;
+}
+
+static void M112Power(void)
+{
+  Sync();
+  setprg16(0xC000,~0);
+  setprg8r(0x10,0x6000,0);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xFFFF,M112Write);
+  SetReadHandler(0x6000,0x7FFF,CartBR);
+  SetWriteHandler(0x6000,0x7FFF,CartBW);
+}
+
+static void StateRestore(int version)
+{
+  Sync();
+}
+
+void Mapper112_Init(CartInfo *info)
+{
+  info->Power=M112Power;
+  info->Close=M112Close;
+  GameStateRestore=StateRestore;
+  WRAM=(uint8*)FCEU_gmalloc(8192);
+  SetupCartPRGMapping(0x10,WRAM,8192,1);
+  AddExState(WRAM, 8192, 0, "WRAM");
+  AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/164.c b/boards/164.c
new file mode 100644 (file)
index 0000000..5b4bf05
--- /dev/null
@@ -0,0 +1,110 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd;
+static uint8 DRegs[8];
+
+static SFORMAT StateRegs[]=
+{
+  {&cmd, 1, "CMD"},
+  {DRegs, 8, "DREG"},
+  {0}
+};
+
+static void Sync(void)
+{
+  setprg32(0x8000,(DRegs[0]<<4)|(DRegs[1]&0xF));
+}
+
+static void StateRestore(int version)
+{
+  Sync();
+}
+
+static DECLFW(Write)
+{
+  switch (A&0x7300)
+  {
+    case 0x5100: DRegs[0]=V; Sync(); break;
+    case 0x5000: DRegs[1]=V; Sync(); break;
+  }
+}
+
+static DECLFW(Write2)
+{
+  switch (A&0x7300)
+  {
+    case 0x5200: DRegs[0]=V; Sync(); break;
+    case 0x5000: DRegs[1]=V; Sync(); break;
+  }
+}
+
+static uint8 WRAM[8192];
+static DECLFR(AWRAM)
+{
+  return(WRAM[A-0x6000]);
+}
+
+static DECLFW(BWRAM)
+{
+  WRAM[A-0x6000]=V;
+}
+
+static void Power(void)
+{
+  memset(DRegs,0,8);
+  DRegs[1]=0xFF;
+  setchr8(0);
+  cmd=0;
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x4020,0xFFFF,Write);
+  SetReadHandler(0x6000,0x7FFF,AWRAM);
+  SetWriteHandler(0x6000,0x7FFF,BWRAM);
+  Sync();
+}
+
+static void Power2(void)
+{
+  memset(DRegs,0,8);
+  DRegs[1]=0xFF;
+  setchr8(0);
+  cmd=0;
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x4020,0xFFFF,Write2);
+  SetReadHandler(0x6000,0x7FFF,AWRAM);
+  SetWriteHandler(0x6000,0x7FFF,BWRAM);
+  Sync();
+}
+
+void Mapper164_Init(CartInfo *info)
+{
+  info->Power=Power;
+  GameStateRestore=StateRestore;
+  AddExState(&StateRegs, ~0, 0, 0);
+}
+
+void Mapper163_Init(CartInfo *info)
+{
+  info->Power=Power2;
+  GameStateRestore=StateRestore;
+  AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/183.c b/boards/183.c
new file mode 100644 (file)
index 0000000..94cf072
--- /dev/null
@@ -0,0 +1,117 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+ * Gimmick Bootleg\r
+ */\r
+\r
+#include "mapinc.h"\r
+\r
+static uint8 prg[4];\r
+static uint8 chr[8];\r
+static uint8 IRQCount;\r
+static uint8 IRQPre;\r
+static uint8 IRQa;\r
+\r
+static SFORMAT StateRegs[]=\r
+{\r
+  {prg, 4, "PRG"},\r
+  {chr, 8, "CHR"},\r
+  {&IRQCount, 1, "IRQCOUNT"},\r
+  {&IRQPre, 1, "IRQPRE"},\r
+  {&IRQa, 1, "IRQA"},\r
+  {0}\r
+};\r
+\r
+static void SyncPrg(void)\r
+{\r
+  setprg8(0x6000,0);\r
+  setprg8(0x8000,prg[0]);\r
+  setprg8(0xA000,prg[1]);\r
+  setprg8(0xC000,prg[2]);\r
+  setprg8(0xE000,~0);\r
+}\r
+\r
+static void SyncChr(void)\r
+{\r
+  int i;\r
+  for(i=0; i<8; i++)\r
+     setchr1(i<<10,chr[i]);\r
+}\r
+\r
+static void StateRestore(int version)\r
+{\r
+  SyncPrg();\r
+  SyncChr();\r
+}\r
+\r
+static DECLFW(M183Write)\r
+{\r
+  if(((A&0xF80C)>=0xB000)&&((A&0xF80C)<=0xE00C))\r
+  {\r
+    uint8 index=(((A&0x7000)>>11)-6)|((A&8)>>3);\r
+    chr[index]=(chr[index]&(0xF0>>(A&4)))|((V&0x0F)<<(A&4));\r
+    SyncChr();\r
+  }\r
+  else switch (A&0xF80C)\r
+  {\r
+    case 0x8800: prg[0]=V; SyncPrg(); break;\r
+    case 0xA800: prg[1]=V; SyncPrg(); break;\r
+    case 0xA000: prg[2]=V; SyncPrg(); break;\r
+    case 0x9800: switch (V&3)\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
+                 break;\r
+    case 0xF000: IRQCount=((IRQCount&0xF0)|(V&0xF)); break;\r
+    case 0xF004: IRQCount=((IRQCount&0x0F)|((V&0xF)<<4)); break;\r
+    case 0xF008: IRQa=V; if(!V)IRQPre=0; X6502_IRQEnd(FCEU_IQEXT); break;\r
+    case 0xF00C: IRQPre=16; break;\r
+  }\r
+}\r
+\r
+static void M183IRQCounter(void)\r
+{\r
+  if(IRQa)\r
+  {\r
+    IRQCount++;\r
+    if((IRQCount-IRQPre)==238)\r
+      X6502_IRQBegin(FCEU_IQEXT);\r
+  }\r
+}\r
+\r
+static void M183Power(void)\r
+{\r
+  IRQPre=IRQCount=IRQa=0;\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x8000,0xFFFF,M183Write);\r
+  SetReadHandler(0x6000,0x7FFF,CartBR);\r
+  SyncPrg();\r
+  SyncChr();\r
+}\r
+\r
+void Mapper183_Init(CartInfo *info)\r
+{\r
+  info->Power=M183Power;\r
+  GameHBIRQHook=M183IRQCounter;\r
+  GameStateRestore=StateRestore;\r
+  AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
diff --git a/boards/186.c b/boards/186.c
new file mode 100644 (file)
index 0000000..3698c6c
--- /dev/null
@@ -0,0 +1,104 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+ * Family Study Box by Fukutake Shoten\r
+ */\r
+\r
+#include "mapinc.h"\r
+\r
+static uint8 SWRAM[2816];\r
+static uint8 *WRAM=NULL;\r
+static uint8 regs[4];\r
+\r
+static SFORMAT StateRegs[]=\r
+{\r
+  {regs, 4, "DREG"},\r
+  {SWRAM, 2816, "SWRAM"},\r
+  {0}\r
+};\r
+\r
+static void Sync(void)\r
+{\r
+  setprg8r(0x10,0x6000,regs[0]>>6);\r
+  setprg16(0x8000,regs[1]);\r
+  setprg16(0xc000,0);\r
+}\r
+\r
+static DECLFW(M186Write)\r
+{\r
+  if(A&0x4203) regs[A&3]=V;\r
+  Sync();\r
+}\r
+\r
+static DECLFR(M186Read)\r
+{\r
+  switch(A)\r
+  {\r
+    case 0x4200: return 0x00; break;\r
+    case 0x4201: return 0x00; break;\r
+    case 0x4202: return 0x40; break;\r
+    case 0x4203: return 0x00; break;\r
+  }\r
+  return 0xFF;\r
+}\r
+\r
+static DECLFR(ASWRAM)\r
+{\r
+  return(SWRAM[A-0x4400]);\r
+}\r
+static DECLFW(BSWRAM)\r
+{\r
+  SWRAM[A-0x4400]=V;\r
+}\r
+\r
+static void M186Power(void)\r
+{\r
+  setchr8(0);\r
+  SetReadHandler(0x6000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x6000,0xFFFF,CartBW);\r
+  SetReadHandler(0x4200,0x43FF,M186Read);\r
+  SetWriteHandler(0x4200,0x43FF,M186Write);\r
+  SetReadHandler(0x4400,0x4EFF,ASWRAM);\r
+  SetWriteHandler(0x4400,0x4EFF,BSWRAM);\r
+  regs[0]=regs[1]=regs[2]=regs[3];\r
+  Sync();\r
+}\r
+\r
+static void M186Close(void)\r
+{\r
+  if(WRAM)\r
+    FCEU_gfree(WRAM);\r
+  WRAM=NULL;\r
+}\r
+\r
+static void M186Restore(int version)\r
+{\r
+  Sync();\r
+}\r
+\r
+void Mapper186_Init(CartInfo *info)\r
+{\r
+  info->Power=M186Power;\r
+  info->Close=M186Close;\r
+  GameStateRestore=M186Restore;\r
+  WRAM=(uint8*)FCEU_gmalloc(32384);\r
+  SetupCartPRGMapping(0x10,WRAM,32384,1);\r
+  AddExState(WRAM, 32384, 0, "WRAM");\r
+  AddExState(StateRegs, ~0, 0, 0);\r
+}\r
diff --git a/boards/8157.c b/boards/8157.c
new file mode 100644 (file)
index 0000000..3c4a4fb
--- /dev/null
@@ -0,0 +1,77 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+#include "mapinc.h"\r
+\r
+static uint16 cmdreg;\r
+static SFORMAT StateRegs[]=\r
+{\r
+  {&cmdreg, 2, "CMDREG"},\r
+  {0}\r
+};\r
+\r
+static void Sync(void)\r
+{\r
+  setprg16r((cmdreg&0x060)>>5,0x8000,(cmdreg&0x01C)>>2);\r
+  setprg16r((cmdreg&0x060)>>5,0xC000,(cmdreg&0x200)?(~0):0);\r
+  setmirror(((cmdreg&2)>>1)^1);\r
+}\r
+\r
+static DECLFR(UNL8157Read)\r
+{\r
+  if(cmdreg&0x100)\r
+    return 0xFF;\r
+  else\r
+    return CartBR(A);\r
+}\r
+\r
+static DECLFW(UNL8157Write)\r
+{\r
+  cmdreg=A;\r
+  Sync();\r
+}\r
+\r
+static void UNL8157Power(void)\r
+{\r
+  setchr8(0);\r
+  SetWriteHandler(0x8000,0xFFFF,UNL8157Write);\r
+  SetReadHandler(0x8000,0xFFFF,UNL8157Read);\r
+  cmdreg=0;\r
+  Sync();\r
+}\r
+\r
+static void UNL8157Reset(void)\r
+{\r
+  cmdreg=0;\r
+  Sync();\r
+}\r
+\r
+static void UNL8157Restore(int version)\r
+{\r
+  Sync();\r
+}\r
+\r
+void UNL8157_Init(CartInfo *info)\r
+{\r
+  info->Power=UNL8157Power;\r
+  info->Reset=UNL8157Reset;\r
+  GameStateRestore=UNL8157Restore;\r
+  AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
diff --git a/boards/8237.c b/boards/8237.c
new file mode 100644 (file)
index 0000000..5b4e2df
--- /dev/null
@@ -0,0 +1,93 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 cmdin;
+static uint8 UNL8237_perm[8] = {0, 2, 6, 1, 7, 3, 4, 5};
+
+static void UNL8237CW(uint32 A, uint8 V)
+{
+  setchr1(A,((EXPREGS[1]&4)<<6)|V);
+}
+
+static void UNL8237PW(uint32 A, uint8 V)
+{
+  if(EXPREGS[0]&0x80)
+  {
+    if(EXPREGS[0]&0x20)
+      setprg32(0x8000,(EXPREGS[0]&0xF)>>1);
+    else
+    {
+      setprg16(0x8000,(EXPREGS[0]&0x1F));
+      setprg16(0xC000,(EXPREGS[0]&0x1F));
+    }
+  }
+  else
+    setprg8(A,V&0x3F);
+}
+
+static DECLFW(UNL8237Write)
+{
+  if((A&0xF000)==0xF000)
+    IRQCount=V;
+  else if((A&0xF000)==0xE000)
+    X6502_IRQEnd(FCEU_IQEXT);
+  else switch(A&0xE001)
+  {
+    case 0x8000: setmirror(((V|(V>>7))&1)^1); break;
+    case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(UNL8237_perm[V&7])); cmdin=1; break;
+    case 0xC000: if(cmdin)
+                 {
+                   MMC3_CMDWrite(0x8001,V);
+                   cmdin=0;
+                 }
+                 break;
+  }
+}
+
+static DECLFW(UNL8237ExWrite)
+{
+  switch(A)
+  {
+    case 0x5000: EXPREGS[0]=V; FixMMC3PRG(MMC3_cmd); break;
+    case 0x5001: EXPREGS[1]=V; FixMMC3CHR(MMC3_cmd); break;
+  }
+}
+
+static void UNL8237Power(void)
+{
+  IRQa=1;
+  EXPREGS[0]=EXPREGS[1]=0;
+  GenMMC3Power();
+  SetWriteHandler(0x8000,0xFFFF,UNL8237Write);
+  SetWriteHandler(0x5000,0x7FFF,UNL8237ExWrite);
+}
+
+void UNL8237_Init(CartInfo *info)
+{
+  GenMMC3_Init(info, 256, 256, 0, 0);
+  cwrap=UNL8237CW;
+  pwrap=UNL8237PW;
+  info->Power=UNL8237Power;
+  AddExState(EXPREGS, 3, 0, "EXPR");
+  AddExState(&cmdin, 1, 0, "CMDIN");
+}
diff --git a/boards/90.c b/boards/90.c
new file mode 100644 (file)
index 0000000..489a540
--- /dev/null
@@ -0,0 +1,408 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static int is209;
+
+static uint8 IRQMode;        // from $c001
+static uint8 IRQPre;         // from $c004
+static uint8 IRQPreSize;     // from $c007
+static uint8 IRQCount;       // from $c005
+static uint8 IRQXOR;         // Loaded from $C006
+static uint8 IRQa;           // $c002, $c003, and $c000
+
+static uint8 mul[2];
+static uint8 regie;
+
+static uint8 tkcom[4];
+static uint8 prgb[4];
+static uint8 chrlow[8];
+static uint8 chrhigh[8];
+
+static uint16 names[4];
+static uint8 tekker;
+
+static SFORMAT Tek_StateRegs[]={
+  {&IRQMode, 1, "IRQMODE"},
+  {&IRQPre, 1, "IRQPRE"},
+  {&IRQPreSize, 1, "IRQPRESIZE"},
+  {&IRQCount, 1, "IRQC"},
+  {&IRQXOR, 1, "IRQXOR"},
+  {&IRQa, 1, "IRQa"},
+  {mul, 2, "MUL"},
+  {&regie, 1, "REGI"},
+  {tkcom, 4, "TKCO"},
+  {prgb, 4, "PRGB"},
+  {chrlow, 4, "CHRL"},
+  {chrhigh, 8, "CHRH"},
+  {&names[0], 2|FCEUSTATE_RLSB, "NMS0"},
+  {&names[1], 2|FCEUSTATE_RLSB, "NMS1"},
+  {&names[2], 2|FCEUSTATE_RLSB, "NMS2"},
+  {&names[3], 2|FCEUSTATE_RLSB, "NMS3"},
+  {&tekker, 1, "TEKR"},
+  {0}
+};
+
+static DECLFR(M90Read)
+{
+  switch(A)
+  {
+    case 0x5800: return (mul[0]*mul[1]);
+    case 0x5801: return((mul[0]*mul[1])>>8);
+    case 0x5803: return (regie);
+    default: return(tekker);
+  }
+}
+
+static void mira(void)
+{
+  if(tkcom[0]&0x20 && is209)
+  {
+    int x;
+    if(tkcom[0]&0x40)        // Name tables are ROM-only
+    {
+      for(x=0;x<4;x++)
+         setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
+    }
+    else                        // Name tables can be RAM or ROM.
+    {
+      for(x=0;x<4;x++)
+      {
+        if((tkcom[2]&0x80)==(names[x]&0x80))        // RAM selected.
+          setntamem(NTARAM+((names[x]&0x1)<<10),1,x);
+        else
+          setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
+      }
+    }
+  }
+  else
+  {
+    switch(tkcom[1]&3)
+    {
+      case 0: setmirror(MI_V); break;
+      case 1: setmirror(MI_H); break;
+      case 2: setmirror(MI_0); break;
+      case 3: setmirror(MI_1); break;
+    }
+  }
+}
+
+static void tekprom(void)
+{
+  uint32 bankmode=((tkcom[3]&6)<<5);
+  switch(tkcom[0]&3)
+  {
+    case 1:              // 16 KB
+         setprg16(0x8000,(prgb[0]&0x1F)|((tkcom[3]&6)<<4));
+         setprg16(0xC000,(prgb[2]&0x1F)|((tkcom[3]&6)<<4));
+         break;
+    case 2:              //2 = 8 KB ??
+         if(tkcom[0]&0x4)
+         {
+           setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
+           setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
+           setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
+           setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
+         }
+         else
+         {
+           if(tkcom[0]&0x80)
+             setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
+           setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
+           setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
+           setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
+           setprg8(0xe000,((~0)&0x3F)|bankmode);
+         }
+         break;
+    case 0:
+    case 3:
+         setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
+         setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
+         setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
+         setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
+         break;
+  }
+}
+
+static void tekvrom(void)
+{
+  int x, bank=0, mask=0xFFFF;
+  if(!(tkcom[3]&0x20))
+  {
+    bank=(tkcom[3]&1)|((tkcom[3]&0x18)>>2);
+    switch (tkcom[0]&0x18)
+    {
+      case 0x00: bank<<=5; mask=0x1F; break;
+      case 0x08: bank<<=6; mask=0x3F; break;
+      case 0x10: bank<<=7; mask=0x7F; break;
+      case 0x18: bank<<=8; mask=0xFF; break;
+    }
+  }
+  switch(tkcom[0]&0x18)
+  {
+    case 0x00:      // 8KB
+         setchr8(((chrlow[0]|(chrhigh[0]<<8))&mask)|bank);
+         break;
+    case 0x08:      // 4KB
+         for(x=0;x<8;x+=4)
+            setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+         break;
+    case 0x10:      // 2KB
+         for(x=0;x<8;x+=2)
+            setchr2(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+         break;
+    case 0x18:      // 1KB
+         for(x=0;x<8;x++)
+            setchr1(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+         break;
+  }
+}
+
+static DECLFW(M90Write)
+{
+  if(A==0x5800) mul[0]=V;
+  else if(A==0x5801) mul[1]=V;
+  else if(A==0x5803) regie=V;
+
+  A&=0xF007;
+  if(A>=0x8000 && A<=0x8003)
+  {
+    prgb[A&3]=V;
+    tekprom();
+  }
+  else if(A>=0x9000 && A<=0x9007)
+  {
+    chrlow[A&7]=V;
+    tekvrom();
+  }
+  else if(A>=0xa000 && A<=0xa007)
+  {
+    chrhigh[A&7]=V;
+    tekvrom();
+  }
+  else if(A>=0xb000 && A<=0xb007)
+  {
+    if(A&4)
+    {
+      names[A&3]&=0x00FF;
+      names[A&3]|=V<<8;
+    }
+    else
+    {
+      names[A&3]&=0xFF00;
+      names[A&3]|=V;
+    }
+    mira();
+  }
+  else if(A>=0xd000 && A<=0xdfff)
+  {
+    tkcom[A&3]=V;
+    tekprom();
+    tekvrom();
+    mira();
+/*
+  switch (A&3)
+  {
+   case 00: FCEU_printf("Main Control Register:\n");
+            FCEU_printf("  PGR Banking mode: %d\n",V&7);
+            FCEU_printf("  CHR Banking mode: %d\n",(V>>3)&3);
+            FCEU_printf("  6000-7FFF addresses mapping: %s\n",(V&0x80)?"Yes":"No");
+            FCEU_printf("  Nametable control: %s\n",(V&0x20)?"Enabled":"Disabled");
+            if(V&0x20)
+               FCEU_printf("  Nametable can be: %s\n",(V&0x40)?"ROM Only":"RAM or ROM");
+            break;
+   case 01: FCEU_printf("Mirroring mode: ");
+            switch (V&3)
+            {
+             case 00: FCEU_printf("Vertical\n");break;
+             case 01: FCEU_printf("Horizontal\n");break;
+             case 02: FCEU_printf("Nametable 0 only\n");break;
+             case 03: FCEU_printf("Nametable 1 only\n");break;
+            }
+            FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off");
+            break;
+   case 02: if((((tkcom[0])>>5)&3)==1)
+              FCEU_printf("Nametable ROM/RAM select mode: %d\n",V>>7);
+            break;
+   case 03:
+            FCEU_printf("CHR Banking mode: %s\n",(V&0x20)?"Entire CHR ROM":"256Kb Switching mode");
+            if(!(V&0x20)) FCEU_printf("256K CHR bank number: %02x\n",(V&1)|((V&0x18)>>2));
+            FCEU_printf("512K PRG bank number: %d\n",(V&6)>>1);
+            FCEU_printf("CHR Bank mirroring: %s\n",(V&0x80)?"Swapped":"Normal operate");
+  }
+*/
+  }
+  else switch(A)
+  {
+    case 0xc000: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable");
+                 IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break;
+    case 0xc002: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline);
+                 IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break;
+    case 0xc003: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline);
+                 IRQa=1;break;
+    case 0xc001: IRQMode=V;
+/*               FCEU_printf("IRQ Count method: ");
+               switch (IRQMode&3)
+               {
+                 case 00: FCEU_printf("M2 cycles\n");break;
+                 case 01: FCEU_printf("PPU A12 toggles\n");break;
+                 case 02: FCEU_printf("PPU reads\n");break;
+                 case 03: FCEU_printf("Writes to CPU space\n");break;
+               }
+               FCEU_printf("Counter prescaler size: %s\n",(IRQMode&4)?"3 bits":"8 bits");
+               FCEU_printf("Counter prescaler size adjust: %s\n",(IRQMode&8)?"Used C007":"Normal Operation");
+               if((IRQMode>>6)==2) FCEU_printf("Counter Down\n");
+                else if((IRQMode>>6)==1) FCEU_printf("Counter Up\n");
+                else FCEU_printf("Counter Stopped\n");
+*/               break;
+    case 0xc004: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
+                 IRQPre=V^IRQXOR;break;
+    case 0xc005: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
+                 IRQCount=V^IRQXOR;break;
+    case 0xc006: //FCEU_printf("Xor Value: %d\n",V);
+                 IRQXOR=V;break;
+    case 0xc007: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n");
+                 // else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n");
+                 // else FCEU_printf("Counter Stopped\n");
+                 IRQPreSize=V;break;
+  }
+}
+
+static void CCL(void)
+{
+  if((IRQMode>>6) == 1) // Count Up
+  {
+    IRQCount++;
+    if((IRQCount == 0) && IRQa)
+      X6502_IRQBegin(FCEU_IQEXT);
+  }
+  else if((IRQMode>>6) == 2) // Count down
+  {
+    IRQCount--;
+    if((IRQCount == 0xFF) && IRQa)
+      X6502_IRQBegin(FCEU_IQEXT);
+  }
+}
+
+static void ClockCounter(void)
+{
+  uint8 premask;
+
+  if(IRQMode & 0x4)
+    premask = 0x7;
+  else
+    premask = 0xFF;
+  if((IRQMode>>6) == 1) // Count up
+  {
+    IRQPre++;
+    if((IRQPre & premask) == 0) CCL();
+  }
+  else if((IRQMode>>6) == 2) // Count down
+  {
+    IRQPre--;
+    if((IRQPre & premask) == premask) CCL();
+  }
+}
+
+static void SLWrap(void)
+{
+  int x;
+  if((IRQMode&3)!=2) for(x=0;x<8;x++) ClockCounter();
+}
+
+static uint32 lastread;
+static void FP_FASTAPASS(1) M90PPU(uint32 A)
+{
+  if(lastread!=A)
+  {
+    lastread=A;
+    if((IRQMode&3)==2)
+    {
+      ClockCounter();
+      ClockCounter();
+    }
+  }
+}
+
+static void togglie()
+{
+  tekker>>=6;
+  if(tekker>3)
+    tekker=0;
+  else
+    tekker++;
+  tekker<<=6;
+  FCEU_printf("tekker=%04x\n",tekker);
+  memset(tkcom,0xff,sizeof(tkcom));
+  memset(prgb,0xff,sizeof(prgb));
+  tekprom();
+  tekvrom();
+}
+
+static void M90Restore(int version)
+{
+  tekprom();
+  tekvrom();
+  mira();
+}
+
+static void M90Power(void)
+{
+  SetWriteHandler(0x5000,0xffff,M90Write);
+  SetReadHandler(0x5000,0x5fff,M90Read);
+  SetReadHandler(0x6000,0xffff,CartBR);
+
+  mul[0]=mul[1]=regie=0xFF;
+
+  memset(tkcom,0xff,sizeof(tkcom));
+  memset(prgb,0xff,sizeof(prgb));
+  memset(chrlow,0xff,sizeof(chrlow));
+  memset(chrhigh,0xff,sizeof(chrhigh));
+  memset(names,0x00,sizeof(names));
+
+  tekker=0;
+
+  tekprom();
+  tekvrom();
+}
+
+
+void Mapper90_Init(CartInfo *info)
+{
+  is209=0;
+  info->Reset=togglie;
+  info->Power=M90Power;
+  PPU_hook = M90PPU;
+  GameHBIRQHook2 = SLWrap;
+  GameStateRestore=M90Restore;
+  AddExState(Tek_StateRegs, ~0, 0, 0);
+}
+
+void Mapper209_Init(CartInfo *info)
+{
+  is209=1;
+  info->Reset=togglie;
+  info->Power=M90Power;
+  PPU_hook = M90PPU;
+  GameHBIRQHook2 = SLWrap;
+  GameStateRestore=M90Restore;
+  AddExState(Tek_StateRegs, ~0, 0, 0);
+}
index 58dd4ef..b63f897 100644 (file)
@@ -1,9 +1,6 @@
-MUOBJS   =     boards/simple.o boards/malee.o boards/supervision.o boards/novel.o boards/super24.o boards/h2288.o boards/sachen.o
+MUOBJS += boards/mmc5.o boards/mmc3.o boards/mmc1.o boards/tengen.o boards/bonza.o boards/deirom.o
+MUOBJS += boards/dream.o boards/konami-qtai.o boards/n106.o boards/karaoke.o boards/90.o boards/112.o
+MUOBJS += boards/164.o boards/183.o boards/186.o boards/8237.o boards/8157.o boards/addrlatch.o
+MUOBJS += boards/datalatch.o boards/h2288.o boards/malee.o boards/novel.o boards/sachen.o
+MUOBJS += boards/subor.o boards/super24.o boards/supervision.o
 
-boards/simple.o:       boards/simple.c
-boards/malee.o:                boards/malee.c
-boards/supervision.o:  boards/supervision.c
-boards/novel.o:                boards/novel.c
-boards/super24.o:      boards/super24.c
-boards/h2288.o:                boards/h2288.c
-boards/sachen.o:       boards/sachen.c
diff --git a/boards/addrlatch.c b/boards/addrlatch.c
new file mode 100644 (file)
index 0000000..37be90a
--- /dev/null
@@ -0,0 +1,53 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+#include "mapinc.h"\r
+\r
+static uint16 addrlatche;\r
+\r
+//------------------ UNLCC21 ---------------------------\r
+\r
+static DECLFW(UNLCC21Write)\r
+{\r
+  addrlatche=A;\r
+  setchr8(addrlatche&1);\r
+  setmirror(MI_0+((addrlatche&2)>>1));\r
+}\r
+\r
+static void UNLCC21Power(void)\r
+{\r
+  setprg32(0x8000,0);\r
+  setchr8(0);\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x8000,0xffff,UNLCC21Write);\r
+}\r
+\r
+static void UNLCC21Restore(int version)\r
+{\r
+  setchr8(addrlatche&1);\r
+  setmirror(MI_0+((addrlatche&2)>>1));\r
+}\r
+\r
+void UNLCC21_Init(CartInfo *info)\r
+{\r
+  info->Power=UNLCC21Power;\r
+  GameStateRestore=UNLCC21Restore;\r
+  AddExState(&addrlatche, 2, 0, "ALATC");\r
+}\r
diff --git a/boards/bonza.c b/boards/bonza.c
new file mode 100644 (file)
index 0000000..5e572f1
--- /dev/null
@@ -0,0 +1,139 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 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
+#include "mapinc.h"\r
+\r
+static uint8 prg_reg;\r
+static uint8 chr_reg;\r
+\r
+static uint8 sim0reg, sim0bit, sim0byte, sim0parity, sim0bcnt;\r
+static uint16 sim0data;\r
+static uint8 sim0array[128] =\r
+{\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,\r
+  0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xAA,\r
+};\r
+\r
+static SFORMAT StateRegs[]=\r
+{\r
+  {&prg_reg, 1, "PREG"},\r
+  {&chr_reg, 1, "CREG"},\r
+  {0}\r
+};\r
+\r
+static void Sync(void)\r
+{\r
+  setprg32(0x8000, prg_reg);\r
+  setchr8(chr_reg);\r
+}\r
+\r
+static void StateRestore(int version)\r
+{\r
+  Sync();\r
+}\r
+\r
+static DECLFW(M216WriteHi)\r
+{\r
+// FCEU_printf("%04x:%04x\n",A,V);\r
+  prg_reg=A&1;\r
+  chr_reg=(A&0x0E)>>1;\r
+  Sync();\r
+}\r
+\r
+static DECLFW(M216Write5000)\r
+{\r
+// FCEU_printf("WRITE: %04x:%04x\n",A,V);\r
+  sim0reg=V;\r
+  if(!sim0reg)\r
+  {\r
+    sim0bit=sim0byte=sim0parity=0;\r
+    sim0data=sim0array[0];\r
+    sim0bcnt=0x80;\r
+  }\r
+  else if(sim0reg&0x20)\r
+  {\r
+    sim0bcnt=0x20;\r
+  }\r
+}\r
+\r
+static DECLFR(M216Read5000)\r
+{\r
+  if(sim0reg&0x60)\r
+  {\r
+    sim0reg=(sim0reg^(sim0reg<<1))&0x40;\r
+    return sim0reg;\r
+  }\r
+  else\r
+  {\r
+    uint8 sim0out=0;\r
+    if(sim0bit<8)\r
+    {\r
+//       sim0data=((sim0array[sim0byte]<<(sim0bit))&0x80)>>1;\r
+      sim0out=(sim0data&1)<<6;\r
+      sim0data>>=1;\r
+      sim0bit++;\r
+      sim0parity+=sim0data;\r
+    }\r
+    else if(sim0bit==8)\r
+    {\r
+      sim0bit++;\r
+      sim0out=sim0parity&1;\r
+    }\r
+    else if(sim0bit==9)\r
+    {\r
+      if(sim0byte==sim0bcnt)\r
+        sim0out=0x60;\r
+      else\r
+      {\r
+        sim0bit=0;\r
+        sim0byte++;\r
+        sim0data=sim0array[sim0byte];\r
+        sim0out=0;\r
+      }\r
+    }\r
+//    FCEU_printf("READ: %04x (%04x-%02x,%04x)\n",A,X.PC,sim0out,sim0byte);\r
+    return sim0out;\r
+  }\r
+}\r
+\r
+static void Power(void)\r
+{\r
+  prg_reg = 0;\r
+  chr_reg = 0;\r
+  Sync();\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x8000,0xFFFF,M216WriteHi);\r
+  SetWriteHandler(0x5000,0x5000,M216Write5000);\r
+  SetReadHandler(0x5000,0x5000,M216Read5000);\r
+}\r
+\r
+\r
+void Mapper216_Init(CartInfo *info)\r
+{\r
+  info->Power=Power;\r
+  GameStateRestore=StateRestore;\r
+  AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
diff --git a/boards/datalatch.c b/boards/datalatch.c
new file mode 100644 (file)
index 0000000..217adb4
--- /dev/null
@@ -0,0 +1,207 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 latche;
+
+//------------------ CPROM ---------------------------
+
+static DECLFW(CPROMWrite)
+{
+  latche=V&3;
+  setchr4(0x1000,latche);
+}
+
+static void CPROMReset(void)
+{
+  setprg32(0x8000,0);
+  setchr8(0);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xffff,CPROMWrite);
+}
+
+static void CPROMRestore(int version)
+{
+  setchr4(0x1000,latche);
+}
+
+void CPROM_Init(CartInfo *info)
+{
+  info->Power=CPROMReset;
+  GameStateRestore=CPROMRestore;
+  AddExState(&latche, 1, 0, "LATC");
+}
+
+//------------------ CNROM ---------------------------
+
+DECLFW(CNROMWrite)
+{
+  latche=V&3;
+  setchr8(latche);
+}
+
+static void CNROMReset(void)
+{
+  setprg16(0x8000,0);
+  setprg16(0xC000,1);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xffff,CNROMWrite);
+}
+
+static void CNROMRestore(int version)
+{
+  setchr8(latche);
+}
+
+void CNROM_Init(CartInfo *info)
+{
+  info->Power=CNROMReset;
+  GameStateRestore=CNROMRestore;
+  AddExState(&latche, 1, 0, "LATC");
+}
+
+//------------------ NROM128 ---------------------------
+
+static void NROM128Reset(void)
+{
+  setprg16(0x8000,0);
+  setprg16(0xC000,0);
+  setchr8(0);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+void NROM128_Init(CartInfo *info)
+{
+  info->Power=NROM128Reset;
+}
+
+//------------------ NROM256 ---------------------------
+
+static void NROM256Reset(void)
+{
+  setprg16(0x8000,0);
+  setprg16(0xC000,1);
+  setchr8(0);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+void NROM256_Init(CartInfo *info)
+{
+  info->Power=NROM256Reset;
+}
+
+//------------------ MHROM ---------------------------
+
+static DECLFW(MHROMWrite)
+{
+  setprg32(0x8000,V>>4);
+  setchr8(V);
+  latche=V;
+}
+
+static void MHROMReset(void)
+{
+  setprg32(0x8000,0);
+  setchr8(0);
+  latche=0;
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void MHROMRestore(int version)
+{
+  setprg32(0x8000,latche);
+  setchr8(latche);
+  SetWriteHandler(0x8000,0xffff,MHROMWrite);
+}
+
+void MHROM_Init(CartInfo *info)
+{ 
+  info->Power=MHROMReset;
+  AddExState(&latche, 1, 0,"LATC");
+  PRGmask32[0]&=1;
+  CHRmask8[0]&=1;
+  GameStateRestore=MHROMRestore;
+}
+
+//------------------ UNROM ---------------------------
+
+static void UNROMRestore(int version)
+{
+  setprg16(0x8000,latche);
+}
+
+static DECLFW(UNROMWrite)
+{
+  setprg16(0x8000,V);
+  latche=V;
+}
+
+static void UNROMReset(void)
+{
+  setprg16(0x8000,0);
+  setprg16(0xc000,~0);
+  setchr8(0);
+  SetWriteHandler(0x8000,0xffff,UNROMWrite);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  latche=0;
+}
+
+void UNROM_Init(CartInfo *info)
+{
+  info->Power=UNROMReset;
+  PRGmask16[0]&=7;
+  AddExState(&latche, 1, 0, "LATC");
+  GameStateRestore=UNROMRestore;
+}
+
+//------------------ GNROM ---------------------------
+
+static void GNROMSync()
+{
+  setchr8(latche&3);
+  setprg32(0x8000,(latche>>4)&3);
+}
+
+static DECLFW(GNROMWrite)
+{
+  latche=V&0x33;
+  GNROMSync();
+}
+
+static void GNROMStateRestore(int version)
+{
+  GNROMSync();
+}
+
+static void GNROMReset(void)
+{
+  latche=0;
+  GNROMSync();
+  SetWriteHandler(0x8000,0xffff,GNROMWrite);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+void GNROM_Init(CartInfo *info)
+{
+  info->Power=GNROMReset;
+  AddExState(&latche, 1, 0, "LATC");
+  GameStateRestore=GNROMStateRestore;
+}
diff --git a/boards/deirom.c b/boards/deirom.c
new file mode 100644 (file)
index 0000000..7a1ed43
--- /dev/null
@@ -0,0 +1,82 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd;
+static uint8 DRegs[8];
+
+static SFORMAT DEI_StateRegs[]=
+{
+  {&cmd, 1, "CMD"},
+  {DRegs, 8, "DREG"},
+  {0}
+};
+
+static void Sync(void)
+{
+  setchr2(0x0000,DRegs[0]);
+  setchr2(0x0800,DRegs[1]);
+  int x;
+  for(x=0;x<4;x++)
+     setchr1(0x1000+(x<<10),DRegs[2+x]);
+  setprg8(0x8000,DRegs[6]);
+  setprg8(0xa000,DRegs[7]);
+}
+
+static void StateRestore(int version)
+{
+  Sync();
+}
+
+static DECLFW(DEIWrite)
+{
+  switch(A&0x8001)
+  {
+    case 0x8000: cmd=V&0x07; break;
+    case 0x8001: if(cmd<=0x05)
+                   V&=0x3F;
+                 else
+                   V&=0x0F;
+                 if(cmd<=0x01) V>>=1;
+                 DRegs[cmd&0x07]=V;
+                 Sync();
+                 break;
+  }
+}
+
+static void DEIPower(void)
+{
+  setprg8(0xc000,0xE);
+  setprg8(0xe000,0xF);
+  cmd=0;
+  memset(DRegs,0,8);
+  Sync();
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xFFFF,DEIWrite);
+}
+
+
+void DEIROM_Init(CartInfo *info)
+{
+  info->Power=DEIPower;
+  GameStateRestore=StateRestore;
+  AddExState(&DEI_StateRegs, ~0, 0, 0);
+}
diff --git a/boards/dream.c b/boards/dream.c
new file mode 100644 (file)
index 0000000..16214f7
--- /dev/null
@@ -0,0 +1,56 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+#include "mapinc.h"\r
+\r
+static uint8 latch;\r
+\r
+static void DoPRG(void)\r
+{\r
+  setprg16(0x8000,latch);\r
+  setprg16(0xC000,8);\r
+}\r
+\r
+static DECLFW(DREAMWrite)\r
+{\r
+  latch=V&7;\r
+  DoPRG();\r
+}\r
+\r
+static void DREAMPower(void)\r
+{\r
+  latch=0;\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x5020,0x5020,DREAMWrite);\r
+  setchr8(0);\r
+  DoPRG();\r
+}\r
+\r
+static void Restore(int version)\r
+{\r
+  DoPRG();\r
+}\r
+\r
+void DreamTech01_Init(CartInfo *info)\r
+{\r
+  GameStateRestore=Restore;\r
+  info->Power=DREAMPower;\r
+  AddExState(&latch, 1, 0, "LATCH");\r
+}\r
index 9b9dcbc..c2c6621 100644 (file)
-/* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-/* Not finished.  Darn evil game... *Mumble*... */
-
-#include "mapinc.h"
-
-static uint8 cmd;
-static uint8 regs[8];
-
-static void DoPRG(void)
-{
- if(cmd&0x40)
- {
-  setprg8(0xC000,regs[4]);
-  setprg8(0xA000,regs[5]);
-  setprg8(0x8000,~1);
-  setprg8(0xE000,~0);
- }
- else
- {
-  setprg8(0x8000,regs[4]);
-  setprg8(0xA000,regs[5]);
-  setprg8(0xC000,~1);
-  setprg8(0xE000,~0);
- }
-}
-
-static void DoCHR(void)
-{
- uint32 base=(cmd&0x80)<<5;
-
- setchr2(0x0000^base,regs[0]);
- setchr2(0x0800^base,regs[2]);
-
- setchr1(0x1000^base,regs[6]);
- setchr1(0x1400^base,regs[1]);
- setchr1(0x1800^base,regs[7]);
- setchr1(0x1c00^base,regs[3]);
-}
-
-static DECLFW(H2288Write)
-{
- //printf("$%04x:$%02x, $%04x\n",A,V,X.PC.W);
- //RAM[0x7FB]=0x60;
- switch(A&0xE001)
- {
-  case 0xa000:setmirror((V&1)^1);break;
-  case 0x8000://  DumpMem("out",0x0000,0xFFFF);
-             cmd=V;DoPRG();DoCHR();
-              X6502_Rebase();break;
-  case 0x8001:regs[cmd&7]=V;
-             if((cmd&7)==4 || (cmd&7)==5) {
-              DoPRG();
-               X6502_Rebase();
-             } else
-              DoCHR();
-             break;
- }
-}
-
-static DECLFR(H2288Read)
-{
- //printf("Rd: $%04x, $%04x\n",A,X.PC.W);
- return((X.DB&0xFE)|(A&(A>>8)));
-}
-
-static void H2288Reset(void)
-{
-  int x;
-
-  SetReadHandler(0x5800,0x5FFF,H2288Read);
-  SetReadHandler(0x8000,0xFFFF,CartBR);
-  SetWriteHandler(0x8000,0xFFFF,H2288Write);
-  for(x=0;x<8;x++) regs[x]=0;
-  cmd=0;
-  DoPRG();
-  DoCHR();
-}
-
-void H2288_Init(void)
-{
-  BoardPower=H2288Reset;
-}
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+#include "mapinc.h"\r
+#include "mmc3.h"\r
+\r
+extern uint8 m114_perm[8];\r
+\r
+static void H2288PW(uint32 A, uint8 V)\r
+{\r
+  if(EXPREGS[0]&0x40)\r
+  {\r
+    uint8 bank=(EXPREGS[0]&5)|((EXPREGS[0]&8)>>2)|((EXPREGS[0]&0x20)>>2);\r
+    if(EXPREGS[0]&2)\r
+      setprg32(0x8000,bank>>1);\r
+    else\r
+    {\r
+      setprg16(0x8000,bank);\r
+      setprg16(0xC000,bank);\r
+    }\r
+  }\r
+  else\r
+    setprg8(A,V&0x3F);\r
+}\r
+\r
+static DECLFW(H2288WriteHi)\r
+{\r
+  switch (A&0x8001)\r
+  {\r
+    case 0x8000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); break;\r
+    case 0x8001: MMC3_CMDWrite(0x8001,V); break;\r
+  }\r
+}\r
+\r
+static DECLFW(H2288WriteLo)\r
+{\r
+  if(A&0x800)\r
+  {\r
+    if(A&1)\r
+      EXPREGS[1]=V;\r
+    else\r
+      EXPREGS[0]=V;\r
+    FixMMC3PRG(MMC3_cmd);\r
+  }\r
+}\r
+\r
+static DECLFR(H2288Read)\r
+{\r
+  int bit;\r
+  bit=(A&1)^1;\r
+  bit&=((A>>8)&1);\r
+  bit^=1;\r
+  return((X.DB&0xFE)|bit);\r
+}\r
+\r
+static void H2288Power(void)\r
+{\r
+  EXPREGS[0]=EXPREGS[1]=0;\r
+  GenMMC3Power();\r
+  SetReadHandler(0x5000,0x5FFF,H2288Read);\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x5000,0x5FFF,H2288WriteLo);\r
+  SetWriteHandler(0x8000,0x8FFF,H2288WriteHi);\r
+}\r
+\r
+void UNLH2288_Init(CartInfo *info)\r
+{\r
+  GenMMC3_Init(info, 256, 256, 0, 0);\r
+  pwrap=H2288PW;\r
+  info->Power=H2288Power;\r
+  AddExState(EXPREGS, 2, 0, "EXPR");\r
+}\r
diff --git a/boards/karaoke.c b/boards/karaoke.c
new file mode 100644 (file)
index 0000000..eccf9c2
--- /dev/null
@@ -0,0 +1,78 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 DReg;
+static SFORMAT StateRegs[]=
+{
+  {&DReg, 1, "DREG"},
+  {0}
+};
+
+static void Sync(void)
+{
+  if(DReg)
+  {
+    if(DReg & 0x10)
+      setprg16(0x8000,(DReg&7));
+    else
+      setprg16(0x8000,(DReg&7)|8);
+  }
+  else
+    setprg16(0x8000,7);
+}
+
+static void StateRestore(int version)
+{
+  Sync();
+}
+
+static DECLFW(M188Write)
+{
+  DReg=V;
+  Sync();
+}
+
+static DECLFR(testr)
+{
+  return(3);
+}
+
+
+static void Power(void)
+{
+  setchr8(0);
+  setprg8(0xc000,0xE);
+  setprg8(0xe000,0xF);
+  DReg = 0;
+  Sync();
+  SetReadHandler(0x6000,0x7FFF,testr);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xFFFF,M188Write);
+}
+
+
+void Mapper188_Init(CartInfo *info)
+{
+  info->Power=Power;
+  GameStateRestore=StateRestore;
+  AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/konami-qtai.c b/boards/konami-qtai.c
new file mode 100644 (file)
index 0000000..ff552e1
--- /dev/null
@@ -0,0 +1,128 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+ * CAI Shogakko no Sansu\r
+ */\r
+\r
+#include "mapinc.h"\r
+\r
+static uint8 *CHRRAM=NULL;\r
+static uint8 SWRAM[4096];\r
+\r
+static uint8 regs[16];\r
+static uint8 WRAM[4096];\r
+static SFORMAT StateRegs[]=\r
+{\r
+  {&regs, 16, "REGS"},\r
+  {WRAM, 4096, "WRAM"},\r
+  {0}\r
+};\r
+\r
+static void Sync(void)\r
+{\r
+  if(regs[5]&0x40)\r
+  {\r
+    setchr4r(0,0x1000,regs[5]&0x3F);\r
+  }\r
+  else\r
+  {\r
+    setchr4r(0x10,0x0000,regs[5]);\r
+    setchr4r(0x10,0x1000,regs[5]^1);\r
+  }\r
+  setprg8r((regs[2]>>6)&1,0x8000,(regs[2]&0x3F));\r
+  setprg8r((regs[3]>>6)&1,0xA000,(regs[3]&0x3F));\r
+  setprg8r((regs[4]>>6)&1,0xC000,(regs[4]&0x3F));\r
+  setprg8r(1,0xE000,~0);\r
+  setmirror((regs[0xA]&3));\r
+}\r
+\r
+static DECLFW(M190Write)\r
+{\r
+// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);\r
+  regs[(A&0x0F00)>>8]=V;\r
+  Sync();\r
+}\r
+\r
+static DECLFR(M190Read)\r
+{\r
+// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);\r
+  return regs[(A&0x0F00)>>8];\r
+}\r
+\r
+static DECLFR(AWRAM)\r
+{\r
+  return(WRAM[A-0x7000]);\r
+}\r
+static DECLFW(BWRAM)\r
+{\r
+  WRAM[A-0x7000]=V;\r
+}\r
+\r
+static DECLFR(ASWRAM)\r
+{\r
+  return(SWRAM[A-0x6000]);\r
+}\r
+static DECLFW(BSWRAM)\r
+{\r
+  SWRAM[A-0x6000]=V;\r
+}\r
+\r
+static void M190Power(void)\r
+{\r
+  setvram8(CHRRAM);\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+  SetWriteHandler(0x8000,0xFFFF,M190Write);\r
+// SetReadHandler(0xDA00,0xDA00,M190Read);\r
+// SetReadHandler(0xDB00,0xDB00,M190Read);\r
+  SetReadHandler(0xDC00,0xDC00,M190Read);\r
+  SetReadHandler(0xDD00,0xDD00,M190Read);\r
+  SetReadHandler(0x7000,0x7FFF,AWRAM);\r
+  SetWriteHandler(0x7000,0x7FFF,BWRAM);\r
+  SetReadHandler(0x6000,0x6FFF,ASWRAM);\r
+  SetWriteHandler(0x6000,0x6FFF,BSWRAM);\r
+  Sync();\r
+}\r
+\r
+static void M190Close(void)\r
+{\r
+  if(CHRRAM)\r
+    FCEU_gfree(CHRRAM);\r
+  CHRRAM=NULL;\r
+}\r
+\r
+static void StateRestore(int version)\r
+{\r
+  Sync();\r
+}\r
+\r
+void Mapper190_Init(CartInfo *info)\r
+{\r
+  info->Power=M190Power;\r
+  info->Close=M190Close;\r
+  if(info->battery)\r
+  {\r
+    info->SaveGame[0]=SWRAM;\r
+    info->SaveGameLen[0]=4096;\r
+  }\r
+  GameStateRestore=StateRestore;\r
+  CHRRAM=(uint8*)FCEU_gmalloc(8192);\r
+  SetupCartCHRMapping(0x10,CHRRAM,8192,1);\r
+  AddExState(CHRRAM, 8192, 0, "CHRRAM");\r
+  AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
index f575159..b0f194e 100644 (file)
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "mapinc.h"
 
-DECLFW(MWrite)
-{
- (GameMemBlock-0x7000)[A]=V;
-}
+static uint8 WRAM[2048];
 
 static void MALEEReset(void)
 {
@@ -31,15 +28,14 @@ static void MALEEReset(void)
   SetReadHandler(0x8000,0xFFFF,CartBR);
   SetReadHandler(0x6000,0x67ff,CartBR);
   SetReadHandler(0x7000,0x77FF,CartBR);
-  SetWriteHandler(0x7000,0x77FF,MWrite);
   setprg2r(1,0x6000,0);
   setprg32(0x8000,0);
   setchr8(0);
 }
 
-void MALEE_Init(void)
+void MALEE_Init(CartInfo *info)
 {
-  AddExState(GameMemBlock, 2048, 0,"RAM");
-  SetupCartPRGMapping(0x10,GameMemBlock,2048,1);
-  BoardPower=MALEEReset;
+  info->Power=MALEEReset;
+  SetupCartPRGMapping(0x10, WRAM, 2048, 1);
+  AddExState(WRAM, 2048, 0,"RAM");
 }
index e6d4c41..7c2b042 100644 (file)
@@ -1,11 +1,12 @@
-#include       "../types.h"
-#include        "../x6502.h"
-#include        "../fce.h"
-#include        "../version.h"
-#include        "../memory.h"
-#include       "../sound.h"
-#include        "../svga.h"
-#include       "../state.h"
-#define UNIFPRIV
-#include        "../unif.h"
-#include       "../cart.h"
+#include "../types.h"
+#include "../x6502.h"
+#include "../fce.h"
+#include "../ppu.h"
+#include "../memory.h"
+#include "../sound.h"
+#include "../state.h"
+#include "../cart.h"
+#include "../cheat.h"
+#include "../unif.h"
+#include "../svga.h"
+#include <string.h>
diff --git a/boards/mmc1.c b/boards/mmc1.c
new file mode 100644 (file)
index 0000000..0eefc59
--- /dev/null
@@ -0,0 +1,426 @@
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 1998 BERO\r
+ *  Copyright (C) 2002 Xodnizel\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
+#include "mapinc.h"\r
+\r
+static void GenMMC1Power(void);\r
+static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);\r
+\r
+static uint8 DRegs[4];\r
+static uint8 Buffer,BufferShift;\r
+\r
+static int mmc1opts;\r
+\r
+static void (*MMC1CHRHook4)(uint32 A, uint8 V);\r
+static void (*MMC1PRGHook16)(uint32 A, uint8 V);\r
+\r
+static uint8 *WRAM=NULL;\r
+static uint8 *CHRRAM=NULL;\r
+static int is155;\r
+\r
+static DECLFW(MBWRAM)\r
+{\r
+  if(!(DRegs[3]&0x10)||is155)\r
+    Page[A>>11][A]=V;     // WRAM is enabled.\r
+}\r
+\r
+static DECLFR(MAWRAM)\r
+{\r
+  if((DRegs[3]&0x10)&&!is155)\r
+    return X.DB;          // WRAM is disabled\r
+  return(Page[A>>11][A]);\r
+}\r
+\r
+static void MMC1CHR(void)\r
+{\r
+  if(mmc1opts&4)\r
+  {\r
+    if(DRegs[0]&0x10)\r
+      setprg8r(0x10,0x6000,(DRegs[1]>>4)&1);\r
+    else\r
+      setprg8r(0x10,0x6000,(DRegs[1]>>3)&1);\r
+  }\r
+  if(MMC1CHRHook4)\r
+  {\r
+    if(DRegs[0]&0x10)\r
+    {\r
+      MMC1CHRHook4(0x0000,DRegs[1]);\r
+      MMC1CHRHook4(0x1000,DRegs[2]);\r
+    }\r
+    else\r
+    {\r
+      MMC1CHRHook4(0x0000,(DRegs[1]&0xFE));\r
+      MMC1CHRHook4(0x1000,DRegs[1]|1);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if(DRegs[0]&0x10)\r
+    {\r
+      setchr4(0x0000,DRegs[1]);\r
+      setchr4(0x1000,DRegs[2]);\r
+    }\r
+    else\r
+      setchr8(DRegs[1]>>1);\r
+  }\r
+}\r
+\r
+static void MMC1PRG(void)\r
+{\r
+  uint8 offs=DRegs[1]&0x10;\r
+\r
+  if(MMC1PRGHook16)\r
+  {\r
+    switch(DRegs[0]&0xC)\r
+    {\r
+      case 0xC: MMC1PRGHook16(0x8000,(DRegs[3]+offs));\r
+                MMC1PRGHook16(0xC000,0xF+offs);\r
+                break;\r
+      case 0x8: MMC1PRGHook16(0xC000,(DRegs[3]+offs));\r
+                MMC1PRGHook16(0x8000,offs);\r
+                break;\r
+      case 0x0:\r
+      case 0x4:\r
+                MMC1PRGHook16(0x8000,((DRegs[3]&~1)+offs));\r
+                MMC1PRGHook16(0xc000,((DRegs[3]&~1)+offs+1));\r
+                break;\r
+    }\r
+  }\r
+  else switch(DRegs[0]&0xC)\r
+  {\r
+    case 0xC: setprg16(0x8000,(DRegs[3]+offs));\r
+              setprg16(0xC000,0xF+offs);\r
+              break;\r
+    case 0x8: setprg16(0xC000,(DRegs[3]+offs));\r
+              setprg16(0x8000,offs);\r
+              break;\r
+    case 0x0:\r
+    case 0x4:\r
+              setprg16(0x8000,((DRegs[3]&~1)+offs));\r
+              setprg16(0xc000,((DRegs[3]&~1)+offs+1));\r
+              break;\r
+  }\r
+}\r
+\r
+static void MMC1MIRROR(void)\r
+{\r
+  switch(DRegs[0]&3)\r
+  {\r
+    case 2: setmirror(MI_V); break;\r
+    case 3: setmirror(MI_H); break;\r
+    case 0: setmirror(MI_0); break;\r
+    case 1: setmirror(MI_1); break;\r
+  }\r
+}\r
+\r
+\r
+static uint64 lreset;\r
+static DECLFW(MMC1_write)\r
+{\r
+  int n=(A>>13)-4;\r
+  //FCEU_DispMessage("%016x",timestampbase+timestamp);\r
+  //printf("$%04x:$%02x, $%04x\n",A,V,X.PC);\r
+  //DumpMem("out",0xe000,0xffff);\r
+\r
+  /* The MMC1 is busy so ignore the write. */\r
+  /* As of version FCE Ultra 0.81, the timestamp is only\r
+     increased before each instruction is executed(in other words\r
+     precision isn't that great), but this should still work to\r
+     deal with 2 writes in a row from a single RMW instruction. */\r
+  if((timestampbase+timestamp)<(lreset+2)) return;\r
+\r
+  if(V&0x80)\r
+  {\r
+    DRegs[0]|=0xC;\r
+    BufferShift=Buffer=0;\r
+    MMC1PRG();\r
+    lreset=timestampbase+timestamp;\r
+    return;\r
+  }\r
+  Buffer|=(V&1)<<(BufferShift++);\r
+  if(BufferShift==5)\r
+  {\r
+    DRegs[n] = Buffer;\r
+    BufferShift = Buffer = 0;\r
+    switch(n)\r
+    {\r
+      case 0: MMC1MIRROR(); MMC1CHR(); MMC1PRG(); break;\r
+      case 1: MMC1CHR(); MMC1PRG(); break;\r
+      case 2: MMC1CHR(); break;\r
+      case 3: MMC1PRG(); break;\r
+    }\r
+  }\r
+}\r
+\r
+static void MMC1_Restore(int version)\r
+{\r
+  MMC1MIRROR();\r
+  MMC1CHR();\r
+  MMC1PRG();\r
+  //lreset=0;        /* timestamp(base) is not stored in save states. */ // it is now!\r
+}\r
+\r
+static void MMC1CMReset(void)\r
+{\r
+  int i;\r
+  for(i=0;i<4;i++)\r
+     DRegs[i]=0;\r
+  Buffer = BufferShift = 0;\r
+  DRegs[0]=0x1F;\r
+  DRegs[1]=0;\r
+  DRegs[2]=0;                  // Should this be something other than 0?\r
+  DRegs[3]=0;\r
+\r
+  MMC1MIRROR();\r
+  MMC1CHR();\r
+  MMC1PRG();\r
+}\r
+\r
+static int DetectMMC1WRAMSize(uint32 crc32)\r
+{\r
+  switch(crc32)\r
+  {\r
+    case 0xc6182024:       /* Romance of the 3 Kingdoms */\r
+    case 0x2225c20f:       /* Genghis Khan */\r
+    case 0x4642dda6:       /* Nobunaga's Ambition */\r
+    case 0x29449ba9:       /* ""        "" (J) */\r
+    case 0x2b11e0b0:       /* ""        "" (J) */\r
+         FCEU_printf(" >8KB external WRAM present.  Use UNIF if you hack the ROM image.\n");\r
+         return(16);\r
+         break;\r
+    default:return(8);\r
+  }\r
+}\r
+\r
+static uint32 NWCIRQCount;\r
+static uint8 NWCRec;\r
+#define NWCDIP 0xE\r
+\r
+static void FP_FASTAPASS(1) NWCIRQHook(int a)\r
+{\r
+  if(!(NWCRec&0x10))\r
+  {\r
+    NWCIRQCount+=a;\r
+    if((NWCIRQCount|(NWCDIP<<25))>=0x3e000000)\r
+    {\r
+      NWCIRQCount=0;\r
+      X6502_IRQBegin(FCEU_IQEXT);\r
+    }\r
+  }\r
+}\r
+\r
+static void NWCCHRHook(uint32 A, uint8 V)\r
+{\r
+  if((V&0x10)) // && !(NWCRec&0x10))\r
+  {\r
+    NWCIRQCount=0;\r
+    X6502_IRQEnd(FCEU_IQEXT);\r
+  }\r
+  NWCRec=V;\r
+  if(V&0x08)\r
+    MMC1PRG();\r
+  else\r
+    setprg32(0x8000,(V>>1)&3);\r
+}\r
+\r
+static void NWCPRGHook(uint32 A, uint8 V)\r
+{\r
+  if(NWCRec&0x8)\r
+    setprg16(A,8|(V&0x7));\r
+  else\r
+    setprg32(0x8000,(NWCRec>>1)&3);\r
+}\r
+\r
+static void NWCPower(void)\r
+{\r
+  GenMMC1Power();\r
+  setchr8r(0,0);\r
+}\r
+\r
+void Mapper105_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 256, 8, 0);\r
+  MMC1CHRHook4=NWCCHRHook;\r
+  MMC1PRGHook16=NWCPRGHook;\r
+  MapIRQHook=NWCIRQHook;\r
+  info->Power=NWCPower;\r
+}\r
+\r
+static void GenMMC1Power(void)\r
+{\r
+  lreset=0;\r
+  if(mmc1opts&1)\r
+  {\r
+    FCEU_CheatAddRAM(8,0x6000,WRAM);\r
+    if(mmc1opts&4)\r
+      FCEU_dwmemset(WRAM,0,8192)\r
+    else if(!(mmc1opts&2))\r
+      FCEU_dwmemset(WRAM,0,8192);\r
+  }\r
+  SetWriteHandler(0x8000,0xFFFF,MMC1_write);\r
+  SetReadHandler(0x8000,0xFFFF,CartBR);\r
+\r
+  if(mmc1opts&1)\r
+  {\r
+    SetReadHandler(0x6000,0x7FFF,MAWRAM);\r
+    SetWriteHandler(0x6000,0x7FFF,MBWRAM);\r
+    setprg8r(0x10,0x6000,0);\r
+  }\r
+\r
+  MMC1CMReset();\r
+}\r
+\r
+static void GenMMC1Close(void)\r
+{\r
+  if(CHRRAM)\r
+    FCEU_gfree(CHRRAM);\r
+  if(WRAM)\r
+    FCEU_gfree(WRAM);\r
+  CHRRAM=WRAM=NULL;\r
+}\r
+\r
+static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)\r
+{\r
+  is155=0;\r
+\r
+  info->Close=GenMMC1Close;\r
+  MMC1PRGHook16=MMC1CHRHook4=0;\r
+  mmc1opts=0;\r
+  PRGmask16[0]&=(prg>>14)-1;\r
+  CHRmask4[0]&=(chr>>12)-1;\r
+  CHRmask8[0]&=(chr>>13)-1;\r
+\r
+  if(wram)\r
+  {\r
+    WRAM=(uint8*)FCEU_gmalloc(wram*1024);\r
+    mmc1opts|=1;\r
+    if(wram>8) mmc1opts|=4;\r
+    SetupCartPRGMapping(0x10,WRAM,wram*1024,1);\r
+    AddExState(WRAM, wram*1024, 0, "WRAM");\r
+    if(battery)\r
+    {\r
+      mmc1opts|=2;\r
+      info->SaveGame[0]=WRAM+((mmc1opts&4)?8192:0);\r
+      info->SaveGameLen[0]=8192;\r
+    }\r
+  }\r
+  if(!chr)\r
+  {\r
+    CHRRAM=(uint8*)FCEU_gmalloc(8192);\r
+    SetupCartCHRMapping(0, CHRRAM, 8192, 1);\r
+    AddExState(CHRRAM, 8192, 0, "CHRR");\r
+  }\r
+  AddExState(DRegs, 4, 0, "DREG");\r
+\r
+  info->Power=GenMMC1Power;\r
+  GameStateRestore=MMC1_Restore;\r
+  AddExState(&lreset, 8, 1, "LRST");\r
+  AddExState(&Buffer, 1, 1, "BFFR");\r
+  AddExState(&BufferShift, 1, 1, "BFRS");\r
+}\r
+\r
+void Mapper1_Init(CartInfo *info)\r
+{\r
+  int ws=DetectMMC1WRAMSize(info->CRC32);\r
+  GenMMC1Init(info, 512, 256, ws, info->battery);\r
+}\r
+\r
+/* Same as mapper 1, without respect for WRAM enable bit. */\r
+void Mapper155_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info,512,256,8,info->battery);\r
+  is155=1;\r
+}\r
+\r
+void SAROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 128, 64, 8, info->battery);\r
+}\r
+\r
+void SBROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 128, 64, 0, 0);\r
+}\r
+\r
+void SCROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 128, 128, 0, 0);\r
+}\r
+\r
+void SEROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 32, 64, 0, 0);\r
+}\r
+\r
+void SGROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 0, 0, 0);\r
+}\r
+\r
+void SKROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 64, 8, info->battery);\r
+}\r
+\r
+void SLROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 128, 0, 0);\r
+}\r
+\r
+void SL1ROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 128, 128, 0, 0);\r
+}\r
+\r
+/* Begin unknown - may be wrong - perhaps they use different MMC1s from the\r
+   similarly functioning boards?\r
+*/\r
+\r
+void SL2ROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 256, 0, 0);\r
+}\r
+\r
+void SFROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 256, 0, 0);\r
+}\r
+\r
+void SHROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 256, 0, 0);\r
+}\r
+\r
+/* End unknown  */\r
+/*              */\r
+/*              */\r
+\r
+void SNROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 0, 8, info->battery);\r
+}\r
+\r
+void SOROM_Init(CartInfo *info)\r
+{\r
+  GenMMC1Init(info, 256, 0, 16, info->battery);\r
+}\r
+\r
+\r
diff --git a/boards/mmc3.c b/boards/mmc3.c
new file mode 100644 (file)
index 0000000..14ce5cb
--- /dev/null
@@ -0,0 +1,1408 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 1998 BERO
+ *  Copyright (C) 2003 Xodnizel
+ *  Mapper 12 code Copyright (C) 2003 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/*  Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118,
+    119,148,165,205,214,215,245,249,250,254
+*/
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+uint8 MMC3_cmd=0;
+uint8 *WRAM=0;
+uint8 *CHRRAM=0;
+uint32 CHRRAMSize=0;
+uint8 EXPREGS[8]={0,0,0,0,0,0,0,0};    /* For bootleg games, mostly. */
+
+static uint8 A000B=0,A001B=0;
+static uint8 DRegBuf[8]={0,0,0,0,0,0,0,0};
+
+#undef IRQCount
+#undef IRQLatch
+#undef IRQa
+uint8 IRQCount=0,IRQLatch=0,IRQa=0;
+uint8 IRQReload=0;
+
+static SFORMAT MMC3_StateRegs[]=
+{
+ {DRegBuf, 8, "REGS"},
+ {&MMC3_cmd, 1, "CMD"},
+ {&A000B, 1, "A000"},
+ {&A001B, 1, "A001"},
+ {&IRQReload, 1, "IRQR"},
+ {&IRQCount, 1, "IRQC"},
+ {&IRQLatch, 1, "IRQL"},
+ {&IRQa, 1, "IRQA"},
+ {0}
+};
+
+static int mmc3opts=0;
+static int wrams=0;
+
+void (*pwrap)(uint32 A, uint8 V);
+void (*cwrap)(uint32 A, uint8 V);
+void (*mwrap)(uint8 V);
+
+void GenMMC3Power(void);
+void FixMMC3PRG(int V);
+void FixMMC3CHR(int V);
+
+void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
+
+// ----------------------------------------------------------------------
+// ------------------------- Generic MM3 Code ---------------------------
+// ----------------------------------------------------------------------
+
+void FixMMC3PRG(int V)
+{
+ if(V&0x40)
+ {
+  pwrap(0xC000,DRegBuf[6]);
+  pwrap(0x8000,~1);
+ }
+ else
+ {
+  pwrap(0x8000,DRegBuf[6]);
+  pwrap(0xC000,~1);
+ }
+ pwrap(0xA000,DRegBuf[7]);
+ pwrap(0xE000,~0);
+}
+
+void FixMMC3CHR(int V)
+{
+ int cbase=(V&0x80)<<5;
+
+ cwrap((cbase^0x000),DRegBuf[0]&(~1));
+ cwrap((cbase^0x400),DRegBuf[0]|1);
+ cwrap((cbase^0x800),DRegBuf[1]&(~1));
+ cwrap((cbase^0xC00),DRegBuf[1]|1);
+
+ cwrap(cbase^0x1000,DRegBuf[2]);
+ cwrap(cbase^0x1400,DRegBuf[3]);
+ cwrap(cbase^0x1800,DRegBuf[4]);
+ cwrap(cbase^0x1c00,DRegBuf[5]);
+}
+
+void MMC3RegReset(void)
+{
+ IRQCount=IRQLatch=IRQa=MMC3_cmd=0;
+
+ DRegBuf[0]=0;
+ DRegBuf[1]=2;
+ DRegBuf[2]=4;
+ DRegBuf[3]=5;
+ DRegBuf[4]=6;
+ DRegBuf[5]=7;
+ DRegBuf[6]=0;
+ DRegBuf[7]=1;
+
+ FixMMC3PRG(0);
+ FixMMC3CHR(0);
+}
+
+DECLFW(MMC3_CMDWrite)
+{
+ switch(A&0xE001)
+ {
+  case 0x8000:
+       if((V&0x40) != (MMC3_cmd&0x40))
+          FixMMC3PRG(V);
+       if((V&0x80) != (MMC3_cmd&0x80))
+          FixMMC3CHR(V);
+       MMC3_cmd = V;
+       break;
+  case 0x8001:
+       {
+        int cbase=(MMC3_cmd&0x80)<<5;
+        DRegBuf[MMC3_cmd&0x7]=V;
+        switch(MMC3_cmd&0x07)
+        {
+         case 0: cwrap((cbase^0x000),V&(~1));
+                 cwrap((cbase^0x400),V|1);
+                 break;
+         case 1: cwrap((cbase^0x800),V&(~1));
+                 cwrap((cbase^0xC00),V|1);
+                 break;
+         case 2: cwrap(cbase^0x1000,V);
+                 break;
+         case 3: cwrap(cbase^0x1400,V);
+                 break;
+         case 4: cwrap(cbase^0x1800,V);
+                 break;
+         case 5: cwrap(cbase^0x1C00,V);
+                 break;
+         case 6:
+                 if(MMC3_cmd&0x40)
+                    pwrap(0xC000,V);
+                 else
+                    pwrap(0x8000,V);
+                 break;
+         case 7:
+                 pwrap(0xA000,V);
+                 break;
+        }
+       }
+       break;
+  case 0xA000:
+       if(mwrap) mwrap(V&1);
+       break;
+  case 0xA001:
+       A001B=V;
+       break;
+ }
+}
+
+DECLFW(MMC3_IRQWrite)
+{
+ switch(A&0xE001)
+ {
+  case 0xC000:IRQLatch=V;break;
+  case 0xC001:IRQReload=1;break;
+  case 0xE000:X6502_IRQEnd(FCEU_IQEXT);IRQa=0;break;
+  case 0xE001:IRQa=1;break;
+ }
+}
+
+static void ClockMMC3Counter(void)
+{
+ int count = IRQCount;
+ if(!count || IRQReload)
+ {
+    IRQCount = IRQLatch;
+    IRQReload = 0;
+ }
+ else
+    IRQCount--;
+ if(count && !IRQCount)
+ {
+    if(IRQa)
+    {
+       X6502_IRQBegin(FCEU_IQEXT);
+    }
+ }
+}
+
+static void MMC3_hb(void)
+{
+ ClockMMC3Counter();
+}
+
+static void MMC3_hb_KickMasterHack(void)
+{
+ if(scanline==238) ClockMMC3Counter();
+ ClockMMC3Counter();
+}
+
+static void MMC3_hb_PALStarWarsHack(void)
+{
+ if(scanline==240) ClockMMC3Counter();
+ ClockMMC3Counter();
+}
+
+static void genmmc3restore(int version)
+{
+ if(mwrap) mwrap(A000B&1);
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void GENCWRAP(uint32 A, uint8 V)
+{
+ setchr1(A,V);
+}
+
+static void GENPWRAP(uint32 A, uint8 V)
+{
+ setprg8(A,V&0x3F);
+}
+
+static void GENMWRAP(uint8 V)
+{
+ A000B=V;
+ setmirror(V^1);
+}
+
+static void GENNOMWRAP(uint8 V)
+{
+ A000B=V;
+}
+
+static DECLFW(MBWRAM)
+{
+  WRAM[A-0x6000]=V;
+}
+
+static DECLFR(MAWRAM)
+{
+ return(WRAM[A-0x6000]);
+}
+
+static DECLFW(MBWRAMMMC6)
+{
+ WRAM[A&0x3ff]=V;
+}
+
+static DECLFR(MAWRAMMMC6)
+{
+ return(WRAM[A&0x3ff]);
+}
+
+void GenMMC3Power(void)
+{
+ SetWriteHandler(0x8000,0xBFFF,MMC3_CMDWrite);
+ SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ A001B=A000B=0;
+ setmirror(1);
+ if(mmc3opts&1)
+ {
+  if(wrams==1024)
+  {
+   FCEU_CheatAddRAM(1,0x7000,WRAM);
+   SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6);
+   SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6);
+  }
+  else
+  {
+   FCEU_CheatAddRAM(wrams>>10,0x6000,WRAM);
+   SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM);
+   SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM);
+  }
+  if(!(mmc3opts&2))
+     FCEU_dwmemset(WRAM,0,wrams);
+ }
+ MMC3RegReset();
+ if(CHRRAM)
+  FCEU_dwmemset(CHRRAM,0,CHRRAMSize);
+}
+
+static void GenMMC3Close(void)
+{
+ if(CHRRAM)
+    FCEU_gfree(CHRRAM);
+ if(WRAM)
+    FCEU_gfree(WRAM);
+ CHRRAM=WRAM=NULL;
+}
+
+void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery)
+{
+pwrap=GENPWRAP;
+ cwrap=GENCWRAP;
+ mwrap=GENMWRAP;
+
+ wrams=wram<<10;
+
+ PRGmask8[0]&=(prg>>13)-1;
+ CHRmask1[0]&=(chr>>10)-1;
+ CHRmask2[0]&=(chr>>11)-1;
+
+ if(wram)
+ {
+  mmc3opts|=1;
+  WRAM=(uint8*)FCEU_gmalloc(wrams);
+  AddExState(WRAM, wrams, 0, "WRAM");
+ }
+
+ if(battery)
+ {
+  mmc3opts|=2;
+  info->SaveGame[0]=WRAM;
+  info->SaveGameLen[0]=wrams;
+ }
+
+ if(!chr)
+ {
+  CHRRAM=(uint8*)FCEU_gmalloc(8192);
+  CHRRAMSize=8192;
+  SetupCartCHRMapping(0, CHRRAM, 8192, 1);
+  AddExState(CHRRAM, 8192, 0, "CHRR");
+ }
+
+ AddExState(MMC3_StateRegs, ~0, 0, 0);
+
+ info->Power=GenMMC3Power;
+ info->Reset=MMC3RegReset;
+ info->Close=GenMMC3Close;
+
+ if(info->CRC32 == 0x5104833e)        // Kick Master
+  GameHBIRQHook = MMC3_hb_KickMasterHack;
+ else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93
+  GameHBIRQHook = MMC3_hb_KickMasterHack;
+ else if(info->CRC32 == 0xfcd772eb)    // PAL Star Wars, similar problem as Kick Master.
+  GameHBIRQHook = MMC3_hb_PALStarWarsHack;
+ else
+  GameHBIRQHook=MMC3_hb;
+ GameStateRestore=genmmc3restore;
+}
+
+// ----------------------------------------------------------------------
+// -------------------------- MMC3 Based Code ---------------------------
+// ----------------------------------------------------------------------
+
+// ---------------------------- Mapper 4 --------------------------------
+
+static int hackm4=0;/* For Karnov, maybe others.  BLAH.  Stupid iNES format.*/
+
+static void M4Power(void)
+{
+ GenMMC3Power();
+ A000B=(hackm4^1)&1;
+ setmirror(hackm4);
+}
+
+void Mapper4_Init(CartInfo *info)
+{
+ int ws=8;
+
+ if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84))
+ {
+  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");
+  ws=0;
+ }
+ GenMMC3_Init(info,512,256,ws,info->battery);
+ info->Power=M4Power;
+ hackm4=info->mirror;
+}
+
+// ---------------------------- Mapper 12 -------------------------------
+
+static void M12CW(uint32 A, uint8 V)
+{
+ setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V);
+}
+
+static DECLFW(M12Write)
+{
+ EXPREGS[0]=V&0x01;
+ EXPREGS[1]=(V&0x10)>>4;
+}
+
+static void M12Power(void)
+{
+ EXPREGS[0]=EXPREGS[1]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x4100,0x5FFF,M12Write);
+}
+
+void Mapper12_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M12CW;
+ info->Power=M12Power;
+ AddExState(EXPREGS, 2, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 44 -------------------------------
+
+static void M44PW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ if(EXPREGS[0]>=6) NV&=0x1F;
+ else NV&=0x0F;
+ NV|=EXPREGS[0]<<4;
+ setprg8(A,NV);
+}
+
+static void M44CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ if(EXPREGS[0]<6) NV&=0x7F;
+ NV|=EXPREGS[0]<<7;
+ setchr1(A,NV);
+}
+
+static DECLFW(M44Write)
+{
+ if(A&1)
+ {
+  EXPREGS[0]=V&7;
+  FixMMC3PRG(MMC3_cmd);
+  FixMMC3CHR(MMC3_cmd);
+ }
+ else
+  MMC3_CMDWrite(A,V);
+}
+
+static void M44Power(void)
+{
+ EXPREGS[0]=0;
+ GenMMC3Power();
+ SetWriteHandler(0xA000,0xBFFF,M44Write);
+}
+
+void Mapper44_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M44CW;
+ pwrap=M44PW;
+ info->Power=M44Power;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 45 -------------------------------
+
+static void M45CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ if(EXPREGS[2]&8)
+    NV&=(1<<((EXPREGS[2]&7)+1))-1;
+ else
+    NV&=0;
+ NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);
+                    // &0x10(not 0xf0) is valid given the original
+                    // description of mapper 45 by kevtris,
+                    // but this fixes Super 8 in 1.
+ setchr1(A,NV);
+}
+
+static void M45PW(uint32 A, uint8 V)
+{
+ V&=(EXPREGS[3]&0x3F)^0x3F;
+ V|=EXPREGS[1];
+ setprg8(A,V);
+}
+
+static DECLFW(M45Write)
+{
+ if(EXPREGS[3]&0x40)
+ {
+  WRAM[A-0x6000]=V;
+  return;
+ }
+ EXPREGS[EXPREGS[4]]=V;
+ EXPREGS[4]=(EXPREGS[4]+1)&3;
+// FCEU_printf("write 0=%04x 1=%04x 2=%04x 3=%04x (%04x:%04x)\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3],A,V);
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M45Reset(void)
+{
+ FCEU_dwmemset(EXPREGS,0,5);
+ MMC3RegReset();
+}
+
+static void M45Power(void)
+{
+ M45Reset();
+ GenMMC3Power();
+ SetWriteHandler(0x6000,0x7FFF,M45Write);
+}
+
+void Mapper45_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M45CW;
+ pwrap=M45PW;
+ info->Reset=M45Reset;
+ info->Power=M45Power;
+ AddExState(EXPREGS, 5, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 47 -------------------------------
+
+static void M47PW(uint32 A, uint8 V)
+{
+ V&=0xF;
+ V|=EXPREGS[0]<<4;
+ setprg8(A,V);
+}
+
+static void M47CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ NV&=0x7F;
+ NV|=EXPREGS[0]<<7;
+ setchr1(A,NV);
+}
+
+static DECLFW(M47Write)
+{
+ EXPREGS[0]=V&1;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M47Power(void)
+{
+ EXPREGS[0]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x6000,0x7FFF,M47Write);
+ SetReadHandler(0x6000,0x7FFF,0);
+}
+
+void Mapper47_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ pwrap=M47PW;
+ cwrap=M47CW;
+ info->Power=M47Power;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 49 -------------------------------
+
+static void M49PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&1)
+ {
+  V&=0xF;
+  V|=(EXPREGS[0]&0xC0)>>2;
+  setprg8(A,V);
+ }
+ else
+  setprg32(0x8000,(EXPREGS[0]>>4)&3);
+}
+
+static void M49CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ NV&=0x7F;
+ NV|=(EXPREGS[0]&0xC0)<<1;
+ setchr1(A,NV);
+}
+
+static DECLFW(M49Write)
+{
+ if(A001B&0x80)
+ {
+  EXPREGS[0]=V;
+  FixMMC3PRG(MMC3_cmd);
+  FixMMC3CHR(MMC3_cmd);
+ }
+}
+
+static void M49Reset(void)
+{
+ EXPREGS[0]=0;
+ MMC3RegReset();
+}
+
+static void M49Power(void)
+{
+ M49Reset();
+ GenMMC3Power();
+ SetWriteHandler(0x6000,0x7FFF,M49Write);
+ SetReadHandler(0x6000,0x7FFF,0);
+}
+
+void Mapper49_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 0, 0);
+ cwrap=M49CW;
+ pwrap=M49PW;
+ info->Reset=M49Reset;
+ info->Power=M49Power;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 52 -------------------------------
+
+static void M52PW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ NV&=0x1F^((EXPREGS[0]&8)<<1);
+ NV|=((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4;
+ setprg8(A,NV);
+}
+
+static void M52CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ NV&=0xFF^((EXPREGS[0]&0x40)<<1);
+ NV|=(((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7;
+ setchr1(A,NV);
+}
+
+static DECLFW(M52Write)
+{
+ if(EXPREGS[1])
+ {
+  WRAM[A-0x6000]=V;
+  return;
+ }
+ EXPREGS[1]=1;
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M52Reset(void)
+{
+ EXPREGS[0]=EXPREGS[1]=0;
+ MMC3RegReset();
+}
+
+static void M52Power(void)
+{
+ M52Reset();
+ GenMMC3Power();
+ SetWriteHandler(0x6000,0x7FFF,M52Write);
+}
+
+void Mapper52_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M52CW;
+ pwrap=M52PW;
+ info->Reset=M52Reset;
+ info->Power=M52Power;
+ AddExState(EXPREGS, 2, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 74 -------------------------------
+
+static void M74CW(uint32 A, uint8 V)
+{
+//  FCEU_printf("%04x:%04x\n",A,V);
+//  if((V==0)||(V==1)) //Dai-2-Ji - Super Robot Taisen (As).nes
+  if((V==0)||(V==1)||(V==2)||(V==3)) //Ying Lie Qun Xia Zhuan (Chinese).nes, 4096 CHR RAM
+//  if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes
+//  if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese).nes, 4096 CHR RAM
+     setchr1r(0x10,A,V);
+  else
+     setchr1r(0x0,A,V);
+}
+
+void Mapper74_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M74CW;
+// CHRRAMSize=2048;
+ CHRRAMSize=4096;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+}
+
+// ---------------------------- Mapper 114 ------------------------------
+
+static uint8 cmdin;
+uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
+
+static void M114PWRAP(uint32 A, uint8 V)
+{
+  if(EXPREGS[0]&0x80)
+  {
+    setprg16(0x8000,EXPREGS[0]&0xF);
+    setprg16(0xC000,EXPREGS[0]&0xF);
+  }
+  else
+    setprg8(A,V&0x3F);
+}
+
+static DECLFW(M114Write)
+{
+ if(A==0xE003)
+ {
+  IRQa=1;
+  IRQCount=V;
+ }
+ else if(A==0xE002)
+ {
+  IRQa=0;
+  X6502_IRQEnd(FCEU_IQEXT);
+ }
+ else switch(A&0xE000)
+ {
+  case 0x8000: setmirror((V&1)^1); break;
+  case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break;
+  case 0xC000: if(!cmdin) break;
+               MMC3_CMDWrite(0x8001,V);
+               cmdin=0;
+               break;
+ }
+}
+
+static DECLFW(M114ExWrite)
+{
+  if(A<=0x7FFF)
+  {
+   EXPREGS[0]=V;
+   FixMMC3PRG(MMC3_cmd);
+  }
+}
+
+static void M114Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xFFFF,M114Write);
+ SetWriteHandler(0x5000,0x7FFF,M114ExWrite);
+}
+
+static void M114Reset(void)
+{
+ EXPREGS[0]=0;
+ MMC3RegReset();
+}
+
+void Mapper114_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ pwrap=M114PWRAP;
+ info->Power=M114Power;
+ info->Reset=M114Reset;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+ AddExState(&cmdin, 1, 0, "CMDIN");
+}
+
+// ---------------------------- Mapper 115 ------------------------------
+
+static void M115PW(uint32 A, uint8 V)
+{
+ setprg8(A,V);
+ if(EXPREGS[0]&0x80)
+    setprg16(0x8000,EXPREGS[0]&7);
+}
+
+static void M115CW(uint32 A, uint8 V)
+{
+ setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8));
+}
+
+static DECLFW(M115Write)
+{
+ if(A==0x6000)
+    EXPREGS[0]=V;
+ else if(A==0x6001)
+    EXPREGS[1]=V;
+ FixMMC3PRG(MMC3_cmd);
+}
+
+static void M115Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x4100,0x7FFF,M115Write);
+ SetReadHandler(0x4100,0x7FFF,0);
+}
+
+void Mapper115_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 512, 0, 0);
+ cwrap=M115CW;
+ pwrap=M115PW;
+ info->Power=M115Power;
+ AddExState(EXPREGS, 2, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 116 ------------------------------
+
+static void M116CW(uint32 A, uint8 V)
+{
+ setchr1(A,V|((EXPREGS[0]&0x4)<<6));
+}
+
+static DECLFW(M116Write)
+{
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M116Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x4100,0x4100,M116Write);
+}
+
+void Mapper116_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 512, 0, 0);
+ cwrap=M116CW;
+ info->Power=M116Power;
+ AddExState(EXPREGS, 4, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 118 ------------------------------
+
+static uint8 PPUCHRBus;
+static uint8 TKSMIR[8];
+
+static void FP_FASTAPASS(1) TKSPPU(uint32 A)
+{
+ A&=0x1FFF;
+ A>>=10;
+ PPUCHRBus=A;
+ setmirror(MI_0+TKSMIR[A]);
+}
+
+static void TKSWRAP(uint32 A, uint8 V)
+{
+ TKSMIR[A>>10]=V>>7;
+ setchr1(A,V&0x7F);
+ if(PPUCHRBus==(A>>10))
+    setmirror(MI_0+(V>>7));
+}
+
+void Mapper118_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=TKSWRAP;
+ mwrap=GENNOMWRAP;
+ PPU_hook=TKSPPU;
+ AddExState(&PPUCHRBus, 1, 0, "PPUC");
+}
+
+// ---------------------------- Mapper 119 ------------------------------
+
+static void TQWRAP(uint32 A, uint8 V)
+{
+ setchr1r((V&0x40)>>2,A,V&0x3F);
+}
+
+void Mapper119_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 64, 0, 0);
+ cwrap=TQWRAP;
+ CHRRAMSize=8192;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+}
+
+// ---------------------------- Mapper 191 ------------------------------
+
+static void M191CW(uint32 A, uint8 V)
+{
+  setchr1r((V&0x80)>>3,A,V);
+}
+
+void Mapper191_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 8, info->battery);
+ cwrap=M191CW;
+ CHRRAMSize=2048;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+}
+
+// ---------------------------- Mapper 165 ------------------------------
+
+static void M165CW(uint32 A, uint8 V)
+{
+ if(V==0)
+    setchr4r(0x10,A,0);
+ else
+    setchr4(A,V>>2);
+}
+
+static void M165PPUFD(void)
+{
+ if(EXPREGS[0]==0xFD)
+ {
+  M165CW(0x0000,DRegBuf[0]);
+  M165CW(0x1000,DRegBuf[2]);
+ }
+}
+
+static void M165PPUFE(void)
+{
+ if(EXPREGS[0]==0xFE)
+ {
+  M165CW(0x0000,DRegBuf[1]);
+  M165CW(0x1000,DRegBuf[4]);
+ }
+}
+
+static void M165CWM(uint32 A, uint8 V)
+{
+ if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2)) M165PPUFD();
+ if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4)) M165PPUFE();
+}
+
+static void FP_FASTAPASS(1) M165PPU(uint32 A)
+{
+ if((A&0x1FF0)==0x1FD0)
+ {
+  EXPREGS[0]=0xFD;
+  M165PPUFD();
+ } else if((A&0x1FF0)==0x1FE0)
+ {
+  EXPREGS[0]=0xFE;
+  M165PPUFE();
+ }
+}
+
+static void M165Power(void)
+{
+ EXPREGS[0]=0xFD;
+ GenMMC3Power();
+}
+
+void Mapper165_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 128, 8, info->battery);
+ cwrap=M165CWM;
+ PPU_hook=M165PPU;
+ info->Power=M165Power;
+ CHRRAMSize = 4096;
+ CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+ AddExState(EXPREGS, 4, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 182 ------------------------------
+// òàáëèöà ïåðìóòàöè àíàëîãè÷íà 114 ìàïïåðó, ðåãèñòðû ìàïïåðà ãîðàçäî ñëîæíåå,
+// ÷åì èñïîëüçóþòñÿ çäåñü, õîòÿ âñå ïðåêðàñíî ðàáîòàåò.
+
+//static uint8 m182_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4};
+static DECLFW(M182Write)
+{
+ switch(A&0xF003)
+ {
+  case 0x8001: setmirror((V&1)^1); break;
+  case 0xA000: MMC3_CMDWrite(0x8000,m114_perm[V&7]); break;
+  case 0xC000: MMC3_CMDWrite(0x8001,V); break;
+  case 0xE003: IRQCount=V; IRQa=1; X6502_IRQEnd(FCEU_IQEXT); break;
+ }
+}
+
+static void M182Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xFFFF,M182Write);
+}
+
+void Mapper182_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ info->Power=M182Power;
+}
+
+// ---------------------------- Mapper 205 ------------------------------
+
+static void M205PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&2)
+    setprg8(A,(V&0x0f)|((EXPREGS[0]&3)<<4));
+ else
+    setprg8(A,(V&0x1f)|((EXPREGS[0]&3)<<4));
+}
+
+static void M205CW(uint32 A, uint8 V)
+{
+ setchr1(A,V|((EXPREGS[0]&3)*128));
+}
+
+static DECLFW(M205Write)
+{
+ if((A&0x6800)==0x6800) EXPREGS[0]= V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M205Reset(void)
+{
+ EXPREGS[0]=0;
+ MMC3RegReset();
+}
+
+static void M205Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x4020,0x7FFF,M205Write);
+}
+
+void Mapper205_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, 0);
+ pwrap=M205PW;
+ cwrap=M205CW;
+ info->Power=M205Power;
+ info->Reset=M205Reset;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 215 ------------------------------
+
+static uint8 m215_perm[8] = {0, 2, 5, 3, 6, 1, 7, 4};
+
+static void M215CW(uint32 A, uint8 V)
+{
+ if(EXPREGS[1]&0x04)
+   setchr1(A,V|0x100);
+ else
+   setchr1(A,(V&0x7F)|((EXPREGS[1]&0x10)<<3));
+}
+
+static void M215PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x80)
+ {
+   setprg16(0x8000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10));
+   setprg16(0xC000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10));
+ }
+ else if(EXPREGS[1]&0x08)
+        setprg8(A,(V&0x1F)|0x20);
+      else
+        setprg8(A,(V&0x0F)|(EXPREGS[1]&0x10));
+}
+
+static DECLFW(M215Write)
+{
+ if(!(EXPREGS[2]))
+ {
+  if(A >= 0xc000)
+   MMC3_IRQWrite(A,V);
+  else
+   MMC3_CMDWrite(A,V);
+ }
+ else switch(A&0xE001)
+ {
+  case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break;
+  case 0xE001: IRQCount=V; break;
+  case 0xC001: IRQa=1; break;
+  case 0xC000: setmirror(((V|(V>>7))&1)^1); break;
+  case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m215_perm[V&7])); cmdin=1; break;
+  case 0x8001: if(!cmdin) break;
+               MMC3_CMDWrite(0x8001,V);
+               cmdin=0;
+               break;
+ }
+}
+
+static DECLFW(M215ExWrite)
+{
+ switch(A)
+ {
+  case 0x5000:
+       EXPREGS[0]=V;
+       FixMMC3PRG(MMC3_cmd);
+       break;
+  case 0x5001:
+       EXPREGS[1]=V;
+       FixMMC3CHR(MMC3_cmd);
+       break;
+  case 0x5007:
+       EXPREGS[2]=V;
+       MMC3RegReset();
+       break;
+ }
+}
+
+static void M215Power(void)
+{
+ EXPREGS[0]=0;
+ EXPREGS[1]=0xFF;
+ EXPREGS[2]=4;
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xFFFF,M215Write);
+ SetWriteHandler(0x5000,0x7FFF,M215ExWrite);
+}
+
+void Mapper215_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ cwrap=M215CW;
+ pwrap=M215PW;
+ info->Power=M215Power;
+ AddExState(EXPREGS, 3, 0, "EXPR");
+ AddExState(&cmdin, 1, 0, "CMDIN");
+}
+
+// ---------------------------- Mapper 217 ------------------------------
+
+static uint8 m217_perm[8] = {0, 6, 3, 7, 5, 2, 4, 1};
+
+static void M217CW(uint32 A, uint8 V)
+{
+ if(EXPREGS[1]&0x08)
+   setchr1(A,V|((EXPREGS[1]&3)<<8));
+ else
+   setchr1(A,(V&0x7F)|((EXPREGS[1]&3)<<8)|((EXPREGS[1]&0x10)<<3));
+}
+
+static void M217PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x80)
+ {
+   setprg16(0x8000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4));
+   setprg16(0xC000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4));
+ }
+ else if(EXPREGS[1]&0x08)
+        setprg8(A,(V&0x1F)|((EXPREGS[1]&3)<<5));
+      else
+        setprg8(A,(V&0x0F)|((EXPREGS[1]&3)<<5)|(EXPREGS[1]&0x10));
+}
+
+static DECLFW(M217Write)
+{
+ if(!EXPREGS[2])
+ {
+  if(A >= 0xc000)
+   MMC3_IRQWrite(A, V);
+  else
+   MMC3_CMDWrite(A,V);
+ }
+ else switch(A&0xE001)
+ {
+  case 0x8000: IRQCount=V; break;
+  case 0xE000: X6502_IRQEnd(FCEU_IQEXT);IRQa=0; break;
+  case 0xC001: IRQa=1; break;
+  case 0xA001: setmirror((V&1)^1); break;
+  case 0x8001: MMC3_CMDWrite(0x8000,(V&0xC0)|(m217_perm[V&7])); cmdin=1; break;
+  case 0xA000: if(!cmdin) break;
+               MMC3_CMDWrite(0x8001,V);
+               cmdin=0;
+               break;
+ }
+}
+
+static DECLFW(M217ExWrite)
+{
+ switch(A)
+ {
+  case 0x5000:
+       EXPREGS[0]=V;
+       FixMMC3PRG(MMC3_cmd);
+       break;
+  case 0x5001:
+       EXPREGS[1]=V;
+       FixMMC3PRG(MMC3_cmd);
+       break;
+  case 0x5007:
+       EXPREGS[2]=V;
+       break;
+ }
+}
+
+static void M217Power(void)
+{
+ EXPREGS[0]=0;
+ EXPREGS[1]=0xFF;
+ EXPREGS[2]=3;
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xFFFF,M217Write);
+ SetWriteHandler(0x5000,0x7FFF,M217ExWrite);
+}
+
+void Mapper217_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ cwrap=M217CW;
+ pwrap=M217PW;
+ info->Power=M217Power;
+ AddExState(EXPREGS, 3, 0, "EXPR");
+ AddExState(&cmdin, 1, 0, "CMDIN");
+}
+
+// ---------------------------- Mapper 245 ------------------------------
+
+static void M245CW(uint32 A, uint8 V)
+{
+ setchr1(A,V&7);
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+}
+
+static void M245PW(uint32 A, uint8 V)
+{
+ setprg8(A,(V&0x3F)|((EXPREGS[0]&2)<<5));
+}
+
+static void M245Power(void)
+{
+ EXPREGS[0]=0;
+ GenMMC3Power();
+}
+
+void Mapper245_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M245CW;
+ pwrap=M245PW;
+ info->Power=M245Power;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 249 ------------------------------
+
+static void M249PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x2)
+ {
+  if(V<0x20)
+   V=(V&1)|((V>>3)&2)|((V>>1)&4)|((V<<2)&8)|((V<<2)&0x10);
+  else
+  {
+   V-=0x20;
+   V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);
+  }
+ }
+ setprg8(A,V);
+}
+
+static void M249CW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x2)
+    V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0);
+ setchr1(A,V);
+}
+
+static DECLFW(M249Write)
+{
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M249Power(void)
+{
+ EXPREGS[0]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x5000,0x5000,M249Write);
+}
+
+void Mapper249_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M249CW;
+ pwrap=M249PW;
+ info->Power=M249Power;
+ AddExState(EXPREGS, 1, 0, "EXPR");
+}
+
+// ---------------------------- Mapper 250 ------------------------------
+
+static DECLFW(M250Write)
+{
+ MMC3_CMDWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
+}
+
+static DECLFW(M250IRQWrite)
+{
+ MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF);
+}
+
+static void M250_Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xBFFF,M250Write);
+ SetWriteHandler(0xC000,0xFFFF,M250IRQWrite);
+}
+
+void Mapper250_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ info->Power=M250_Power;
+}
+
+// ---------------------------- Mapper 254 ------------------------------
+
+static DECLFR(MR254WRAM)
+{
+  if(EXPREGS[0])
+    return WRAM[A-0x6000];
+  else
+    return WRAM[A-0x6000]^EXPREGS[1];
+}
+
+static DECLFW(M254Write)
+{
+ switch (A) {
+  case 0x8000: EXPREGS[0]=0xff;
+               break;
+  case 0xA001: EXPREGS[1]=V;
+ }
+ MMC3_CMDWrite(A,V);
+}
+
+static void M254_Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xBFFF,M254Write);
+ SetReadHandler(0x6000,0x7FFF,MR254WRAM);
+}
+
+void Mapper254_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 128, 8, info->battery);
+ info->Power=M254_Power;
+ AddExState(EXPREGS, 2, 0, "EXPR");
+}
+
+// ---------------------------- UNIF Boards -----------------------------
+
+void TEROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 32, 32, 0, 0);
+}
+
+void TFROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 64, 0, 0);
+}
+
+void TGROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 0, 0, 0);
+}
+
+void TKROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+}
+
+void TLROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 0, 0);
+}
+
+void TSROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, 0);
+}
+
+void TLSROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, 0);
+ cwrap=TKSWRAP;
+ mwrap=GENNOMWRAP;
+ PPU_hook=TKSPPU;
+ AddExState(&PPUCHRBus, 1, 0, "PPUC");
+}
+
+void TKSROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=TKSWRAP;
+ mwrap=GENNOMWRAP;
+ PPU_hook=TKSPPU;
+ AddExState(&PPUCHRBus, 1, 0, "PPUC");
+}
+
+void TQROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 64, 0, 0);
+ cwrap=TQWRAP;
+ CHRRAMSize=8192;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+}
+
+void HKROM_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 512, 1, info->battery);
+}
diff --git a/boards/mmc3.h b/boards/mmc3.h
new file mode 100644 (file)
index 0000000..e2c7149
--- /dev/null
@@ -0,0 +1,22 @@
+extern uint8 MMC3_cmd;\r
+extern uint8 *WRAM;\r
+//extern uint8 *CHRRAM;\r
+extern uint8 EXPREGS[8];\r
+#undef IRQCount\r
+#undef IRQLatch\r
+#undef IRQa\r
+extern uint8 IRQCount,IRQLatch,IRQa;\r
+extern uint8 IRQReload;\r
+\r
+extern void (*pwrap)(uint32 A, uint8 V);\r
+extern void (*cwrap)(uint32 A, uint8 V);\r
+extern void (*mwrap)(uint8 V);\r
+\r
+void GenMMC3Power(void);\r
+void MMC3RegReset(void);\r
+void FixMMC3PRG(int V);\r
+void FixMMC3CHR(int V);\r
+DECLFW(MMC3_CMDWrite);\r
+DECLFW(MMC3_IRQWrite);\r
+\r
+void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);\r
diff --git a/boards/mmc5.c b/boards/mmc5.c
new file mode 100644 (file)
index 0000000..d14ca0e
--- /dev/null
@@ -0,0 +1,839 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* None of this code should use any of the iNES bank switching wrappers. */
+
+#include "mapinc.h"
+
+static void (*sfun)(int P);
+static void (*psfun)(void);
+
+void MMC5RunSound(int Count);
+//void MMC5RunSoundHQ(void);
+
+static INLINE void MMC5SPRVROM_BANK1(uint32 A,uint32 V)
+{
+ if(CHRptr[0])
+ {
+  V&=CHRmask1[0];
+  MMC5SPRVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);
+ }
+}
+
+static INLINE void MMC5BGVROM_BANK1(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask1[0];MMC5BGVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
+static INLINE void MMC5BGVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]= MMC5SPRVPage[((A)>>10)+2]=MMC5SPRVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
+static INLINE void MMC5BGVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=MMC5BGVPage[((A)>>10)+2]=MMC5BGVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5SPRVPage[0]=MMC5SPRVPage[1]=MMC5SPRVPage[2]=MMC5SPRVPage[3]=MMC5SPRVPage[4]=MMC5SPRVPage[5]=MMC5SPRVPage[6]=MMC5SPRVPage[7]=&CHRptr[0][(V)<<13];}}
+static INLINE void MMC5BGVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5BGVPage[0]=MMC5BGVPage[1]=MMC5BGVPage[2]=MMC5BGVPage[3]=MMC5BGVPage[4]=MMC5BGVPage[5]=MMC5BGVPage[6]=MMC5BGVPage[7]=&CHRptr[0][(V)<<13];}}
+
+static uint8 PRGBanks[4];
+static uint8 WRAMPage;
+static uint8 CHRBanksA[8], CHRBanksB[4];
+static uint8 WRAMMaskEnable[2];
+static uint8 ABMode;                /* A=0, B=1 */
+
+static uint8 IRQScanline,IRQEnable;
+static uint8 CHRMode, NTAMirroring, NTFill, ATFill;
+
+static uint8 MMC5IRQR;
+static uint8 MMC5LineCounter;
+static uint8 mmc5psize, mmc5vsize;
+static uint8 mul[2];
+
+static uint8 *WRAM=NULL;
+static uint8 *MMC5fill=NULL;
+static uint8 *ExRAM=NULL;
+
+static uint8 MMC5WRAMsize;
+static uint8 MMC5WRAMIndex[8];
+
+static uint8 MMC5ROMWrProtect[4];
+static uint8 MMC5MemIn[5];
+
+static void MMC5CHRA(void);
+static void MMC5CHRB(void);
+
+typedef struct __cartdata {
+        uint32 crc32;
+        uint8 size;
+} cartdata;
+
+
+// ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
+// EWROM seems to have 32KB of WRAM
+
+#define MMC5_NOCARTS 14
+cartdata MMC5CartList[MMC5_NOCARTS]=
+{
+ {0x9c18762b,2},         /* L'Empereur */
+ {0x26533405,2},
+ {0x6396b988,2},
+
+ {0xaca15643,2},        /* Uncharted Waters */
+ {0xfe3488d1,2},        /* Dai Koukai Jidai */
+
+ {0x15fe6d0f,2},        /* BKAC             */
+ {0x39f2ce4b,2},        /* Suikoden              */
+
+ {0x8ce478db,2},        /* Nobunaga's Ambition 2 */
+ {0xeee9a682,2},
+
+ {0x1ced086f,2},        /* Ishin no Arashi */
+
+ {0xf540677b,4},        /* Nobunaga...Bushou Fuuun Roku */
+
+ {0x6f4e4312,4},        /* Aoki Ookami..Genchou */
+
+ {0xf011e490,4},        /* Romance of the 3 Kingdoms 2 */
+ {0x184c2124,4},        /* Sangokushi 2 */
+};
+
+
+int DetectMMC5WRAMSize(uint32 crc32)
+{
+ int x;
+ for(x=0;x<MMC5_NOCARTS;x++)
+  if(crc32==MMC5CartList[x].crc32)
+  {
+    FCEU_printf(" >8KB external WRAM present.  Use UNIF if you hack the ROM image.\n");
+    return(MMC5CartList[x].size*8);
+  }
+ return(8);
+}
+
+static void BuildWRAMSizeTable(void)
+{
+ int x;
+ for(x=0;x<8;x++)
+ {
+  switch(MMC5WRAMsize)
+  {
+      case 0: MMC5WRAMIndex[x]=255; break;
+      case 1: MMC5WRAMIndex[x]=(x>3)?255:0; break;
+      case 2: MMC5WRAMIndex[x]=(x&4)>>2; break;
+      case 4: MMC5WRAMIndex[x]=(x>3)?255:(x&3); break;
+  }
+ }
+}
+
+static void MMC5CHRA(void)
+{
+        int x;
+        switch(mmc5vsize&3)
+        {
+    case 0: setchr8(CHRBanksA[7]);
+                MMC5SPRVROM_BANK8(CHRBanksA[7]);
+                break;
+    case 1: setchr4(0x0000,CHRBanksA[3]);
+                setchr4(0x1000,CHRBanksA[7]);
+                MMC5SPRVROM_BANK4(0x0000,CHRBanksA[3]);
+                MMC5SPRVROM_BANK4(0x1000,CHRBanksA[7]);
+                break;
+    case 2: setchr2(0x0000,CHRBanksA[1]);
+                setchr2(0x0800,CHRBanksA[3]);
+                setchr2(0x1000,CHRBanksA[5]);
+                setchr2(0x1800,CHRBanksA[7]);
+                MMC5SPRVROM_BANK2(0x0000,CHRBanksA[1]);
+                MMC5SPRVROM_BANK2(0x0800,CHRBanksA[3]);
+                MMC5SPRVROM_BANK2(0x1000,CHRBanksA[5]);
+                MMC5SPRVROM_BANK2(0x1800,CHRBanksA[7]);
+                break;
+    case 3: for(x=0;x<8;x++)
+                {
+                 setchr1(x<<10,CHRBanksA[x]);
+                 MMC5SPRVROM_BANK1(x<<10,CHRBanksA[x]);
+                }
+                break;
+ }
+}
+
+static void MMC5CHRB(void)
+{
+ int x;
+ switch(mmc5vsize&3)
+ {
+    case 0: setchr8(CHRBanksB[3]);
+                MMC5BGVROM_BANK8(CHRBanksB[3]);
+                break;
+    case 1: setchr4(0x0000,CHRBanksB[3]);
+                       setchr4(0x1000,CHRBanksB[3]);
+                MMC5BGVROM_BANK4(0x0000,CHRBanksB[3]);
+                MMC5BGVROM_BANK4(0x1000,CHRBanksB[3]);
+                break;
+    case 2: setchr2(0x0000,CHRBanksB[1]);
+                setchr2(0x0800,CHRBanksB[3]);
+                setchr2(0x1000,CHRBanksB[1]);
+                setchr2(0x1800,CHRBanksB[3]);
+                MMC5BGVROM_BANK2(0x0000,CHRBanksB[1]);
+                MMC5BGVROM_BANK2(0x0800,CHRBanksB[3]);
+                MMC5BGVROM_BANK2(0x1000,CHRBanksB[1]);
+                MMC5BGVROM_BANK2(0x1800,CHRBanksB[3]);
+                break;
+    case 3: for(x=0;x<8;x++)
+                {
+                 setchr1(x<<10,CHRBanksB[x&3]);
+                 MMC5BGVROM_BANK1(x<<10,CHRBanksB[x&3]);
+                }
+                break;
+ }
+}
+
+static void FASTAPASS(2) MMC5WRAM(uint32 A, uint32 V)
+{
+   //printf("%02x\n",V);
+   V=MMC5WRAMIndex[V&7];
+   if(V!=255)
+   {
+    setprg8r(0x10,A,V);
+    MMC5MemIn[(A-0x6000)>>13]=1;
+   }
+   else
+    MMC5MemIn[(A-0x6000)>>13]=0;
+}
+
+static void MMC5PRG(void)
+{
+ int x;
+ switch(mmc5psize&3)
+  {
+    case 0: MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=
+           MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
+           setprg32(0x8000,((PRGBanks[1]&0x7F)>>2));
+           for(x=0;x<4;x++)
+             MMC5MemIn[1+x]=1;
+           break;
+    case 1: if(PRGBanks[1]&0x80)
+          {
+           MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
+           setprg16(0x8000,(PRGBanks[1]>>1));
+           MMC5MemIn[1]=MMC5MemIn[2]=1;
+          }
+         else
+          {
+           MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
+           MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
+           MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
+          }
+          MMC5MemIn[3]=MMC5MemIn[4]=1;
+          MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
+          setprg16(0xC000,(PRGBanks[3]&0x7F)>>1);
+         break;
+    case 2: if(PRGBanks[1]&0x80)
+          {
+           MMC5MemIn[1]=MMC5MemIn[2]=1;
+           MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
+           setprg16(0x8000,(PRGBanks[1]&0x7F)>>1);
+          }
+         else
+          {
+           MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
+           MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
+           MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
+          }
+         if(PRGBanks[2]&0x80)
+            {
+              MMC5ROMWrProtect[2]=1;
+              MMC5MemIn[3]=1;
+              setprg8(0xC000,PRGBanks[2]&0x7F);
+            }
+            else
+            {
+              MMC5ROMWrProtect[2]=0;
+              MMC5WRAM(0xC000,PRGBanks[2]&7);
+            }
+            MMC5MemIn[4]=1;
+            MMC5ROMWrProtect[3]=1;
+            setprg8(0xE000,PRGBanks[3]&0x7F);
+            break;
+    case 3: for(x=0;x<3;x++)
+          if(PRGBanks[x]&0x80)
+          {
+           MMC5ROMWrProtect[x]=1;
+           setprg8(0x8000+(x<<13),PRGBanks[x]&0x7F);
+           MMC5MemIn[1+x]=1;
+          }
+          else
+          {
+           MMC5ROMWrProtect[x]=0;
+           MMC5WRAM(0x8000+(x<<13),PRGBanks[x]&7);
+          }
+         MMC5MemIn[4]=1;
+         MMC5ROMWrProtect[3]=1;
+         setprg8(0xE000,PRGBanks[3]&0x7F);
+         break;
+  }
+}
+
+static DECLFW(Mapper5_write)
+{
+  if(A>=0x5120&&A<=0x5127)
+ {
+  ABMode = 0;
+  CHRBanksA[A&7]=V;
+  MMC5CHRA();
+ }
+ else switch(A)
+ {
+    case 0x5105: {
+                int x;
+                for(x=0;x<4;x++)
+                {
+                 switch((V>>(x<<1))&3)
+                 {
+                  case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
+                  case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
+                  case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
+                  case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
+                 }
+                }
+               }
+               NTAMirroring=V;
+               break;
+    case 0x5113: WRAMPage=V;MMC5WRAM(0x6000,V&7);break;
+    case 0x5100: mmc5psize=V;MMC5PRG();break;
+    case 0x5101: mmc5vsize=V;
+                 if(!ABMode)
+                 { MMC5CHRB();MMC5CHRA();}
+                 else
+                 { MMC5CHRA();MMC5CHRB();}
+                 break;
+   case 0x5114:
+   case 0x5115:
+   case 0x5116:
+    case 0x5117: PRGBanks[A&3]=V;MMC5PRG();break;
+   case 0x5128:
+   case 0x5129:
+   case 0x512a:
+    case 0x512b: ABMode=1;
+               CHRBanksB[A&3]=V;
+               MMC5CHRB();
+               break;
+    case 0x5102: WRAMMaskEnable[0]=V;break;
+    case 0x5103: WRAMMaskEnable[1]=V;break;
+    case 0x5104: CHRMode=V;MMC5HackCHRMode=V&3;break;
+    case 0x5106: if(V!=NTFill)
+               {
+                uint32 t;
+                t=V|(V<<8)|(V<<16)|(V<<24);
+                FCEU_dwmemset(MMC5fill,t,0x3c0);
+               }
+               NTFill=V;
+               break;
+    case 0x5107: if(V!=ATFill)
+               {
+                unsigned char moop;
+                uint32 t;
+                moop=V|(V<<2)|(V<<4)|(V<<6);
+                t=moop|(moop<<8)|(moop<<16)|(moop<<24);
+                FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
+               }
+               ATFill=V;
+               break;
+    case 0x5200: MMC5HackSPMode=V;break;
+    case 0x5201: MMC5HackSPScroll=(V>>3)&0x1F;break;
+    case 0x5202: MMC5HackSPPage=V&0x3F;break;
+    case 0x5203: X6502_IRQEnd(FCEU_IQEXT);IRQScanline=V;break;
+    case 0x5204: X6502_IRQEnd(FCEU_IQEXT);IRQEnable=V&0x80;break;
+    case 0x5205: mul[0]=V;break;
+    case 0x5206: mul[1]=V;break;
+  }
+}
+
+static DECLFR(MMC5_ReadROMRAM)
+{
+        if(MMC5MemIn[(A-0x6000)>>13])
+         return Page[A>>11][A];
+        else
+         return X.DB;
+}
+
+static DECLFW(MMC5_WriteROMRAM)
+{
+       if(A>=0x8000)
+    if(MMC5ROMWrProtect[(A-0x8000)>>13]) return;
+  if(MMC5MemIn[(A-0x6000)>>13])
+    if(((WRAMMaskEnable[0]&3)|((WRAMMaskEnable[1]&3)<<2)) == 6) Page[A>>11][A]=V;
+}
+
+static DECLFW(MMC5_ExRAMWr)
+{
+ if(MMC5HackCHRMode!=3)
+  ExRAM[A&0x3ff]=V;
+}
+
+static DECLFR(MMC5_ExRAMRd)
+{
+ /* Not sure if this is correct, so I'll comment it out for now. */
+ //if(MMC5HackCHRMode>=2)
+  return ExRAM[A&0x3ff];
+ //else
+ // return(X.DB);
+}
+
+static DECLFR(MMC5_read)
+{
+ switch(A)
+ {
+    case 0x5204: X6502_IRQEnd(FCEU_IQEXT);
+              {
+                uint8 x;
+                x=MMC5IRQR;
+                if(!fceuindbg)
+                 MMC5IRQR&=0x40;
+                return x;
+              }
+    case 0x5205: return (mul[0]*mul[1]);
+    case 0x5206: return ((mul[0]*mul[1])>>8);
+ }
+ return(X.DB);
+}
+
+void MMC5Synco(void)
+{
+ int x;
+
+ MMC5PRG();
+ for(x=0;x<4;x++)
+ {
+  switch((NTAMirroring>>(x<<1))&3)
+   {
+    case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
+    case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
+    case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
+    case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
+   }
+ }
+ MMC5WRAM(0x6000,WRAMPage&7);
+ if(!ABMode)
+ {
+  MMC5CHRB();
+  MMC5CHRA();
+ }
+ else
+ {
+   MMC5CHRA();
+   MMC5CHRB();
+ }
+  {
+    uint32 t;
+    t=NTFill|(NTFill<<8)|(NTFill<<16)|(NTFill<<24);
+    FCEU_dwmemset(MMC5fill,t,0x3c0);
+  }
+  {
+   unsigned char moop;
+   uint32 t;
+   moop=ATFill|(ATFill<<2)|(ATFill<<4)|(ATFill<<6);
+   t=moop|(moop<<8)|(moop<<16)|(moop<<24);
+   FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
+  }
+  X6502_IRQEnd(FCEU_IQEXT);
+  MMC5HackCHRMode=CHRMode&3;
+}
+
+void MMC5_hb(int scanline)
+{
+  if(scanline==240)
+  {
+   MMC5LineCounter=0;
+   MMC5IRQR=0x40;
+   return;
+  }
+  if(MMC5LineCounter<240)
+  {
+   if(MMC5LineCounter==IRQScanline)
+   {
+    MMC5IRQR|=0x80;
+    if(IRQEnable&0x80)
+     X6502_IRQBegin(FCEU_IQEXT);
+   }
+   MMC5LineCounter++;
+  }
+ if(MMC5LineCounter==240)
+   MMC5IRQR=0;
+}
+
+void MMC5_StateRestore(int version)
+{
+ MMC5Synco();
+}
+
+typedef struct {
+        uint16 wl[2];
+        uint8 env[2];
+        uint8 enable;
+        uint8 running;
+        uint8 raw;
+        uint8 rawcontrol;
+        int32 dcount[2];
+        int32 BC[3];
+        int32 vcount[2];
+} MMC5APU;
+
+static MMC5APU MMC5Sound;
+
+
+static void Do5PCM()
+{
+   int32 V;
+   int32 start,end;
+
+   start=MMC5Sound.BC[2];
+   end=(SOUNDTS<<16)/soundtsinc;
+   if(end<=start) return;
+   MMC5Sound.BC[2]=end;
+
+   if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
+    for(V=start;V<end;V++)
+     Wave[V>>4]+=MMC5Sound.raw<<1;
+}
+
+#if 0
+static void Do5PCMHQ()
+{
+   int32 V;
+   if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
+    for(V=MMC5Sound.BC[2];V<SOUNDTS;V++)
+     WaveHi[V]+=MMC5Sound.raw<<5;
+   MMC5Sound.BC[2]=SOUNDTS;
+}
+#endif
+
+static DECLFW(Mapper5_SW)
+{
+ A&=0x1F;
+
+ GameExpSound.Fill=MMC5RunSound;
+ GameExpSound.HiFill=0;//MMC5RunSoundHQ;
+
+ switch(A)
+ {
+  case 0x10:if(psfun) psfun();MMC5Sound.rawcontrol=V;break;
+  case 0x11:if(psfun) psfun();MMC5Sound.raw=V;break;
+
+  case 0x0:
+  case 0x4://printf("%04x:$%02x\n",A,V&0x30);
+           if(sfun) sfun(A>>2);
+           MMC5Sound.env[A>>2]=V;
+           break;
+  case 0x2:
+    case 0x6: if(sfun) sfun(A>>2);
+           MMC5Sound.wl[A>>2]&=~0x00FF;
+           MMC5Sound.wl[A>>2]|=V&0xFF;
+           break;
+  case 0x3:
+  case 0x7://printf("%04x:$%02x\n",A,V>>3);
+           MMC5Sound.wl[A>>2]&=~0x0700;
+           MMC5Sound.wl[A>>2]|=(V&0x07)<<8;
+           MMC5Sound.running|=1<<(A>>2);
+           break;
+  case 0x15:if(sfun)
+            {
+             sfun(0);
+             sfun(1);
+            }
+            MMC5Sound.running&=V;
+            MMC5Sound.enable=V;
+                //printf("%02x\n",V);
+            break;
+ }
+}
+
+static void Do5SQ(int P)
+{
+ static int tal[4]={1,2,4,6};
+ int32 V,amp,rthresh,wl;
+ int32 start,end;
+
+ start=MMC5Sound.BC[P];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ MMC5Sound.BC[P]=end;
+
+ wl=MMC5Sound.wl[P]+1;
+ amp=(MMC5Sound.env[P]&0xF)<<4;
+ rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
+
+ if(wl>=8 && (MMC5Sound.running&(P+1)))
+ {
+  int dc,vc;
+
+  wl<<=18;
+  dc=MMC5Sound.dcount[P];
+  vc=MMC5Sound.vcount[P];
+
+  for(V=start;V<end;V++)
+  {
+    if(dc<rthresh)
+     Wave[V>>4]+=amp;
+    vc-=nesincsize;
+    while(vc<=0)
+    {
+     vc+=wl;
+     dc=(dc+1)&7;
+    }
+  }
+  MMC5Sound.dcount[P]=dc;
+  MMC5Sound.vcount[P]=vc;
+ }
+}
+
+#if 0
+static void Do5SQHQ(int P)
+{
+ static int tal[4]={1,2,4,6};
+ int32 V,amp,rthresh,wl;
+
+ wl=MMC5Sound.wl[P]+1;
+ amp=((MMC5Sound.env[P]&0xF)<<8);
+ rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
+
+ if(wl>=8 && (MMC5Sound.running&(P+1)))
+ {
+  int dc,vc;
+
+  wl<<=1;
+
+  dc=MMC5Sound.dcount[P];
+  vc=MMC5Sound.vcount[P];
+  for(V=MMC5Sound.BC[P];V<SOUNDTS;V++)
+  {
+    if(dc<rthresh)
+     WaveHi[V]+=amp;
+    vc--;
+    if(vc<=0)   /* Less than zero when first started. */
+    {
+     vc=wl;
+     dc=(dc+1)&7;
+    }
+  }
+  MMC5Sound.dcount[P]=dc;
+  MMC5Sound.vcount[P]=vc;
+ }
+ MMC5Sound.BC[P]=SOUNDTS;
+}
+
+void MMC5RunSoundHQ(void)
+{
+  Do5SQHQ(0);
+  Do5SQHQ(1);
+  Do5PCMHQ();
+}
+
+void MMC5HiSync(int32 ts)
+{
+ int x;
+ for(x=0;x<3;x++) MMC5Sound.BC[x]=ts;
+}
+#endif
+
+void MMC5RunSound(int Count)
+{
+  int x;
+  Do5SQ(0);
+  Do5SQ(1);
+  Do5PCM();
+  for(x=0;x<3;x++)
+   MMC5Sound.BC[x]=Count;
+}
+
+void Mapper5_ESI(void)
+{
+ GameExpSound.RChange=Mapper5_ESI;
+ if(FSettings.SndRate)
+ {
+#if 0
+  if(FSettings.soundq>=1)
+  {
+   sfun=Do5SQHQ;
+   psfun=Do5PCMHQ;
+  }
+  else
+#endif
+  {
+   sfun=Do5SQ;
+   psfun=Do5PCM;
+  }
+ }
+ else
+ {
+  sfun=0;
+  psfun=0;
+ }
+ memset(MMC5Sound.BC,0,sizeof(MMC5Sound.BC));
+ memset(MMC5Sound.vcount,0,sizeof(MMC5Sound.vcount));
+ GameExpSound.HiSync=0;//MMC5HiSync;
+}
+
+void NSFMMC5_Init(void)
+{
+  memset(&MMC5Sound,0,sizeof(MMC5Sound));
+  mul[0]=mul[1]=0;
+  ExRAM=(uint8*)FCEU_gmalloc(1024);
+  Mapper5_ESI();
+  SetWriteHandler(0x5c00,0x5fef,MMC5_ExRAMWr);
+  SetReadHandler(0x5c00,0x5fef,MMC5_ExRAMRd);
+  MMC5HackCHRMode=2;
+  SetWriteHandler(0x5000,0x5015,Mapper5_SW);
+  SetWriteHandler(0x5205,0x5206,Mapper5_write);
+  SetReadHandler(0x5205,0x5206,MMC5_read);
+}
+
+void NSFMMC5_Close(void)
+{
+ FCEU_gfree(ExRAM);
+ ExRAM=0;
+}
+
+static void GenMMC5Reset(void)
+{
+ int x;
+
+ for(x=0;x<4;x++) PRGBanks[x]=~0;
+ for(x=0;x<8;x++) CHRBanksA[x]=~0;
+ for(x=0;x<4;x++) CHRBanksB[x]=~0;
+ WRAMMaskEnable[0]=WRAMMaskEnable[1]=~0;
+
+ mmc5psize=mmc5vsize=3;
+ CHRMode=0;
+
+ NTAMirroring=NTFill=ATFill=0xFF;
+
+ MMC5Synco();
+
+ SetWriteHandler(0x4020,0x5bff,Mapper5_write);
+ SetReadHandler(0x4020,0x5bff,MMC5_read);
+
+ SetWriteHandler(0x5c00,0x5fff,MMC5_ExRAMWr);
+ SetReadHandler(0x5c00,0x5fff,MMC5_ExRAMRd);
+
+ SetWriteHandler(0x6000,0xFFFF,MMC5_WriteROMRAM);
+ SetReadHandler(0x6000,0xFFFF,MMC5_ReadROMRAM);
+
+ SetWriteHandler(0x5000,0x5015,Mapper5_SW);
+ SetWriteHandler(0x5205,0x5206,Mapper5_write);
+ SetReadHandler(0x5205,0x5206,MMC5_read);
+
+ //GameHBIRQHook=MMC5_hb;
+ FCEU_CheatAddRAM(8,0x6000,WRAM);
+ FCEU_CheatAddRAM(1,0x5c00,ExRAM);
+}
+
+static SFORMAT MMC5_StateRegs[]={
+        { PRGBanks, 4, "PRGB"},
+        { CHRBanksA, 8, "CHRA"},
+        { CHRBanksB, 4, "CHRB"},
+        { &WRAMPage, 1, "WRMP"},
+        { WRAMMaskEnable, 2, "WRME"},
+        { &ABMode, 1, "ABMD"},
+        { &IRQScanline, 1, "IRQS"},
+        { &IRQEnable, 1, "IRQE"},
+        { &CHRMode, 1, "CHRM"},
+        { &NTAMirroring, 1, "NTAM"},
+        { &NTFill, 1, "NTFL"},
+        { &ATFill, 1, "ATFL"},
+
+        { &MMC5Sound.wl[0], 2|FCEUSTATE_RLSB, "SDW0"},
+        { &MMC5Sound.wl[1], 2|FCEUSTATE_RLSB, "SDW1"},
+        { MMC5Sound.env, 2, "SDEV"},
+        { &MMC5Sound.enable, 1, "SDEN"},
+        { &MMC5Sound.running, 1, "SDRU"},
+        { &MMC5Sound.raw, 1, "SDRW"},
+        { &MMC5Sound.rawcontrol, 1, "SDRC"},
+        {0}
+};
+
+static void GenMMC5_Init(CartInfo *info, int wsize, int battery)
+{
+ if(wsize)
+ {
+  WRAM=(uint8*)FCEU_gmalloc(wsize*1024);
+  SetupCartPRGMapping(0x10,WRAM,wsize*1024,1);
+  AddExState(WRAM, wsize*1024, 0, "WRAM");
+ }
+
+ MMC5fill=(uint8*)FCEU_gmalloc(1024);
+ ExRAM=(uint8*)FCEU_gmalloc(1024);
+
+ AddExState(MMC5_StateRegs, ~0, 0, 0);
+ AddExState(WRAM, wsize*1024, 0, "WRAM");
+ AddExState(ExRAM, 1024, 0, "ERAM");
+ AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
+ AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
+ AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
+
+ MMC5WRAMsize=wsize/8;
+ BuildWRAMSizeTable();
+ GameStateRestore=MMC5_StateRestore;
+ info->Power=GenMMC5Reset;
+
+ if(battery)
+ {
+  info->SaveGame[0]=WRAM;
+  if(wsize<=16)
+   info->SaveGameLen[0]=8192;
+  else
+   info->SaveGameLen[0]=32768;
+ }
+
+ MMC5HackVROMMask=CHRmask4[0];
+ MMC5HackExNTARAMPtr=ExRAM;
+ MMC5Hack=1;
+ MMC5HackVROMPTR=CHRptr[0];
+ MMC5HackCHRMode=0;
+ MMC5HackSPMode=MMC5HackSPScroll=MMC5HackSPPage=0;
+ Mapper5_ESI();
+}
+
+void Mapper5_Init(CartInfo *info)
+{
+ GenMMC5_Init(info, DetectMMC5WRAMSize(info->CRC32), info->battery);
+}
+
+// ELROM seems to have 0KB of WRAM
+// EKROM seems to have 8KB of WRAM
+// ETROM seems to have 16KB of WRAM
+// EWROM seems to have 32KB of WRAM
+
+// ETROM and EWROM are battery-backed, EKROM isn't.
+
+void ETROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info, 16,info->battery);
+}
+
+void ELROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,0,0);
+}
+
+void EWROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,32,info->battery);
+}
+
+void EKROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,8,info->battery);
+}
diff --git a/boards/n106.c b/boards/n106.c
new file mode 100644 (file)
index 0000000..2872d16
--- /dev/null
@@ -0,0 +1,472 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint16 IRQCount;
+static uint8 IRQa;
+
+static uint8 WRAM[8192];
+static uint8 IRAM[128];
+
+static DECLFR(AWRAM)
+{
+  return(WRAM[A-0x6000]);
+}
+
+static DECLFW(BWRAM)
+{
+  WRAM[A-0x6000]=V;
+}
+
+void Mapper19_ESI(void);
+
+static uint8 NTAPage[4];
+
+static uint8 dopol;
+static uint8 gorfus;
+static uint8 gorko;
+
+static void NamcoSound(int Count);
+static void NamcoSoundHack(void);
+static void DoNamcoSound(int32 *Wave, int Count);
+//static void DoNamcoSoundHQ(void);
+static void SyncHQ(int32 ts);
+
+static int is210;        /* Lesser mapper. */
+
+static uint8 PRG[3];
+static uint8 CHR[8];
+
+static SFORMAT N106_StateRegs[]={
+  {PRG,3,"PRG"},
+  {CHR,8,"CHR"},
+  {NTAPage,4,"NTA"},
+  {0}
+};
+
+static void SyncPRG(void)
+{
+  setprg8(0x8000,PRG[0]);
+  setprg8(0xa000,PRG[1]);
+  setprg8(0xc000,PRG[2]);
+  setprg8(0xe000,0x3F);
+}
+
+static void FP_FASTAPASS(1) NamcoIRQHook(int a)
+{
+  if(IRQa)
+  {
+    IRQCount+=a;
+    if(IRQCount>=0x7FFF)
+    {
+      X6502_IRQBegin(FCEU_IQEXT);
+      IRQa=0;
+      IRQCount=0x7FFF; //7FFF;
+    }
+  }
+}
+
+static DECLFR(Namco_Read4800)
+{
+  uint8 ret=IRAM[dopol&0x7f];
+  /* Maybe I should call NamcoSoundHack() here? */
+  if(!fceuindbg)
+    if(dopol&0x80)
+      dopol=(dopol&0x80)|((dopol+1)&0x7f);
+  return ret;
+}
+
+static DECLFR(Namco_Read5000)
+{
+  return(IRQCount);
+}
+
+static DECLFR(Namco_Read5800)
+{
+  return(IRQCount>>8);
+}
+
+static void FASTAPASS(2) DoNTARAMROM(int w, uint8 V)
+{
+  NTAPage[w]=V;
+  if(V>=0xE0)
+    setntamem(NTARAM+((V&1)<<10), 1, w);
+  else
+  {
+    V&=CHRmask1[0];
+    setntamem(CHRptr[0]+(V<<10), 0, w);
+  }
+}
+
+static void FixNTAR(void)
+{
+  int x;
+  for(x=0;x<4;x++)
+     DoNTARAMROM(x,NTAPage[x]);
+}
+
+static void FASTAPASS(2) DoCHRRAMROM(int x, uint8 V)
+{
+  CHR[x]=V;
+  if(!is210 && !((gorfus>>((x>>2)+6))&1) && (V>=0xE0))
+  {
+    // printf("BLAHAHA: %d, %02x\n",x,V);
+    //setchr1r(0x10,x<<10,V&7);
+  }
+  else
+    setchr1(x<<10,V);
+}
+
+static void FixCRR(void)
+{
+  int x;
+  for(x=0;x<8;x++)
+     DoCHRRAMROM(x,CHR[x]);
+}
+
+static DECLFW(Mapper19C0D8_write)
+{
+  DoNTARAMROM((A-0xC000)>>11,V);
+}
+
+static uint32 FreqCache[8];
+static uint32 EnvCache[8];
+static uint32 LengthCache[8];
+
+static void FixCache(int a,int V)
+{
+  int w=(a>>3)&0x7;
+  switch(a&0x07)
+  {
+    case 0x00:FreqCache[w]&=~0x000000FF;FreqCache[w]|=V;break;
+    case 0x02:FreqCache[w]&=~0x0000FF00;FreqCache[w]|=V<<8;break;
+    case 0x04:FreqCache[w]&=~0x00030000;FreqCache[w]|=(V&3)<<16;
+              LengthCache[w]=(8-((V>>2)&7))<<2;
+              break;
+    case 0x07:EnvCache[w]=(double)(V&0xF)*576716;break;
+  }
+}
+
+static DECLFW(Mapper19_write)
+{
+  A&=0xF800;
+  if(A>=0x8000 && A<=0xb800)
+    DoCHRRAMROM((A-0x8000)>>11,V);
+  else switch(A)
+  {
+    case 0x4800:
+         if(dopol&0x40)
+         {
+           if(FSettings.SndRate)
+           {
+             NamcoSoundHack();
+             GameExpSound.Fill=NamcoSound;
+             GameExpSound.HiFill=0;//DoNamcoSoundHQ;
+             GameExpSound.HiSync=SyncHQ;
+           }
+           FixCache(dopol,V);
+         }
+         IRAM[dopol&0x7f]=V;
+         if(dopol&0x80)
+           dopol=(dopol&0x80)|((dopol+1)&0x7f);
+         break;
+    case 0xf800:
+         dopol=V;break;
+    case 0x5000:
+         IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break;
+    case 0x5800:
+         IRQCount&=0x00ff;IRQCount|=(V&0x7F)<<8;
+         IRQa=V&0x80;
+         X6502_IRQEnd(FCEU_IQEXT);
+         break;
+    case 0xE000:
+         gorko=V&0xC0;
+         PRG[0]=V&0x3F;
+         SyncPRG();
+         break;
+    case 0xE800:
+         gorfus=V&0xC0;
+         FixCRR();
+         PRG[1]=V&0x3F;
+         SyncPRG();
+         break;
+    case 0xF000:
+         PRG[2]=V&0x3F;
+         SyncPRG();
+         break;
+  }
+}
+
+static int dwave=0;
+
+static void NamcoSoundHack(void)
+{
+  int32 z,a;
+#if 0
+  if(FSettings.soundq>=1)
+  {
+    DoNamcoSoundHQ();
+    return;
+  }
+#endif
+  z=((SOUNDTS<<16)/soundtsinc)>>4;
+  a=z-dwave;
+  if(a) DoNamcoSound(&Wave[dwave], a);
+  dwave+=a;
+}
+
+static void NamcoSound(int Count)
+{
+  int32 z,a;
+  z=((SOUNDTS<<16)/soundtsinc)>>4;
+  a=z-dwave;
+  if(a) DoNamcoSound(&Wave[dwave], a);
+  dwave=0;
+}
+
+static uint32 PlayIndex[8];
+static int32 vcount[8];
+static int32 CVBC;
+
+#define TOINDEX        (16+1)
+
+// 16:15
+static void SyncHQ(int32 ts)
+{
+  CVBC=ts;
+}
+
+
+/* Things to do:
+        1        Read freq low
+        2        Read freq mid
+        3        Read freq high
+        4        Read envelope
+        ...?
+*/
+
+static INLINE uint32 FetchDuff(uint32 P, uint32 envelope)
+{
+  uint32 duff;
+  duff=IRAM[((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&0xFF)>>1];
+  if((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&1)
+    duff>>=4;
+  duff&=0xF;
+  duff=(duff*envelope)>>16;
+  return(duff);
+}
+
+#if 0
+static void DoNamcoSoundHQ(void)
+{
+  int32 P,V;
+  int32 cyclesuck=(((IRAM[0x7F]>>4)&7)+1)*15;
+
+  for(P=7;P>=(7-((IRAM[0x7F]>>4)&7));P--)
+  {
+    if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
+    {
+      uint32 freq;
+      int32 vco;
+      uint32 duff2,lengo,envelope;
+
+      vco=vcount[P];
+      freq=FreqCache[P];
+      envelope=EnvCache[P];
+      lengo=LengthCache[P];
+
+      duff2=FetchDuff(P,envelope);
+      for(V=CVBC<<1;V<SOUNDTS<<1;V++)
+      {
+        WaveHi[V>>1]+=duff2;
+        if(!vco)
+        {
+          PlayIndex[P]+=freq;
+          while((PlayIndex[P]>>TOINDEX)>=lengo) PlayIndex[P]-=lengo<<TOINDEX;
+          duff2=FetchDuff(P,envelope);
+          vco=cyclesuck;
+        }
+        vco--;
+      }
+      vcount[P]=vco;
+    }
+  }
+  CVBC=SOUNDTS;
+}
+#endif
+
+static void DoNamcoSound(int32 *Wave, int Count)
+{
+  int P,V;
+  for(P=7;P>=7-((IRAM[0x7F]>>4)&7);P--)
+  {
+    if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
+    {
+      int32 inc;
+      uint32 freq;
+      int32 vco;
+      uint32 duff,duff2,lengo,envelope;
+
+      vco=vcount[P];
+      freq=FreqCache[P];
+      envelope=EnvCache[P];
+      lengo=LengthCache[P];
+
+      if(!freq) {/*printf("Ack");*/  continue;}
+
+      {
+        int c=((IRAM[0x7F]>>4)&7)+1;
+        inc=(long double)(FSettings.SndRate<<15)/((long double)freq*21477272/((long double)0x400000*c*45));
+      }
+
+      duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
+      if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
+        duff>>=4;
+      duff&=0xF;
+      duff2=(duff*envelope)>>19;
+      for(V=0;V<Count*16;V++)
+      {
+        if(vco>=inc)
+        {
+          PlayIndex[P]++;
+          if(PlayIndex[P]>=lengo)
+            PlayIndex[P]=0;
+          vco-=inc;
+          duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
+          if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
+            duff>>=4;
+          duff&=0xF;
+          duff2=(duff*envelope)>>19;
+        }
+        Wave[V>>4]+=duff2;
+        vco+=0x8000;
+      }
+      vcount[P]=vco;
+    }
+  }
+}
+
+static void Mapper19_StateRestore(int version)
+{
+  SyncPRG();
+  FixNTAR();
+  FixCRR();
+  int x;
+  for(x=0x40;x<0x80;x++)
+     FixCache(x,IRAM[x]);
+}
+
+static void M19SC(void)
+{
+  if(FSettings.SndRate)
+    Mapper19_ESI();
+}
+
+void Mapper19_ESI(void)
+{
+  GameExpSound.RChange=M19SC;
+  memset(vcount,0,sizeof(vcount));
+  memset(PlayIndex,0,sizeof(PlayIndex));
+  CVBC=0;
+}
+
+void NSFN106_Init(void)
+{
+  SetWriteHandler(0xf800,0xffff,Mapper19_write);
+  SetWriteHandler(0x4800,0x4fff,Mapper19_write);
+  SetReadHandler(0x4800,0x4fff,Namco_Read4800);
+  Mapper19_ESI();
+}
+
+static int battery=0;
+
+static void N106_Power(void)
+{
+  int x;
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetWriteHandler(0x8000,0xffff,Mapper19_write);
+  SetWriteHandler(0x4020,0x5fff,Mapper19_write);
+  if(!is210)
+  {
+    SetWriteHandler(0xc000,0xdfff,Mapper19C0D8_write);
+    SetReadHandler(0x4800,0x4fff,Namco_Read4800);
+    SetReadHandler(0x5000,0x57ff,Namco_Read5000);
+    SetReadHandler(0x5800,0x5fff,Namco_Read5800);
+    NTAPage[0]=NTAPage[1]=NTAPage[2]=NTAPage[3]=0xFF;
+    FixNTAR();
+  }
+
+  SetReadHandler(0x6000,0x7FFF,AWRAM);
+  SetWriteHandler(0x6000,0x7FFF,BWRAM);
+  FCEU_CheatAddRAM(8,0x6000,WRAM);
+
+  gorfus=0xFF;
+  SyncPRG();
+  FixCRR();
+
+  if(!battery)
+  {
+    FCEU_dwmemset(WRAM,0,8192);
+    FCEU_dwmemset(IRAM,0,128);
+  }
+  for(x=0x40;x<0x80;x++)
+     FixCache(x,IRAM[x]);
+}
+
+void Mapper19_Init(CartInfo *info)
+{
+  is210=0;
+  battery=info->battery;
+  info->Power=N106_Power;
+
+  MapIRQHook=NamcoIRQHook;
+  GameStateRestore=Mapper19_StateRestore;
+  GameExpSound.RChange=M19SC;
+
+  if(FSettings.SndRate)
+    Mapper19_ESI();
+
+  AddExState(WRAM, 8192, 0, "WRAM");
+  AddExState(IRAM, 128, 0, "WRAM");
+  AddExState(N106_StateRegs, ~0, 0, 0);
+
+  if(info->battery)
+  {
+    info->SaveGame[0]=WRAM;
+    info->SaveGameLen[0]=8192;
+    info->SaveGame[1]=IRAM;
+    info->SaveGameLen[1]=128;
+  }
+}
+
+static void Mapper210_StateRestore(int version)
+{
+  SyncPRG();
+  FixCRR();
+}
+
+void Mapper210_Init(CartInfo *info)
+{
+  is210=1;
+  GameStateRestore=Mapper210_StateRestore;
+  info->Power=N106_Power;
+  AddExState(WRAM, 8192, 0, "WRAM");
+}
index fe3a37c..26e70ec 100644 (file)
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "mapinc.h"
 
+static uint8 latch;
+
 static void DoNovel(void)
 {
- setprg32(0x8000,GameMemBlock[0]&3);
- setchr8(GameMemBlock[0]&7);
- X6502_Rebase();
+  setprg32(0x8000,latch&3);
+  setchr8(latch&7);
 }
 
 static DECLFW(NovelWrite)
 {
GameMemBlock[0]=A&0xFF;
- DoNovel();
 latch=A&0xFF;
 DoNovel();
 }
 
 static void NovelReset(void)
 {
   SetWriteHandler(0x8000,0xFFFF,NovelWrite);
-  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetReadHandler(0x8000,0xFFFF,CartBR);  
   setprg32(0x8000,0);
   setchr8(0);
 }
 
 static void NovelRestore(int version)
 {
- DoNovel();
 DoNovel();
 }
 
-void Novel_Init(void)
+void Novel_Init(CartInfo *info)
 {
-  AddExState(&GameMemBlock[0], 1, 0,"L1");
-  BoardPower=NovelReset;
+  AddExState(&latch, 1, 0,"L1");
+  info->Power=NovelReset;
   GameStateRestore=NovelRestore;
 }
index a26dd07..bcec3a9 100644 (file)
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 static uint8 cmd;
 static uint8 latch[8];
-#define CHRRAM (GameMemBlock)
+
+static void MSync(uint8 mirr)
+{
+  switch(mirr&3)
+  {
+    case 0:setmirror(MI_V);break;
+    case 1:setmirror(MI_H);break;
+    case 2:setmirrorw(0,1,1,1);break;
+    case 3:setmirror(MI_0);break;
+  }
+}
 
 static void S74LS374NSynco(void)
 {
- setprg32(0x8000,latch[0]);
- X6502_Rebase();
- setchr8(latch[1]);
- setmirror(latch[2]&1);
-// setchr8(6);
+  setprg32(0x8000,latch[0]);
+  setchr8(latch[1]|latch[3]|latch[4]);
+  MSync(latch[2]);
 }
 
 static DECLFW(S74LS374NWrite)
 {
- //printf("$%04x:$%02x\n",A,V);
- A&=0x4101;
- if(A==0x4100)
-  cmd=V&7;
- else
- {
-  switch(cmd)
+  A&=0x4101;
+  if(A==0x4100)
+    cmd=V&7;
+  else
   {
-   case 0:latch[0]=0;latch[1]=3;break;
-   case 4:latch[1]&=3;latch[1]|=(V<<2);break;
-   case 5:latch[0]=V&0x7;break;
-   case 6:latch[1]&=0x1C;latch[1]|=V&3;break;
-   case 7:latch[2]=V&1;break;
+    switch(cmd)
+    {
+      case 2:latch[3]=(V&1)<<3;break;
+      case 4:latch[4]=(V&1)<<2;break;
+      case 5:latch[0]=V&0x7;break;
+      case 6:latch[1]=V&3;break;
+      case 7:latch[2]=V>>1;break;
+    }
+    S74LS374NSynco();
   }
-  S74LS374NSynco();
- }
 }
 
-static void S74LS374NReset(void)
+static void S74LS374NPower(void)
 {
- latch[0]=latch[2]=0;
- latch[1]=3;
- S74LS374NSynco();
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite);
+   latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0;
+   S74LS374NSynco();
+   SetReadHandler(0x8000,0xFFFF,CartBR);
+   SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite);
 }
 
 static void S74LS374NRestore(int version)
 {
- S74LS374NSynco();
  S74LS374NSynco();
 }
 
-void S74LS374N_Init(void)
+void S74LS374N_Init(CartInfo *info)
 {
BoardPower=S74LS374NReset;
- GameStateRestore=S74LS374NRestore;
AddExState(latch, 3, 0, "LATC");
- AddExState(&cmd, 1, 0, "CMD");
 info->Power=S74LS374NPower;
 GameStateRestore=S74LS374NRestore;
 AddExState(latch, 5, 0, "LATC");
 AddExState(&cmd, 1, 0, "CMD");
 }
 
-static int type;
-static void S8259Synco(void)
+static void S74LS374NASynco(void)
 {
int x;
-
setprg32(0x8000,latch[5]&7);
- X6502_Rebase();
 setprg32(0x8000,latch[0]);
+  setchr8(latch[1]);
 MSync(latch[2]);
+}
 
- if(!UNIFchrrama)      // No CHR RAM?  Then BS'ing is ok.
- {
-  if(!type)
+static DECLFW(S74LS374NAWrite)
+{
+  A&=0x4101;
+  if(A==0x4100)
+    cmd=V&7;
+  else
   {
-   for(x=0;x<4;x++)
-    setchr2(0x800*x,(x&1)|((latch[x]&7)<<1)|((latch[4]&7)<<4));
+    switch(cmd)
+    {
+      case 0:latch[0]=0;latch[1]=3;break;
+      case 2:latch[3]=(V&1)<<3;break;
+      case 4:latch[1]=(latch[1]&6)|(V&3);break;
+      case 5:latch[0]=V&1;break;
+      case 6:latch[1]=(latch[1]&1)|latch[3]|((V&3)<<1);break;
+      case 7:latch[2]=V&1;break;
+    }
+    S74LS374NSynco();
   }
-  else
+}
+
+static void S74LS374NAPower(void)
+{
+   latch[0]=latch[2]=latch[3]=latch[4]=0;
+   latch[1]=3;
+   S74LS374NASynco();
+   SetReadHandler(0x8000,0xFFFF,CartBR);
+   SetWriteHandler(0x4100,0x7FFF,S74LS374NAWrite);
+}
+
+void S74LS374NA_Init(CartInfo *info)
+{
+  info->Power=S74LS374NAPower;
+  GameStateRestore=S74LS374NRestore;
+  AddExState(latch, 5, 0, "LATC");
+  AddExState(&cmd, 1, 0, "CMD");
+}
+
+static int type;
+//static int PPUbus;
+static void S8259Synco(void)
+{
+  int x;
+  setprg32(0x8000,latch[5]&7);
+
+  if(!UNIFchrrama)        // No CHR RAM?  Then BS'ing is ok.
   {
-   for(x=0;x<4;x++)
-    setchr2(0x800*x,(latch[x]&0x7)|((latch[4]&7)<<3));
+    for(x=0;x<4;x++)
+    {
+      int bank;
+      if(latch[7]&1)
+        bank=(latch[0]&0x7)|((latch[4]&7)<<3);
+      else
+        bank=(latch[x]&0x7)|((latch[4]&7)<<3);
+      switch (type)
+      {
+        case 00: bank=(bank<<1)|(x&1); setchr2(0x800*x,bank); break;
+        case 01: setchr2(0x800*x,bank); break;
+        case 02: bank=(bank<<2)|(x&3); setchr2(0x800*x,bank); break;
+        case 03: bank=latch[x]&7;
+                 switch (x&3)
+                 {
+                   case 01: bank|=(latch[4]&1)<<4;break;
+                   case 02: bank|=(latch[4]&2)<<3;break;
+                   case 03: bank|=((latch[4]&4)<<2)|((latch[6]&1)<<3);break;
+                 }
+                 setchr1(0x400*x,bank);
+                 setchr4(0x1000,~0);
+                 break;
+      }
+    }
   }
- }
- switch((latch[7]>>1)&3)
- {
-  case 0:setmirrorw(0,0,0,1);break;
-  case 1:setmirror(MI_H);break;
-  case 2:setmirror(MI_V);break;
-  case 3:setmirror(MI_0);break;
- }
+  MSync(latch[7]>>1);
 }
 
 static DECLFW(S8259Write)
 {
- A&=0x4101;
- if(A==0x4100) cmd=V;
- else
- {
-  latch[cmd&7]=V;
-  S8259Synco();
- }
+  A&=0x4101;
+  if(A==0x4100)
+    cmd=V;
+  else
+  {
+    latch[cmd&7]=V;
+    S8259Synco();
+  }
 }
 
 static void S8259Reset(void)
 {
- int x;
- cmd=0;
 int x;
 cmd=0;
 
- for(x=0;x<8;x++) latch[x]=0;
if(UNIFchrrama) setchr8(0);
 for(x=0;x<8;x++) latch[x]=0;
+  setchr8(0);
 
- S8259Synco();
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x4100,0x7FFF,S8259Write);
 S8259Synco();
 SetReadHandler(0x8000,0xFFFF,CartBR);
 SetWriteHandler(0x4100,0x7FFF,S8259Write);
 }
 
 static void S8259Restore(int version)
 {
- S8259Synco();
+  S8259Synco();
+}
+
+void S8259A_Init(CartInfo *info) // Kevin's Horton 141 mapper
+{
+  info->Power=S8259Reset;
+  GameStateRestore=S8259Restore;
+  AddExState(latch, 8, 0, "LATC");
+  AddExState(&cmd, 1, 0, "CMD");
+  type=0;
 }
 
-void S8259A_Init(void)
+void S8259B_Init(CartInfo *info) // Kevin's Horton 138 mapper
 {
- BoardPower=S8259Reset;
- GameStateRestore=S8259Restore;
- AddExState(latch, 8, 0, "LATC");
- AddExState(&cmd, 1, 0, "CMD");
- type=0;
+  info->Power=S8259Reset;
+  GameStateRestore=S8259Restore;
+  AddExState(latch, 8, 0, "LATC");
+  AddExState(&cmd, 1, 0, "CMD");
+  type=1;
+}
 
- //if(!CHRsize[0])
- //{
- // SetupCartCHRMapping(0,CHRRAM,8192,1);
- // AddExState(CHRRAM, 8192, 0, "CHRR");
- //}
+void S8259C_Init(CartInfo *info) // Kevin's Horton 139 mapper
+{
+  info->Power=S8259Reset;
+  GameStateRestore=S8259Restore;
+  AddExState(latch, 8, 0, "LATC");
+  AddExState(&cmd, 1, 0, "CMD");
+  type=2;
 }
 
-void S8259B_Init(void)
+void S8259D_Init(CartInfo *info) // Kevin's Horton 137 mapper
 {
BoardPower=S8259Reset;
- GameStateRestore=S8259Restore;
- AddExState(latch, 8, 0, "LATC");
- AddExState(&cmd, 1, 0, "CMD");
type=1;
 info->Power=S8259Reset;
 GameStateRestore=S8259Restore;
 AddExState(latch, 8, 0, "LATC");
 AddExState(&cmd, 1, 0, "CMD");
 type=3;
 }
 
 static void(*WSync)(void);
 
 static void SA0161MSynco()
 {
- setprg32(0x8000,(latch[0]>>3)&1);
- X6502_Rebase();
- setchr8(latch[0]&7);
+  setprg32(0x8000,(latch[0]>>3)&1);
+  setchr8(latch[0]&7);
 }
 
 static DECLFW(SAWrite)
 {
- if(A&0x100)
- {
-  latch[0]=V;
-  WSync();
- }
 if(A&0x100)
 {
+    latch[0]=V;
+    WSync();
 }
 }
 
 static void SAReset(void)
 {
- latch[0]=0;
- WSync();
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x4100,0x5FFF,SAWrite);
 latch[0]=0;
 WSync();
 SetReadHandler(0x8000,0xFFFF,CartBR);
 SetWriteHandler(0x4100,0x5FFF,SAWrite);
 }
 
-void SA0161M_Init(void)
+static void SA0161MRestore(int version)
 {
- WSync=SA0161MSynco;
- GameStateRestore=SA0161MSynco;
- BoardPower=SAReset;
- AddExState(&latch[0], 1, 0, "LATC");
+  SA0161MSynco();
+}
+
+void SA0161M_Init(CartInfo *info)
+{
+  WSync=SA0161MSynco;
+  GameStateRestore=SA0161MRestore;
+  info->Power=SAReset;
+  AddExState(&latch[0], 1, 0, "LATC");
 }
 
 static void SA72007Synco()
 {
- setprg32(0x8000,0);
- X6502_Rebase();
- setchr8(latch[0]>>7);
+  setprg32(0x8000,0);
+  setchr8(latch[0]>>7);
+}
+
+static void SA72007Restore(int version)
+{
+  SA72007Synco();
 }
 
-void SA72007_Init(void)
+void SA72007_Init(CartInfo *info)
 {
- WSync=SA72007Synco;
GameStateRestore=SA72007Synco;
BoardPower=SAReset;
- AddExState(&latch[0], 1, 0, "LATC");
 WSync=SA72007Synco;
 GameStateRestore=SA72007Restore;
 info->Power=SAReset;
 AddExState(&latch[0], 1, 0, "LATC");
 }
 
 static void SA72008Synco()
 {
- setprg32(0x8000,(latch[0]>>2)&1);
- X6502_Rebase();
- setchr8(latch[0]&3);
+  setprg32(0x8000,(latch[0]>>2)&1);
+  setchr8(latch[0]&3);
 }
 
-void SA72008_Init(void)
+static void SA72008Restore(int version)
 {
- WSync=SA72008Synco;
- GameStateRestore=SA72008Synco;
- BoardPower=SAReset;
- AddExState(&latch[0], 1, 0, "LATC");
+  SA72008Synco();
+}
+
+void SA72008_Init(CartInfo *info)
+{
+  WSync=SA72008Synco;
+  GameStateRestore=SA72008Restore;
+  info->Power=SAReset;
+  AddExState(&latch[0], 1, 0, "LATC");
 }
 
 static DECLFW(SADWrite)
 {
- latch[0]=V;
- WSync();
 latch[0]=V;
 WSync();
 }
 
 static void SADReset(void)
 {
- latch[0]=0;
- WSync();
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x8000,0xFFFF,SADWrite);
 latch[0]=0;
 WSync();
 SetReadHandler(0x8000,0xFFFF,CartBR);
 SetWriteHandler(0x8000,0xFFFF,SADWrite);
 }
 
-static void SA0036Synco()
+static void SA0037Synco()
 {
- setprg32(0x8000,0);
- X6502_Rebase();
- setchr8(latch[0]>>7);
+  setprg32(0x8000,(latch[0]>>3)&1);
+  setchr8(latch[0]&7);
 }
 
-static void SA0037Synco()
+static void SA0037Restore(int version)
 {
- setprg32(0x8000,(latch[0]>>3)&1);
- X6502_Rebase();
- setchr8(latch[0]&7);
+  SA0037Synco();
 }
 
-void SA0036_Init(void)
+void SA0036_Init(CartInfo *info)
 {
WSync=SA0036Synco;
GameStateRestore=SA0036Synco;
BoardPower=SADReset;
- AddExState(&latch[0], 1, 0, "LATC");
 WSync=SA72007Synco;
 GameStateRestore=SA72007Restore;
 info->Power=SADReset;
 AddExState(&latch[0], 1, 0, "LATC");
 }
 
-void SA0037_Init(void)
+void SA0037_Init(CartInfo *info)
 {
- WSync=SA0037Synco;
GameStateRestore=SA0037Synco;
BoardPower=SADReset;
- AddExState(&latch[0], 1, 0, "LATC");
 WSync=SA0037Synco;
 GameStateRestore=SA0037Restore;
 info->Power=SADReset;
 AddExState(&latch[0], 1, 0, "LATC");
 }
 
 static void TCU01Synco()
 {
- setprg32(0x8000,(latch[0]>>2)&1);
- X6502_Rebase();
- setchr8((latch[0]>>3)&0xF);
+  setprg32(0x8000,(latch[0]>>2)&1);
+  setchr8((latch[0]>>3)&0xF);
 }
 
 static DECLFW(TCWrite)
 {
- if((A&0x103)==0x102)
-  latch[0]=V;
- TCU01Synco();
 if((A&0x103)==0x102)
+    latch[0]=V;
 TCU01Synco();
 }
 
 static void TCU01Reset(void)
 {
- latch[0]=0;
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x4100,0xFFFF,TCWrite);
- TCU01Synco();
 latch[0]=0;
 SetReadHandler(0x8000,0xFFFF,CartBR);
 SetWriteHandler(0x4100,0xFFFF,TCWrite);
 TCU01Synco();
 }
 
-void TCU01_Init(void)
+static void TCU01Restore(int version)
 {
- GameStateRestore=TCU01Synco;
- BoardPower=TCU01Reset;
- AddExState(&latch[0], 1, 0, "LATC");
+  TCU01Synco();
 }
 
+void TCU01_Init(CartInfo *info)
+{
+  GameStateRestore=TCU01Restore;
+  info->Power=TCU01Reset;
+  AddExState(&latch[0], 1, 0, "LATC");
+}
+
+static DECLFR(TCA01Read)
+{
+  uint8 ret;
+  if((A&0x4100)==0x4100)
+    ret=(X.DB&0xC0)|((~A)&0x3F);
+  else
+    ret=X.DB;
+  return ret;
+}
+
+static void TCA01Reset(void)
+{
+  setprg16(0x8000,0);
+  setprg16(0xC000,1);
+  setchr8(0);
+  SetReadHandler(0x8000,0xFFFF,CartBR);
+  SetReadHandler(0x4100,0x5FFF,TCA01Read);
+}
+
+void TCA01_Init(CartInfo *info)
+{
+  info->Power=TCA01Reset;
+}
diff --git a/boards/simple.c b/boards/simple.c
deleted file mode 100644 (file)
index 5629a5f..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "mapinc.h"
-
-#define CHRRAM (GameMemBlock)
-static uint8 latche;
-
-DECLFW(CPROMWrite)
-{
- latche=V&3;
- setvram4(0x1000,CHRRAM+((V&3)<<12));
-}
-
-static void CPROMReset(void)
-{
- setprg32(0x8000,0);
- setvram8(0);
- SetReadHandler(0x8000,0xFFFF,CartBR);
- SetWriteHandler(0x8000,0xffff,CPROMWrite);
-}
-
-static void CPROMRestore(int version)
-{
- setvram4(0x1000,CHRRAM+((latche)<<12));
-}
-
-void CPROM_Init(void)
-{
- BoardPower=CPROMReset;
- GameStateRestore=CPROMRestore;
- AddExState(&latche, 1, 0, "LATC");
-}
-
-DECLFW(CNROMWrite)
-{
- latche=V&3;
- setchr8(V&3);
-}
-
-static void CNROMReset(void)
-{
-  setprg16(0x8000,0);
-  setprg16(0xC000,1);
-  SetReadHandler(0x8000,0xFFFF,CartBR);
-  SetWriteHandler(0x8000,0xffff,CNROMWrite);
-}
-
-static void CNROMRestore(int version)
-{
- setchr8(latche);
-}
-
-void CNROM_Init(void)
-{
- BoardPower=CNROMReset;
- GameStateRestore=CNROMRestore;
- AddExState(&latche, 1, 0, "LATC");
-}
-
-static void NROM128Reset(void)
-{
-  setprg16(0x8000,0);
-  setprg16(0xC000,0);
-  setchr8(0);
-  SetReadHandler(0x8000,0xFFFF,CartBR);
-}
-
-static void NROM256Reset(void)
-{
-  setprg16(0x8000,0);
-  setprg16(0xC000,1);
-  setchr8(0);
-  SetReadHandler(0x8000,0xFFFF,CartBR);
-}
-void NROM128_Init(void)
-{
-  BoardPower=NROM128Reset;
-}
-
-void NROM256_Init(void)
-{
-  BoardPower=NROM256Reset;
-}
-
-static DECLFW(MHROMWrite)
-{
- setprg32(0x8000,V>>4);
- setchr8(V);
- latche=V;
- X6502_Rebase();
-}
-
-static void MHROMReset(void)
-{
- setprg32(0x8000,0);
- setchr8(0);
- latche=0;
- SetReadHandler(0x8000,0xFFFF,CartBR);
-}
-
-static void MHROMRestore(int version)
-{
- setprg32(0x8000,latche);
- setchr8(latche);
- SetWriteHandler(0x8000,0xffff,MHROMWrite);
-}
-
-void MHROM_Init(void)
-{
- BoardPower=MHROMReset;
- AddExState(&latche, 1, 0,"LATC");
- PRGmask32[0]&=1;
- CHRmask8[0]&=1;
- GameStateRestore=MHROMRestore;
-}
-
-static void UNROMRestore(int version)
-{
- setprg16(0x8000,latche);
-}
-
-static DECLFW(UNROMWrite)
-{
- setprg16(0x8000,V);
- latche=V;
- X6502_Rebase();
-}
-
-static void UNROMReset(void)
-{
- setprg16(0x8000,0);
- setprg16(0xc000,~0);
- setvram8(CHRRAM);
- SetWriteHandler(0x8000,0xffff,UNROMWrite);
- SetReadHandler(0x8000,0xFFFF,CartBR);
- latche=0;
-}
-
-void UNROM_Init(void)
-{
- BoardPower=UNROMReset;
- PRGmask16[0]&=7;
- AddExState(&latche, 1, 0, "LATC");
- AddExState(CHRRAM, 8192, 0, "CHRR");
- GameStateRestore=UNROMRestore;
-}
diff --git a/boards/subor.c b/boards/subor.c
new file mode 100644 (file)
index 0000000..31e5b65
--- /dev/null
@@ -0,0 +1,79 @@
+#include "mapinc.h"\r
+\r
+static uint8 mode;\r
+static uint8 DRegs[4];\r
+\r
+static SFORMAT StateRegs[]=\r
+{\r
+ {DRegs, 4, "DREG"},\r
+ {0}\r
+};\r
+\r
+static void Sync(void)\r
+{\r
+ int base, bank;\r
+ base = ((DRegs[0]^DRegs[1])&0x10)<<1;\r
+ bank = (DRegs[2]^DRegs[3])&0x1f;\r
+\r
+ if(DRegs[1]&0x08)\r
+ {\r
+   bank &= 0xfe;\r
+   if(mode==0)\r
+   {\r
+     setprg16(0x8000,base+bank+1);\r
+     setprg16(0xC000,base+bank+0);\r
+   }\r
+   else\r
+   {\r
+     setprg16(0x8000,base+bank+0);\r
+     setprg16(0xC000,base+bank+1);\r
+   }\r
+ }\r
+ else\r
+ {\r
+   if(DRegs[1]&0x04)\r
+   {\r
+     setprg16(0x8000,0x1f);\r
+     setprg16(0xC000,base+bank);\r
+   }\r
+   else\r
+   {\r
+     setprg16(0x8000,base+bank);\r
+     if(mode==0)\r
+        setprg16(0xC000,0x20);\r
+     else\r
+        setprg16(0xC000,0x07);\r
+   }\r
+ }\r
+}\r
+\r
+static DECLFW(Mapper167_write)\r
+{\r
+ DRegs[(A>>13)&0x03]=V;\r
+ Sync();\r
+}\r
+\r
+static void StateRestore(int version)\r
+{\r
+ Sync();\r
+}\r
+\r
+void Mapper166_init(void)\r
+{\r
+ mode=1;\r
+ DRegs[0]=DRegs[1]=DRegs[2]=DRegs[3]=0;\r
+ Sync();\r
+ SetWriteHandler(0x8000,0xFFFF,Mapper167_write);\r
+ GameStateRestore=StateRestore;\r
+ AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
+\r
+void Mapper167_init(void)\r
+{\r
+ mode=0;\r
+ DRegs[0]=DRegs[1]=DRegs[2]=DRegs[3]=0;\r
+ Sync();\r
+ SetWriteHandler(0x8000,0xFFFF,Mapper167_write);\r
+ GameStateRestore=StateRestore;\r
+ AddExState(&StateRegs, ~0, 0, 0);\r
+}\r
index 7cf0646..4265b5c 100644 (file)
-/* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include "mapinc.h"
-//undef printf
-
-static int32 IRQCount,IRQLatch;
-static uint8 IRQa,resetmode,mbia;
-static uint8 sizer,bigbank,bigbank2;
-
-static uint8 DRegBuf[8],MMC3_cmd;
-
-static int masko8[8]={63,31,15,1,3,0,0,0};
-//static int masko1[8]={511,255,127,7,7,0,0,0};
-
-static void swsetprg8(uint32 A, uint32 V)
-{
- V&=masko8[sizer&7];
- V|=(bigbank*2);
- setprg8r((V/64)&15,A,V);
-}
-
-static void swsetchr1(uint32 A, uint32 V)
-{
- if(sizer&0x20)
-  setchr1r(0x10,A,V);
- else
- {
-//  V&=masko1[sizer&7];
-  V|=bigbank2*8;
-  setchr1r((V/512)&15,A,V);
- }
-}
-
-static void swsetchr2(uint32 A, uint32 V)
-{
- if(sizer&0x20)
-  setchr2r(0x10,A,V);
- else
- {
-  //V&=masko1[sizer&7]>>1;
-  V|=bigbank2*4;
-  setchr2r((V/256)&15,A,V);
- }
-}
-
-static void Sup24_hb(void)
-{
-     if(ScreenON || SpriteON)
-     {
-      resetmode=0;
-      if(IRQCount>=0)
-      {
-        IRQCount--;
-        if(IRQCount<0)
-        {
-         if(IRQa)
-         {
-            resetmode = 1;
-           X6502_IRQBegin(FCEU_IQEXT);
-         }
-        }
-      }
-     }
-}
-
-static DECLFW(Sup24IRQWrite)
-{
-        switch(A&0xE001)
-        {
-         case 0xc000:IRQLatch=V;
-                     if(resetmode==1)
-                      IRQCount=IRQLatch;
-                     break;
-         case 0xc001:resetmode=1;
-                     IRQCount=IRQLatch;
-                     break;
-         case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);
-                     if(resetmode==1)
-                      {IRQCount=IRQLatch;}
-                     break;
-         case 0xE001:IRQa=1;
-                     if(resetmode==1)
-                       {IRQCount=IRQLatch;}
-                     break;
-        }
-}
-
-static INLINE void FixMMC3PRG(int V)
-{
-         swsetprg8(0xA000,DRegBuf[7]);
-         swsetprg8(0xE000,~0);
-          if(V&0x40)
-           {
-            swsetprg8(0xC000,DRegBuf[6]);
-            swsetprg8(0x8000,~1);
-           }
-          else
-           {
-            swsetprg8(0x8000,DRegBuf[6]);
-            swsetprg8(0xC000,~1);
-           }
-         X6502_Rebase();
-}
-
-static INLINE void FixMMC3CHR(int V)
-{
-           int cbase=(V&0x80)<<5;
-           swsetchr2((cbase^0x000),DRegBuf[0]>>1);
-           swsetchr2((cbase^0x800),DRegBuf[1]>>1);
-           swsetchr1(cbase^0x1000,DRegBuf[2]);
-           swsetchr1(cbase^0x1400,DRegBuf[3]);
-           swsetchr1(cbase^0x1800,DRegBuf[4]);
-           swsetchr1(cbase^0x1c00,DRegBuf[5]);
-}
-
-static DECLFW(Super24hiwrite)
-{
-       //printf("$%04x:$%02x, %d\n",A,V,scanline);
-        switch(A&0xE001)
-        {
-         case 0x8000:
-          if((V&0x40) != (MMC3_cmd&0x40))
-           FixMMC3PRG(V);
-          if((V&0x80) != (MMC3_cmd&0x80))
-           FixMMC3CHR(V);
-          MMC3_cmd = V;
-          break;
-
-        case 0x8001:
-                {
-                 int cbase=(MMC3_cmd&0x80)<<5;
-                 DRegBuf[MMC3_cmd&0x7]=V;
-                 switch(MMC3_cmd&0x07)
-                 {
-                  case 0: V>>=1;swsetchr2((cbase^0x000),V);break;
-                  case 1: V>>=1;swsetchr2((cbase^0x800),V);break;
-                  case 2: swsetchr1(cbase^0x1000,V); break;
-                  case 3: swsetchr1(cbase^0x1400,V); break;
-                  case 4: swsetchr1(cbase^0x1800,V); break;
-                  case 5: swsetchr1(cbase^0x1C00,V); break;
-                  case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V);
-                          else swsetprg8(0x8000,V);
-                          X6502_Rebase();
-                          break;
-                  case 7: swsetprg8(0xA000,V);
-                          X6502_Rebase();
-                          break;
-                 }
-                }
-                break;
-
-        case 0xA000:
-               mbia=V;
-                setmirror((V&1)^1);
-                break;
- }
-}
-
-
-DECLFW(Super24Write)
-{
- //printf("$%04x:$%02x\n",A,V);
- switch(A)
- {
-  case 0x5ff0:sizer=V;
-             FixMMC3PRG(MMC3_cmd);
-             FixMMC3CHR(MMC3_cmd);
-             break;
-  case 0x5FF1:
-             bigbank=V;
-             FixMMC3PRG(MMC3_cmd);
-             break;
-  case 0x5FF2:
-             bigbank2=V;
-             FixMMC3CHR(MMC3_cmd);
-             break;
- }
-}
-
-static void Super24Reset(void)
-{
- SetWriteHandler(0x8000,0xBFFF,Super24hiwrite);
- SetWriteHandler(0x5000,0x7FFF,Super24Write);
- SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite);
- SetReadHandler(0x8000,0xFFFF,CartBR);
- GameHBIRQHook=Sup24_hb;
- IRQCount=IRQLatch=IRQa=resetmode=0;
- sizer=0x24;
- bigbank=159;
- bigbank2=0;
-
- MMC3_cmd=0;
- DRegBuf[6]=0;
- DRegBuf[7]=1;
-
- FixMMC3PRG(0);
- FixMMC3CHR(0);
-}
-
-static void MrRestore(int version)
-{
- FixMMC3PRG(MMC3_cmd);
- FixMMC3CHR(MMC3_cmd);
- setmirror((mbia&1)^1);
-}
-
-void Super24_Init(void)
-{
- BoardPower=Super24Reset;
- SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1);
- GameStateRestore=MrRestore;
-
- AddExState(GameMemBlock, 8192, 0, "CHRR");
- AddExState(DRegBuf, 8, 0, "DREG");
- AddExState(&IRQCount, 4, 1, "IRQC");
- AddExState(&IRQLatch, 4, 1, "IQL1");
- AddExState(&IRQa, 1, 0, "IRQA");
- AddExState(&sizer, 1, 0, "SIZA");
- AddExState(&bigbank, 1, 0, "BIG1");
- AddExState(&bigbank2, 1, 0, "BIG2");
-}
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2005 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
+#include "mapinc.h"\r
+#include "mmc3.h"\r
+\r
+static uint8 *CHRRAM = NULL;\r
+static uint8 resetmode;\r
+static int masko8[8]={63,31,15,1,3,0,0,0};\r
+\r
+static void Super24PW(uint32 A, uint8 V)\r
+{\r
+ uint32 NV=V&masko8[EXPREGS[0]&7];\r
+ NV|=(EXPREGS[1]<<1);\r
+ setprg8r((NV>>6)&0xF,A,NV);\r
+}\r
+\r
+static void Super24CW(uint32 A, uint8 V)\r
+{\r
+ if(EXPREGS[0]&0x20)\r
+  setchr1r(0x10,A,V);\r
+ else\r
+ {\r
+  uint32 NV=V|(EXPREGS[2]<<3);\r
+  setchr1r((NV>>9)&0xF,A,NV);\r
+ }\r
+}\r
+\r
+static DECLFW(Super24Write)\r
+{\r
+ switch(A)\r
+ {\r
+  case 0x5FF0: EXPREGS[0]=V;\r
+               FixMMC3PRG(MMC3_cmd);\r
+               FixMMC3CHR(MMC3_cmd);\r
+               break;\r
+  case 0x5FF1: EXPREGS[1]=V;\r
+               FixMMC3PRG(MMC3_cmd);\r
+               break;\r
+  case 0x5FF2: EXPREGS[2]=V;\r
+               FixMMC3CHR(MMC3_cmd);\r
+               break;\r
+ }\r
+}\r
+\r
+static DECLFW(Super24IRQ)\r
+{\r
+  switch(A&0xE001)\r
+  {\r
+    case 0xc000: IRQLatch=V;\r
+                 if(resetmode==1)\r
+                   IRQCount=IRQLatch;\r
+                 break;\r
+    case 0xc001: resetmode=1;\r
+                 IRQCount=IRQLatch;\r
+                 break;\r
+    case 0xE000: IRQa=0;\r
+                 X6502_IRQEnd(FCEU_IQEXT);\r
+                 if(resetmode==1)\r
+                   IRQCount=IRQLatch;\r
+                 break;\r
+    case 0xE001: IRQa=1;\r
+                 if(resetmode==1)\r
+                   IRQCount=IRQLatch;\r
+                 break;\r
+  }\r
+}\r
+\r
+static void Super24HB(void)\r
+{\r
+  resetmode=0;\r
+  if(IRQCount!=0)\r
+  {\r
+    IRQCount--;\r
+    if(IRQCount==0)\r
+    {\r
+      if(IRQa)\r
+      {\r
+        resetmode=1;\r
+        X6502_IRQBegin(FCEU_IQEXT);\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+static void Super24Power(void)\r
+{\r
+ EXPREGS[0]=0x24;\r
+ EXPREGS[1]=159;\r
+ EXPREGS[2]=0;\r
+ GenMMC3Power();\r
+ SetWriteHandler(0x5000,0x7FFF,Super24Write);\r
+ SetWriteHandler(0xC000,0xFFFF,Super24IRQ);\r
+ SetReadHandler(0x8000,0xFFFF,CartBR);\r
+}\r
+\r
+static void Super24Reset(void)\r
+{\r
+ EXPREGS[0]=0x24;\r
+ EXPREGS[1]=159;\r
+ EXPREGS[2]=0;\r
+ MMC3RegReset();\r
+}\r
+\r
+static void Super24Close(void)\r
+{\r
+ if(CHRRAM)\r
+  FCEU_gfree(CHRRAM);\r
+ CHRRAM = NULL;\r
+}\r
+\r
+void Super24_Init(CartInfo *info)\r
+{\r
+ info->Power=Super24Power;\r
+ info->Reset=Super24Reset;\r
+ info->Close=Super24Close;\r
+ cwrap=Super24CW;\r
+ pwrap=Super24PW;\r
+  CHRRAM=(uint8*)FCEU_gmalloc(8192);\r
+ SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);\r
+ GameHBIRQHook=Super24HB;\r
+ AddExState(CHRRAM, 8192, 0, "CHRR");\r
+ AddExState(EXPREGS, 3, 0, "BIG2");\r
+}\r
index cb2890f..953c068 100644 (file)
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include "mapinc.h"
 
-#define CHRRAM (GameMemBlock+16)
+static uint8 cmd0, cmd1;
 
 static void DoSuper(void)
 {
- setprg8r((GameMemBlock[0]&0xC)>>2,0x6000,((GameMemBlock[0]&0x3)<<4)|0xF);
- if(GameMemBlock[0]&0x10)
+ setprg8r((cmd0&0xC)>>2,0x6000,((cmd0&0x3)<<4)|0xF);
+ if(cmd0&0x10)
  {
-  setprg16r((GameMemBlock[0]&0xC)>>2,0x8000,((GameMemBlock[0]&0x3)<<3)|(GameMemBlock[1]&7));
-  setprg16r((GameMemBlock[0]&0xC)>>2,0xc000,((GameMemBlock[0]&0x3)<<3)|7);
+  setprg16r((cmd0&0xC)>>2,0x8000,((cmd0&0x3)<<3)|(cmd1&7));
+  setprg16r((cmd0&0xC)>>2,0xc000,((cmd0&0x3)<<3)|7);
  }
  else
   setprg32r(4,0x8000,0);
-
- setmirror(((GameMemBlock[0]&0x20)>>5)^1);
- X6502_Rebase();
+ setmirror(((cmd0&0x20)>>5)^1);
 }
 
 static DECLFW(SuperWrite)
 {
- if(!(GameMemBlock[0]&0x10))
+ if(!(cmd0&0x10))
  {
-  GameMemBlock[0]=V;
+  cmd0=V;
   DoSuper();
  }
 }
 
 static DECLFW(SuperHi)
 {
GameMemBlock[1]=V;
cmd1=V;
  DoSuper();
 }
 
@@ -56,10 +54,10 @@ static void SuperReset(void)
 {
   SetWriteHandler(0x6000,0x7FFF,SuperWrite);
   SetWriteHandler(0x8000,0xFFFF,SuperHi);
-  SetReadHandler(0x6000,0xFFFF,CartBR);
-  GameMemBlock[0]=GameMemBlock[1]=0;
+  SetReadHandler(0x6000,0xFFFF,CartBR);  
+  cmd0=cmd1=0;
   setprg32r(4,0x8000,0);
-  setvram8(CHRRAM);
+  setchr8(0);
 }
 
 static void SuperRestore(int version)
@@ -67,11 +65,10 @@ static void SuperRestore(int version)
  DoSuper();
 }
 
-void Supervision16_Init(void)
+void Supervision16_Init(CartInfo *info)
 {
-  AddExState(&GameMemBlock[0], 1, 0,"L1");
-  AddExState(&GameMemBlock[1], 1, 0,"L2");
-  AddExState(CHRRAM, 8192, 0, "CHRR");
-  BoardPower=SuperReset;
+  AddExState(&cmd0, 1, 0,"L1");
+  AddExState(&cmd1, 1, 0,"L2");
+  info->Power=SuperReset;
   GameStateRestore=SuperRestore;
 }
diff --git a/boards/tengen.c b/boards/tengen.c
new file mode 100644 (file)
index 0000000..84f050a
--- /dev/null
@@ -0,0 +1,198 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ *  Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd,mir,rmode,IRQmode;
+static uint8 DRegs[11];
+static uint8 IRQCount,IRQa,IRQLatch;
+
+static SFORMAT Rambo_StateRegs[]={
+        {&cmd, 1, "CMD"},
+        {&mir, 1, "MIR"},
+        {&rmode, 1, "RMOD"},
+        {&IRQmode, 1, "IRQM"},
+        {&IRQCount, 1, "IRQC"},
+        {&IRQa, 1, "IRQA"},
+        {&IRQLatch, 1, "IRQL"},
+        {DRegs, 11, "DREG"},
+        {0}
+};
+
+static void FP_FASTAPASS(2) (*setchr1wrap)(unsigned int A, unsigned int V);
+static int nomirror;
+
+static void FP_FASTAPASS(1) RAMBO1_IRQHook(int a)
+{
+ static int smallcount;
+ if(!IRQmode) return;
+
+ smallcount+=a;
+ while(smallcount>=4)
+ {
+  smallcount-=4;
+  IRQCount--;
+  if(IRQCount==0xFF)
+      if(IRQa) X6502_IRQBegin(FCEU_IQEXT);
+ }
+}
+
+static void RAMBO1_hb(void)
+{
+      if(IRQmode) return;
+  if(scanline==240) return;        /* hmm.  Maybe that should be an mmc3-only call in fce.c. */
+      rmode=0;
+      IRQCount--;
+      if(IRQCount==0xFF)
+      {
+       if(IRQa)
+       {
+        rmode = 1;
+        X6502_IRQBegin(FCEU_IQEXT);
+       }
+      }
+}
+
+static void Synco(void)
+{
+ int x;
+
+ if(cmd&0x20)
+ {
+  setchr1wrap(0x0000,DRegs[0]);
+  setchr1wrap(0x0800,DRegs[1]);
+  setchr1wrap(0x0400,DRegs[8]);
+  setchr1wrap(0x0c00,DRegs[9]);
+ }
+ else
+ {
+  setchr1wrap(0x0000,(DRegs[0]&0xFE));
+  setchr1wrap(0x0400,(DRegs[0]&0xFE)|1);
+  setchr1wrap(0x0800,(DRegs[1]&0xFE));
+  setchr1wrap(0x0C00,(DRegs[1]&0xFE)|1);
+ }
+
+ for(x=0;x<4;x++)
+  setchr1wrap(0x1000+x*0x400,DRegs[2+x]);
+
+ setprg8(0x8000,DRegs[6]);
+ setprg8(0xA000,DRegs[7]);
+
+ setprg8(0xC000,DRegs[10]);
+}
+
+
+static DECLFW(RAMBO1_write)
+{
+ switch(A&0xF001)
+  {
+    case 0xa000: mir=V&1;
+                 if(!nomirror)
+                   setmirror(mir^1);
+                 break;
+    case 0x8000: cmd = V;
+                 break;
+    case 0x8001: if((cmd&0xF)<10)
+                     DRegs[cmd&0xF]=V;
+                    else if((cmd&0xF)==0xF)
+                     DRegs[10]=V;
+                    Synco();
+                    break;
+    case 0xc000: IRQLatch=V;
+                 if(rmode==1)
+                   IRQCount=IRQLatch;
+                 break;
+    case 0xc001: rmode=1;
+                    IRQCount=IRQLatch;
+                    IRQmode=V&1;
+                    break;
+    case 0xE000: IRQa=0;
+                 X6502_IRQEnd(FCEU_IQEXT);
+                 if(rmode==1)
+                   IRQCount=IRQLatch;
+                 break;
+    case 0xE001: IRQa=1;
+                 if(rmode==1)
+                   IRQCount=IRQLatch;
+                    break;
+  }
+}
+
+static void RAMBO1_Restore(int version)
+{
+ Synco();
+ if(!nomirror)
+  setmirror(mir^1);
+}
+
+static void RAMBO1_init(void)
+{
+        int x;
+        for(x=0;x<11;x++)
+         DRegs[x]=~0;
+  cmd=mir=0;
+        if(!nomirror)
+         setmirror(1);
+        Synco();
+        GameHBIRQHook=RAMBO1_hb;
+        MapIRQHook=RAMBO1_IRQHook;
+        GameStateRestore=RAMBO1_Restore;
+        SetWriteHandler(0x8000,0xffff,RAMBO1_write);
+        AddExState(Rambo_StateRegs, ~0, 0, 0);
+}
+
+static void FP_FASTAPASS(2) CHRWrap(unsigned int A, unsigned int V)
+{
+ setchr1(A,V);
+}
+
+void Mapper64_init(void)
+{
+        setchr1wrap=CHRWrap;
+        nomirror=0;
+        RAMBO1_init();
+}
+
+static int MirCache[8];
+static unsigned int PPUCHRBus;
+
+static void FP_FASTAPASS(2) MirWrap(unsigned int A, unsigned int V)
+{
+ MirCache[A>>10]=(V>>7)&1;
+ if(PPUCHRBus==(A>>10))
+  setmirror(MI_0+((V>>7)&1));
+ setchr1(A,V);
+}
+
+static void FP_FASTAPASS(1) MirrorFear(uint32 A)
+{
+ A&=0x1FFF;
+ A>>=10;
+ PPUCHRBus=A;
+ setmirror(MI_0+MirCache[A]);
+}
+
+void Mapper158_init(void)
+{
+        setchr1wrap=MirWrap;
+        PPU_hook=MirrorFear;
+        nomirror=1;
+        RAMBO1_init();
+}
diff --git a/cart.c b/cart.c
index 6a32021..f888397 100644 (file)
--- a/cart.c
+++ b/cart.c
@@ -1,7 +1,7 @@
 /* FCE Ultra - NES/Famicom Emulator
  *
  * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
+ *  Copyright (C) 2002 Xodnizel
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <string.h>
 #include <stdlib.h>
-#include <stdio.h>     /* For GG loading code. */
+#include <stdio.h>
 
 #include "types.h"
-#include "version.h"
 #include "fce.h"
+#include "ppu.h"
+
 #include "cart.h"
 #include "memory.h"
+#include "x6502.h"
 
 #include "general.h"
+
 #include "svga.h"
+#include "file.h"
+
+#define FCEUPPU_LineUpdate(...)
 
 /*
    This file contains all code for coordinating the mapping in of the
@@ -43,8 +49,9 @@ uint8 *VPageG[8];
 uint8 *MMC5SPRVPage[8];
 uint8 *MMC5BGVPage[8];
 
-/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
+static uint8 PRGIsRAM[32];  /* This page is/is not PRG RAM. */
 
+/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
 static int CHRram[32];
 static int PRGram[32];
 
@@ -74,29 +81,39 @@ uint8 geniech[3];
 
 uint32 genieaddr[3];
 
-static INLINE void setpageptr(int s, uint32 A, uint8 *p)
+static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram)
 {
  uint32 AB=A>>11;
  int x;
 
- for(x=(s>>1)-1;x>=0;x--)
-  Page[AB+x]=p-A;
+ if(p)
+  for(x=(s>>1)-1;x>=0;x--)
+  {
+   PRGIsRAM[AB+x]=ram;
+   Page[AB+x]=p-A;
+  }
+ else
+  for(x=(s>>1)-1;x>=0;x--)
+  {
+   PRGIsRAM[AB+x]=0;
+   Page[AB+x]=0;
+  }
 }
 
-static char nothing[8192];
+static uint8 nothing[8192];
 void ResetCartMapping(void)
 {
  int x;
 
  for(x=0;x<32;x++)
  {
-  Page[x]=(uint8 *)(nothing-x*2048);
+  Page[x]=nothing-x*2048;
   PRGptr[x]=CHRptr[x]=0;
   PRGsize[x]=CHRsize[x]=0;
  }
  for(x=0;x<8;x++)
  {
-  MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=(uint8 *)(nothing-0x400*x);
+  MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x;
  }
 
 }
@@ -133,12 +150,23 @@ DECLFR(CartBR)
  return Page[A>>11][A];
 }
 
-void FASTAPASS(3) GINLINE setprg2r(int r, unsigned int A, unsigned int V)
+DECLFW(CartBW)
 {
-  if(!PRGptr[r]) return;
-  V&=PRGmask2[r];
+ //printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]);
+ if(PRGIsRAM[A>>11] && Page[A>>11])
+  Page[A>>11][A]=V;
+}
+
+DECLFR(CartBROB)
+{
+ if(!Page[A>>11]) return(X.DB);
+ return Page[A>>11][A];
+}
 
-  setpageptr(2,A,(&PRGptr[r][V<<11]));
+void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V)
+{
+  V&=PRGmask2[r];
+  setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]);
 }
 
 void FASTAPASS(2) setprg2(uint32 A, uint32 V)
@@ -146,11 +174,10 @@ void FASTAPASS(2) setprg2(uint32 A, uint32 V)
  setprg2r(0,A,V);
 }
 
-void FASTAPASS(3) GINLINE setprg4r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
 {
-  if(!PRGptr[r]) return;
   V&=PRGmask4[r];
-  setpageptr(4,A,(&PRGptr[r][V<<12]));
+  setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
 }
 
 void FASTAPASS(2) setprg4(uint32 A, uint32 V)
@@ -158,21 +185,19 @@ void FASTAPASS(2) setprg4(uint32 A, uint32 V)
  setprg4r(0,A,V);
 }
 
-void FASTAPASS(3) GINLINE setprg8r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
 {
-  if(!PRGptr[r]) return;
-
   if(PRGsize[r]>=8192)
   {
    V&=PRGmask8[r];
-   setpageptr(8,A,(&PRGptr[r][V<<13]));
+   setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
   }
   else
   {
    uint32 VA=V<<2;
    int x;
    for(x=0;x<4;x++)
-    setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
+    setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
   }
 }
 
@@ -181,14 +206,12 @@ void FASTAPASS(2) setprg8(uint32 A, uint32 V)
  setprg8r(0,A,V);
 }
 
-void FASTAPASS(3) GINLINE setprg16r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
 {
-  if(!PRGptr[r]) return;
-
   if(PRGsize[r]>=16384)
   {
    V&=PRGmask16[r];
-   setpageptr(16,A,(&PRGptr[r][V<<14]));
+   setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
   }
   else
   {
@@ -196,7 +219,7 @@ void FASTAPASS(3) GINLINE setprg16r(int r, unsigned int A, unsigned int V)
    int x;
 
    for(x=0;x<8;x++)
-    setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
+    setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
   }
 }
 
@@ -205,13 +228,12 @@ void FASTAPASS(2) setprg16(uint32 A, uint32 V)
  setprg16r(0,A,V);
 }
 
-void FASTAPASS(3) GINLINE setprg32r(int r,unsigned int A, unsigned int V)
+void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
 {
-  if(!PRGptr[r]) return;
   if(PRGsize[r]>=32768)
   {
    V&=PRGmask32[r];
-   setpageptr(32,A,(&PRGptr[r][V<<15]));
+   setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
   }
   else
   {
@@ -219,7 +241,7 @@ void FASTAPASS(3) GINLINE setprg32r(int r,unsigned int A, unsigned int V)
    int x;
 
    for(x=0;x<16;x++)
-    setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]));
+    setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
   }
 }
 
@@ -228,9 +250,10 @@ void FASTAPASS(2) setprg32(uint32 A, uint32 V)
  setprg32r(0,A,V);
 }
 
-void GINLINE FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
 {
   if(!CHRptr[r]) return;
+  FCEUPPU_LineUpdate();
   V&=CHRmask1[r];
   if(CHRram[r])
    PPUCHRRAM|=(1<<(A>>10));
@@ -239,9 +262,10 @@ void GINLINE FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
   VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
 }
 
-void GINLINE FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
 {
   if(!CHRptr[r]) return;
+  FCEUPPU_LineUpdate();
   V&=CHRmask2[r];
   VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
   if(CHRram[r])
@@ -250,9 +274,10 @@ void GINLINE FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
    PPUCHRRAM&=~(3<<(A>>10));
 }
 
-void GINLINE FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
+void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
 {
   if(!CHRptr[r]) return;
+  FCEUPPU_LineUpdate();
   V&=CHRmask4[r];
   VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
   VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
@@ -262,11 +287,12 @@ void GINLINE FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
    PPUCHRRAM&=~(15<<(A>>10));
 }
 
-void GINLINE FASTAPASS(2) setchr8r(int r, unsigned int V)
+void FASTAPASS(2) setchr8r(int r, unsigned int V)
 {
   int x;
 
   if(!CHRptr[r]) return;
+  FCEUPPU_LineUpdate();
   V&=CHRmask8[r];
   for(x=7;x>=0;x--)
    VPageR[x]=&CHRptr[r][V<<13];
@@ -291,7 +317,7 @@ void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
  setchr4r(0,A,V);
 }
 
-void FASTAPASS(2) setchr8(unsigned int V)
+void FASTAPASS(1) setchr8(unsigned int V)
 {
  setchr8r(0,V);
 }
@@ -314,12 +340,14 @@ void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
 
 void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
 {
+  FCEUPPU_LineUpdate();
   VPageR[A>>10]=p-A+(b<<10);
   PPUCHRRAM|=(1<<(A>>10));
 }
 
 void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
 {
+  FCEUPPU_LineUpdate();
   VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
   PPUCHRRAM|=(3<<(A>>10));
 }
@@ -328,6 +356,7 @@ void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
 {
   int x;
 
+  FCEUPPU_LineUpdate();
   for(x=3;x>=0;x--)
    VPageR[(A>>10)+x]=p-A+(b<<12);
   PPUCHRRAM|=(15<<(A>>10));
@@ -337,6 +366,7 @@ void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
 {
   int x;
 
+  FCEUPPU_LineUpdate();
   for(x=7;x>=0;x--)
    VPageR[x]=p+(b<<13);
   PPUCHRRAM|=255;
@@ -346,6 +376,7 @@ void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
 
 void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
 {
+ FCEUPPU_LineUpdate();
  vnapage[b]=p;
  PPUNTARAM&=~(1<<b);
  if(ram)
@@ -355,6 +386,7 @@ void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
 static int mirrorhard=0;
 void setmirrorw(int a, int b, int c, int d)
 {
+ FCEUPPU_LineUpdate();
  vnapage[0]=NTARAM+a*0x400;
  vnapage[1]=NTARAM+b*0x400;
  vnapage[2]=NTARAM+c*0x400;
@@ -363,6 +395,7 @@ void setmirrorw(int a, int b, int c, int d)
 
 void FASTAPASS(1) setmirror(int t)
 {
+  FCEUPPU_LineUpdate();
   if(!mirrorhard)
   {
    switch(t)
@@ -387,7 +420,10 @@ void FASTAPASS(1) setmirror(int t)
 void SetupCartMirroring(int m, int hard, uint8 *extra)
 {
  if(m<4)
+ {
+  mirrorhard = 0;
   setmirror(m);
+ }
  else
  {
   vnapage[0]=NTARAM;
@@ -411,9 +447,13 @@ void OpenGenie(void)
 
  if(!GENIEROM)
  {
-  if(!(GENIEROM=FCEU_malloc(4096+1024))) return;
+  char *fn;
+
+  if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
 
-  if(!(fp=fopen(FCEU_MakeFName(FCEUMKF_GGROM,0,0),"rb")))
+  fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
+  fp=fopen(fn,"rb");
+  if(!fp)
   {
    FCEU_PrintError("Error opening Game Genie ROM image!");
    free(GENIEROM);
@@ -429,7 +469,7 @@ void OpenGenie(void)
    fclose(fp);
    return;
   }
-  if(GENIEROM[0]==0x4E)        /* iNES ROM image */
+  if(GENIEROM[0]==0x4E)  /* iNES ROM image */
   {
    if(fread(GENIEROM,1,4096,fp)!=4096)
     goto grerr;
@@ -462,6 +502,15 @@ void CloseGenie(void)
  VPageR=VPage;
 }
 
+void FCEU_KillGenie(void)
+{
+ if(GENIEROM)
+ {
+  free(GENIEROM);
+  GENIEROM=0;
+ }
+}
+
 static DECLFR(GenieRead)
 {
  return GENIEROM[A&4095];
@@ -488,14 +537,14 @@ static DECLFW(GenieWrite)
   case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
 
   case 0x8000:if(!V)
-               FixGenieMap();
-              else
-              {
-               modcon=V^0xFF;
-               if(V==0x71)
-               modcon=0;
-              }
-              break;
+         FixGenieMap();
+        else
+        {
+         modcon=V^0xFF;
+         if(V==0x71)
+    modcon=0;
+        }
+        break;
  }
 }
 
@@ -505,7 +554,7 @@ static DECLFR(GenieFix1)
 {
  uint8 r=GenieBackup[0](A);
 
- if((modcon>>1)&1)             // No check
+ if((modcon>>1)&1)    // No check
   return genieval[0];
  else if(r==geniech[0])
   return genieval[0];
@@ -517,7 +566,7 @@ static DECLFR(GenieFix2)
 {
  uint8 r=GenieBackup[1](A);
 
- if((modcon>>2)&1)              // No check
+ if((modcon>>2)&1)        // No check
   return genieval[1];
  else if(r==geniech[1])
   return genieval[1];
@@ -529,7 +578,7 @@ static DECLFR(GenieFix3)
 {
  uint8 r=GenieBackup[2](A);
 
- if((modcon>>3)&1)              // No check
+ if((modcon>>3)&1)        // No check
   return genieval[2];
  else if(r==geniech[2])
   return genieval[2];
@@ -549,7 +598,7 @@ void FixGenieMap(void)
 
  VPageR=VPage;
  FlushGenieRW();
-
+ //printf("Rightyo\n");
  for(x=0;x<3;x++)
   if((modcon>>(4+x))&1)
   {
@@ -588,3 +637,54 @@ void GeniePower(void)
 }
 
 
+void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
+{
+ if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
+ {
+  FILE *sp;
+  char *soot;
+
+  soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
+  if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
+  {
+   FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
+  }
+  else
+  {
+   int x;
+
+   for(x=0;x<4;x++)
+    if(LocalHWInfo->SaveGame[x])
+    {
+     fwrite(LocalHWInfo->SaveGame[x],1,
+      LocalHWInfo->SaveGameLen[x],sp);
+    }
+  }
+  free(soot);
+ }
+}
+
+// hack, movie.c has to communicate with this function somehow
+int disableBatteryLoading=0;
+
+void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
+{
+ if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
+ {
+  FILE *sp;
+  char *soot;
+
+  soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
+  sp=FCEUD_UTF8fopen(soot,"rb");
+  if(sp!=NULL)
+  {
+   int x;
+   for(x=0;x<4;x++)
+    if(LocalHWInfo->SaveGame[x])
+     fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);
+  }
+  free(soot);
+ }
+}
+
+
diff --git a/cart.h b/cart.h
index 2a91681..140c54e 100644 (file)
--- a/cart.h
+++ b/cart.h
@@ -1,3 +1,32 @@
+#ifndef _CART_H
+#define _CART_H
+
+typedef struct {
+  /* Set by mapper/board code: */
+  void (*Power)(void);
+  void (*Reset)(void);
+  void (*Close)(void);
+  uint8 *SaveGame[4];     /* Pointers to memory to save/load. */
+  uint32 SaveGameLen[4];  /* How much memory to save/load. */
+
+  /* Set by iNES/UNIF loading code. */
+  int mirror;    /* As set in the header or chunk.
+           iNES/UNIF specific.  Intended
+           to help support games like "Karnov"
+           that are not really MMC3 but are
+           set to mapper 4.
+        */
+  int battery;      /* Presence of an actual battery. */
+  uint8 MD5[16];
+  uint32 CRC32;     /* Should be set by the iNES/UNIF loading
+           code, used by mapper/board code, maybe
+           other code in the future.
+        */
+} CartInfo;
+
+void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
+void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
+
 extern uint8 *Page[32],*VPage[8],*MMC5SPRVPage[8],*MMC5BGVPage[8];
 
 void ResetCartMapping(void);
@@ -5,7 +34,9 @@ void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram);
 void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram);
 void SetupCartMirroring(int m, int hard, uint8 *extra);
 
+DECLFR(CartBROB);
 DECLFR(CartBR);
+DECLFW(CartBW);
 
 extern uint8 *PRGptr[32];
 extern uint8 *CHRptr[32];
@@ -44,7 +75,7 @@ void FASTAPASS(2) setchr8r(int r, unsigned int V);
 void FASTAPASS(2) setchr1(unsigned int A, unsigned int V);
 void FASTAPASS(2) setchr2(unsigned int A, unsigned int V);
 void FASTAPASS(2) setchr4(unsigned int A, unsigned int V);
-void FASTAPASS(2) setchr8(unsigned int V);
+void FASTAPASS(1) setchr8(unsigned int V);
 
 void FASTAPASS(2) setvram4(uint32 A, uint8 *p);
 void FASTAPASS(1) setvram8(uint8 *p);
@@ -69,3 +100,7 @@ void GeniePower(void);
 
 void OpenGenie(void);
 void CloseGenie(void);
+void FCEU_KillGenie(void);
+
+#endif // ndef _CART_H
+
index cfaf2cf..aa6a2c7 100644 (file)
--- a/driver.h
+++ b/driver.h
@@ -59,18 +59,34 @@ void FCEUI_DisableFourScore(int s);
 
 #include "version.h"
 
-#define SI_NONE     0
-#define SI_GAMEPAD  1
-#define SI_ZAPPER   2
-#define SI_POWERPAD 3
-#define SI_ARKANOID 4
-
-#define SIFC_NONE      0
-#define SIFC_ARKANOID  1
-#define SIFC_SHADOW    2
+#define SI_NONE      0
+#define SI_GAMEPAD   1
+#define SI_ZAPPER    2
+#define SI_POWERPADA  3
+#define SI_POWERPADB  4
+#define SI_ARKANOID   5
+
+#define SIFC_NONE      0
+#define SIFC_ARKANOID  1
+#define SIFC_SHADOW      2
 #define SIFC_4PLAYER    3
-#define SIFC_FKB       4
-#define SIFC_OEKA      5
+#define SIFC_FKB      4
+#define SIFC_SUBORKB    5
+#define SIFC_HYPERSHOT  6
+#define SIFC_MAHJONG  7
+#define SIFC_QUIZKING  8
+#define SIFC_FTRAINERA  9
+#define SIFC_FTRAINERB  10
+#define SIFC_OEKAKIDS  11
+#define SIFC_BWORLD      12
+#define SIFC_TOPRIDER  13
+
+#define SIS_NONE  0
+#define SIS_DATACH  1
+#define SIS_NWC    2
+#define SIS_VSUNISYSTEM  3
+#define SIS_NSF    4
+
 
 /* New interface functions */
 
index ad36e01..95ed4bd 100644 (file)
@@ -193,7 +193,7 @@ static void DoArgs(int argc, char *argv[])
 {
         static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"};
         static int cortabi[5]={SI_NONE,SI_GAMEPAD,
-                               SI_ZAPPER,SI_POWERPAD,SI_ARKANOID};
+                               SI_ZAPPER,SI_POWERPADA,SI_ARKANOID};
        static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"};
        static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
                                 SIFC_4PLAYER,SIFC_FKB};
diff --git a/fce.c b/fce.c
index 53abd93..e36a86c 100644 (file)
--- a/fce.c
+++ b/fce.c
@@ -97,7 +97,7 @@ void (*GameInterface)(int h);
 void FP_FASTAPASS(1) (*PPU_hook)(uint32 A);
 
 void (*GameStateRestore)(int version);
-void (*GameHBIRQHook)(void);
+void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
 
 readfunc ARead[0x10000];
 writefunc BWrite[0x10000];
@@ -973,6 +973,8 @@ static void DoHBlank(void)
   Fixit2();
   X6502_Run(85-6-16);
  }
+ if(GameHBIRQHook2 && (ScreenON || SpriteON))
+  GameHBIRQHook2();
  //PPU_hook(0,-1);
  //fprintf(stderr,"%3d: $%04x\n",scanline,RefreshAddr);
  scanline++;
@@ -1044,7 +1046,7 @@ void ResetGameLoaded(void)
         if(GameLoaded) CloseGame();
         GameStateRestore=0;
         PPU_hook=0;
-        GameHBIRQHook=0;
+        GameHBIRQHook=GameHBIRQHook2=0;
        GameExpSound.Fill=0;
        GameExpSound.RChange=0;
         if(GameExpSound.Kill)
@@ -1063,6 +1065,10 @@ void ResetGameLoaded(void)
 }
 
 char lastLoadedGameName [2048];
+int UNIFLoad(const char *name, int fp);
+int iNESLoad(const char *name, int fp);
+int FDSLoad(const char *name, int fp);
+int NSFLoad(int fp);
 
 FCEUGI *FCEUI_LoadGame(char *name)
 {
@@ -1255,8 +1261,12 @@ void EmLoop(void)
   X6502_Run(256);
   {
    if(ScreenON || SpriteON)
+   {
     if(GameHBIRQHook)
      GameHBIRQHook();
+    if(GameHBIRQHook2)
+     GameHBIRQHook2();
+   }
 
    X6502_Run(85-16);
 
diff --git a/fce.h b/fce.h
index 8734f4c..04d050a 100644 (file)
--- a/fce.h
+++ b/fce.h
@@ -5,6 +5,8 @@ void asmcpu_unpack(void);
 void asmcpu_pack(void);
 #endif
 
+#define fceuindbg 0
+
 extern int GameLoaded;
 void ResetGameLoaded(void);
 
@@ -72,7 +74,7 @@ extern writefunc BWrite[0x10000];
 
 extern void (*GameInterface)(int h);
 extern void FP_FASTAPASS(1) (*PPU_hook)(uint32 A);
-extern void (*GameHBIRQHook)(void);
+extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
 extern void (*GameStateRestore)(int version);
 
 #define GI_RESETM2     1
@@ -83,6 +85,9 @@ extern void (*GameStateRestore)(int version);
 extern FCEUGI FCEUGameInfo;
 extern int GameAttributes;
 
+extern uint8 pale;
+extern uint8 vsdip;
+
 
 #endif
 
diff --git a/fds.c b/fds.c
index 455acc5..f0640a0 100644 (file)
--- a/fds.c
+++ b/fds.c
-/* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 2002 Ben Parnell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "types.h"
-#include "x6502.h"
-#include "version.h"
-#include "fce.h"
-#include "fds.h"
-#include "svga.h"
-#include "sound.h"
-#include "general.h"
-#include "state.h"
-#include "file.h"
-#include "memory.h"
-#include "cart.h"
-
-/*     TODO:  Add code to put a delay in between the time a disk is inserted
-       and the when it can be successfully read/written to.  This should
-       prevent writes to wrong places OR add code to prevent disk ejects
-       when the virtual motor is on(mmm...virtual motor).
-*/
-
-static DECLFR(FDSRead4030);
-static DECLFR(FDSRead4031);
-static DECLFR(FDSRead4032);
-static DECLFR(FDSRead4033);
-static DECLFW(FDSWrite4020);
-static DECLFW(FDSWrite4021);
-static DECLFW(FDSWrite4022);
-static DECLFW(FDSWrite4023);
-static DECLFW(FDSWrite4024);
-static DECLFW(FDSWrite4025);
-static DECLFW(FDSWaveWrite);
-static DECLFR(FDSWaveRead);
-
-static DECLFR(FDSSRead);
-static DECLFW(FDSSWrite);
-static DECLFR(FDSBIOSRead);
-static DECLFR(FDSRAMRead);
-static DECLFW(FDSRAMWrite);
-static void FDSInit(void);
-static void FDSReset(void);
-static void FP_FASTAPASS(1) FDSFix(int a);
-
-#define FDSRAM GameMemBlock
-#define mapbyte1 (GameMemBlock+32768)
-#define mapbyte2 (GameMemBlock+32768+8)
-#define mapbyte3 (GameMemBlock+32768+16)
-#define mapbyte4 (GameMemBlock+32768+24)        // 8 bytes
-#define CHRRAM   (GameMemBlock+32768+32+64)
-
-#define IRQLatch       (*(int32*)(CHRRAM+8192))
-#define IRQCount       (*(int32*)(CHRRAM+8192+4))
-#define IRQa           (*(CHRRAM+8192+8))
-
-static void FDSClose(void);
-static uint8 header[16];
-#define writeskip mapbyte2[0]
-
-static char FDSSaveName[2048];
-
-uint8 FDSBIOS[8192];
-uint8 *diskdata[4]={0,0,0,0};
-
-#define SideWrite mapbyte2[1]
-#define DiskPtr (*(uint32*)(mapbyte2+4))
-#define dsr0 mapbyte2[2]
-#define dsr1 mapbyte2[3]
-
-#define DC_INC         1
-
-#define DiskSeekIRQ (*(int32*)(mapbyte3+4))
-#define SelectDisk mapbyte3[0]
-#define InDisk    mapbyte3[1]
-
-static void FDSReset(void)
-{
-        memset(mapbyte1,0,8);
-        memset(mapbyte2,0,8);
-        memset(mapbyte3+4,0,4);
-        memset(mapbyte4,0,8);
-}
-
-void FDSGI(int h)
-{
- switch(h)
- {
-  case GI_CLOSE: FDSClose();break;
-  case GI_POWER: FDSReset();FDSInit();break;
- }
-}
-
-static void FDSStateRestore(int version)
-{
- setmirror(((mapbyte1[5]&8)>>3)^1);
-}
-
-void FDSSound();
-void FDSSoundReset(void);
-void FDSSoundStateAdd(void);
-static void RenderSound(void);
-
-static void FDSInit(void)
-{
- dsr0=0;
- dsr1=0x41;
- setmirror(1);
- if(InDisk!=255)
-  dsr1&=0xFE;
-
- setprg8r(0,0xe000,0);          // BIOS
- setprg32r(1,0x6000,0);         // 32KB RAM
- setchr8(0);           // 8KB CHR RAM
-
- MapIRQHook=FDSFix;
- GameStateRestore=FDSStateRestore;
-
- SetReadHandler(0x4030,0x4030,FDSRead4030);
- SetReadHandler(0x4031,0x4031,FDSRead4031);
- SetReadHandler(0x4032,0x4032,FDSRead4032);
- SetReadHandler(0x4033,0x4033,FDSRead4033);
-
- SetWriteHandler(0x4020,0x4020,FDSWrite4020);
- SetWriteHandler(0x4021,0x4021,FDSWrite4021);
- SetWriteHandler(0x4022,0x4022,FDSWrite4022);
- SetWriteHandler(0x4023,0x4023,FDSWrite4023);
- SetWriteHandler(0x4024,0x4024,FDSWrite4024);
- SetWriteHandler(0x4025,0x4025,FDSWrite4025);
-
- SetWriteHandler(0x6000,0xdfff,FDSRAMWrite);
- SetReadHandler(0x6000,0xdfff,FDSRAMRead);
- SetReadHandler(0xE000,0xFFFF,FDSBIOSRead);
-
- IRQCount=IRQLatch=IRQa=0;
-
- FDSSoundReset();
-}
-
-void FDSControl(int what)
-{
- switch(what)
- {
-  case FDS_IDISK:dsr1&=0xFE;
-                 if(InDisk==255)
-                {
-                 FCEU_DispMessage("Disk %d Side %s Inserted",
-                 SelectDisk>>1,(SelectDisk&1)?"B":"A");
-                 InDisk=SelectDisk;
-                }
-                else
-                 FCEU_DispMessage("Jamming disks is a BAD IDEA");
-                break;
-  case FDS_EJECT:
-                if(InDisk!=255)
-                 FCEU_DispMessage("Disk Ejected");
-                else
-                 FCEU_DispMessage("Cannot Eject Air");
-                dsr1|=1;
-                InDisk=255;
-                break;
-  case FDS_SELECT:
-                 if(InDisk!=255)
-                 {
-                  FCEU_DispMessage("Eject disk before selecting.");
-                  break;
-                 }
-                 SelectDisk=((SelectDisk+1)%header[4])&3;
-                 FCEU_DispMessage("Disk %d Side %s Selected",
-                       SelectDisk>>1,(SelectDisk&1)?"B":"A");
-                 break;
- }
-}
-
-static void FP_FASTAPASS(1) FDSFix(int a)
-{
- if(IRQa)
- {
-  IRQCount-=a;
-  if(IRQCount<=0)
-  {
-   IRQa=0;
-   dsr0|=1;
-   dsr0&=~2;
-   IRQCount=0xFFFF;
-   X6502_IRQBegin(FCEU_IQEXT);
-  }
- }
- if(DiskSeekIRQ>0)
- {
-  DiskSeekIRQ-=a;
-  if(DiskSeekIRQ<=0)
-  {
-   if(mapbyte1[5]&0x80)
-   {
-    dsr0&=~1;
-    dsr0|=2;
-    TriggerIRQ();
-   }
-  }
- }
-}
-
-void DiskControl(int which)
-{
-if(mapbyte1[5]&1)
- {
-  switch(which)
-  {
-  case DC_INC:
-              if(DiskPtr<64999) DiskPtr++;
-              //DiskSeekIRQ=160+100;
-              //DiskSeekIRQ=140;
-              //DiskSeekIRQ=160;
-               DiskSeekIRQ=150;
-              break;
-  }
- }
-}
-static DECLFR(FDSRead4030)
-{
-       X6502_IRQEnd(FCEU_IQEXT);
-       return dsr0;
-}
-
-static DECLFR(FDSRead4031)
-{
-       static uint8 z=0;
-       if(InDisk!=255)
-       {
-         z=diskdata[InDisk][DiskPtr];
-         DiskControl(DC_INC);
-       }
-        return z;
-}
-
-static DECLFR(FDSRead4032)
-{
-       return dsr1;
-}
-
-static DECLFR(FDSRead4033)
-{
-       return 0x80; // battery
-}
-
-static DECLFW(FDSRAMWrite)
-{
- (FDSRAM-0x6000)[A]=V;
-}
-
-static DECLFR(FDSBIOSRead)
-{
- return (FDSBIOS-0xE000)[A];
-}
-
-static DECLFR(FDSRAMRead)
-{
- return (FDSRAM-0x6000)[A];
-}
-
-/* Begin FDS sound */
-
-#define FDSClock (1789772.7272727272727272/8)
-
-typedef struct {
-        int64 cycles;           // Cycles per PCM sample
-        int64 count;           // Cycle counter
-       int64 envcount;         // Envelope cycle counter
-       uint32 b19shiftreg60;
-       uint32 b24adder66;
-       uint32 b24latch68;
-       uint32 b17latch76;
-        int32 clockcount;      // Counter to divide frequency by 8.
-       uint8 b8shiftreg88;     // Modulation register.
-       uint8 amplitude[2];     // Current amplitudes.
-        uint8 mwave[0x20];      // Modulation waveform
-        uint8 cwave[0x40];      // Game-defined waveform(carrier)
-        uint8 SPSG[0xB];
-} FDSSOUND;
-
-static FDSSOUND fdso;
-
-#define        SPSG    fdso.SPSG
-#define b19shiftreg60  fdso.b19shiftreg60
-#define b24adder66     fdso.b24adder66
-#define b24latch68     fdso.b24latch68
-#define b17latch76     fdso.b17latch76
-#define b8shiftreg88   fdso.b8shiftreg88
-#define clockcount     fdso.clockcount
-#define amplitude      fdso.amplitude
-
-void FDSSoundStateAdd(void)
-{
- AddExState(fdso.cwave,64,0,"WAVE");
- AddExState(fdso.mwave,32,0,"MWAV");
- AddExState(amplitude,2,0,"AMPL");
- AddExState(SPSG,0xB,0,"SPSG");
-
- AddExState(&b8shiftreg88,1,0,"B88");
-
- AddExState(&clockcount, 4, 1, "CLOC");
- AddExState(&b19shiftreg60,4,1,"B60");
- AddExState(&b24adder66,4,1,"B66");
- AddExState(&b24latch68,4,1,"B68");
- AddExState(&b17latch76,4,1,"B76");
-
-}
-
-static DECLFR(FDSSRead)
-{
- switch(A&0xF)
- {
-  case 0x0:return(amplitude[0]|(X.DB&0xC0));
-  case 0x2:return(amplitude[1]|(X.DB&0xC0));
- }
- return(X.DB);
-}
-
-static DECLFW(FDSSWrite)
-{
- if(FSettings.SndRate)
-  RenderSound();
- A-=0x4080;
- switch(A)
- {
-  case 0x0:
-  case 0x4:
-           if(!(V&0x80))
-           {
-             // if(V&0x40) amplitude[(A&0xF)>>2]=0;
-             // else amplitude[(A&0xF)>>2]=0x3F;
-           }
-           else
-            amplitude[(A&0xF)>>2]=V&0x3F;
-           break;
-  case 0x7: b17latch76=0;SPSG[0x5]=0;break;
-  case 0x8:
-          //printf("%d:$%02x\n",SPSG[0x5],V);
-          fdso.mwave[SPSG[0x5]&0x1F]=V&0x7;
-           SPSG[0x5]=(SPSG[0x5]+1)&0x1F;
-          break;
- }
- //if(A>=0x7 && A!=0x8 && A<=0xF)
- //if(A==0xA || A==0x9) printf("$%04x:$%02x\n",A,V);
- SPSG[A]=V;
-}
-
-// $4080 - Fundamental wave amplitude data register 92
-// $4082 - Fundamental wave frequency data register 58
-// $4083 - Same as $4082($4083 is the upper 4 bits).
-
-// $4084 - Modulation amplitude data register 78
-// $4086 - Modulation frequency data register 72
-// $4087 - Same as $4086($4087 is the upper 4 bits)
-
-
-static void DoEnv()
-{
- int x;
-
- for(x=0;x<2;x++)
-  if(!(SPSG[x<<2]&0x80) && !(SPSG[0x9+x]&0x80))
-  {
-   static int counto[2]={0,0};
-
-   if(counto[x]<=0)
-   {
-    if(SPSG[x<<2]&0x40)
-    {
-     if(amplitude[x]<0x3F)
-      amplitude[x]++;
-    }
-    else
-    {
-     if(amplitude[x]>0)
-      amplitude[x]--;
-    }
-    counto[x]=(SPSG[x<<2]&0x3F);
-   }
-   else
-    counto[x]--;
-  }
-}
-
-static DECLFR(FDSWaveRead)
-{
- return(fdso.cwave[A&0x3f]|(X.DB&0xC0));
-}
-
-static DECLFW(FDSWaveWrite)
-{
- if(SPSG[0x9]&0x80)
-  fdso.cwave[A&0x3f]=V&0x3F;
-}
-
-static INLINE void ClockRise(void)
-{
- if(!clockcount)
- {
-  b19shiftreg60=(SPSG[0x2]|((SPSG[0x3]&0xF)<<8));
-  b17latch76=(SPSG[0x6]|((SPSG[0x07]&0x3)<<8))+b17latch76;
-
-  if(!(SPSG[0x7]&0x80))
-  {
-   b8shiftreg88=(amplitude[1]*((fdso.mwave[(b17latch76>>11)&0x1F]&7)));
-   //b8shiftreg88=((fdso.mwave[(b17latch76>>11)&0x1F]&7))|(amplitude[1]<<3);
-  }
-  else
-  { b8shiftreg88=0;}
- }
- else
- {
-  b19shiftreg60<<=1;
-  b8shiftreg88>>=1;
- }
- b24adder66=(b24latch68+b19shiftreg60)&0xFFFFFF;
-}
-
-static INLINE void ClockFall(void)
-{
-// if(!(SPSG[0x7]&0x80))
- {
-  if(!(b8shiftreg88&1))
-   b24latch68=b24adder66;
- }
- clockcount=(clockcount+1)&7;
-}
-
-static INLINE int32 FDSDoSound(void)
-{
- fdso.count+=fdso.cycles;
- if(fdso.count>=((int64)1<<40))
- {
-  dogk:
-  fdso.count-=(int64)1<<40;
-  ClockRise();
-  ClockFall();
- }
- if(fdso.count>=32768) goto dogk;
-
- fdso.envcount-=fdso.cycles;
- if(fdso.envcount<=0)
- {
-  // Fix this?
-  fdso.envcount+=((int64)1<<40)*FDSClock/1024;
-  DoEnv();
- }
-
- // Might need to emulate applying the amplitude to the waveform a bit better...
- return (fdso.cwave[b24latch68>>18]*amplitude[0]);
-}
-
-static int32 FBC=0;
-
-static void RenderSound(void)
-{
- int32 end, start;
- int32 x;
-
- start=FBC;
- end=(SOUNDTS<<16)/soundtsinc;
- if(end<=start)
-  return;
- FBC=end;
-
- if(!(SPSG[0x9]&0x80))
-  for(x=start;x<end;x++)
-  {
-   uint32 t=FDSDoSound();
-   Wave[x>>4]+=t>>3;
-  }
-}
-
-void FDSSound(int c)
-{
-  RenderSound();
-  FBC=c;
-}
-
-static void FDS_ESI(void)
-{
- if(FSettings.SndRate)
- {
-  fdso.cycles=((int64)1<<40)*FDSClock;
-  fdso.cycles/=FSettings.SndRate OVERSAMPLE;
- }
-//  fdso.cycles=(int64)32768*FDSClock/(FSettings.SndRate OVERSAMPLE);
- SetReadHandler(0x4040,0x407f,FDSWaveRead);
- SetWriteHandler(0x4040,0x407f,FDSWaveWrite);
- SetWriteHandler(0x4080,0x408A,FDSSWrite);
- SetReadHandler(0x4090,0x4092,FDSSRead);
-}
-
-void FDSSoundReset(void)
-{
- memset(&fdso,0,sizeof(fdso));
- FDS_ESI();
- GameExpSound.Fill=FDSSound;
- GameExpSound.RChange=FDS_ESI;
-}
-
-
-static DECLFW(FDSWrite4020)
-{
-       X6502_IRQEnd(FCEU_IQEXT);
-       IRQLatch&=0xFF00;
-       IRQLatch|=V;
-       mapbyte1[0]=V;
-}
-static DECLFW(FDSWrite4021)
-{
-       X6502_IRQEnd(FCEU_IQEXT);
-       IRQLatch&=0xFF;
-       IRQLatch|=V<<8;
-       mapbyte1[1]=V;
-}
-static DECLFW(FDSWrite4022)
-{
-       X6502_IRQEnd(FCEU_IQEXT);
-       IRQCount=IRQLatch;
-       IRQa=V&2;
-       mapbyte1[2]=V;
-}
-static DECLFW(FDSWrite4023)
-{
-       mapbyte1[3]=V;
-}
-static DECLFW(FDSWrite4024)
-{
-        if(InDisk!=255 && !(mapbyte1[5]&0x4) && mapbyte1[3]&0x1)
-        {
-         if(DiskPtr>=0 && DiskPtr<65000)
-         {
-          if(writeskip) writeskip--;
-          else if(DiskPtr>=2)
-          {
-           SideWrite|=1<<InDisk;
-           diskdata[InDisk][DiskPtr-2]=V;
-          }
-         }
-        }
-}
-static DECLFW(FDSWrite4025)
-{
-       if(InDisk!=255)
-       {
-         if(!(V&0x40))
-         {
-          if(mapbyte1[5]&0x40 && !(V&0x10))
-          {
-           DiskSeekIRQ=200;
-           DiskPtr-=2;
-          }
-          if(DiskPtr<0) DiskPtr=0;
-         }
-         if(!(V&0x4)) writeskip=2;
-         if(V&2) {DiskPtr=0;DiskSeekIRQ=200;}
-         if(V&0x40) DiskSeekIRQ=200;
-       }
-       mapbyte1[5]=V;
-        setmirror(((V>>3)&1)^1);
-}
-static void FreeFDSMemory(void)
-{
- int x;
-
- for(x=0;x<header[4];x++)
-  if(diskdata[x])
-  {
-   free(diskdata[x]);
-   diskdata[x]=0;
-  }
-}
-
-int FDSLoad(char *name, int fp)
-{
- FILE *zp;
- int x;
-
- FCEU_fseek(fp,0,SEEK_SET);
- FCEU_fread(header,16,1,fp);
-
- if(memcmp(header,"FDS\x1a",4))
- {
-  if(!(memcmp(header+1,"*NINTENDO-HVC*",14)))
-  {
-   long t;
-   t=FCEU_fgetsize(fp);
-   if(t<65500)
-    t=65500;
-   header[4]=t/65500;
-   header[0]=0;
-   FCEU_fseek(fp,0,SEEK_SET);
-  }
-  else
-   return 0;
- }
-
- if(header[4]>4) header[4]=4;
- if(!header[4]) header[4]|=1;
- for(x=0;x<header[4];x++)
- {
-  diskdata[x]=FCEU_malloc(65500);
-  if(!diskdata[x])
-  {
-   int zol;
-   for(zol=0;zol<x;zol++)
-    free(diskdata[zol]);
-   return 0;
-  }
-  FCEU_fread(diskdata[x],1,65500,fp);
- }
-
- if(!(zp=fopen(FCEU_MakeFName(FCEUMKF_FDSROM,0,0),"rb")))
- {
-  FCEU_PrintError("FDS BIOS ROM image missing!");
-  FreeFDSMemory();
-  return 0;
- }
-
- if(fread(FDSBIOS,1,8192,zp)!=8192)
- {
-  fclose(zp);
-  FreeFDSMemory();
-  FCEU_PrintError("Error reading FDS BIOS ROM image");
-  return 0;
- }
-
- fclose(zp);
-
- FCEUGameInfo.type=GIT_FDS;
- strcpy(FDSSaveName,name);
- GameInterface=FDSGI;
-
- SelectDisk=0;
- InDisk=255;
-
- ResetExState();
- FDSSoundStateAdd();
-
- for(x=0;x<header[4];x++)
- {
-  char temp[5];
-  sprintf(temp,"DDT%d",x);
-  AddExState(diskdata[x],65500,0,temp);
- }
-
- AddExState(FDSRAM,32768,0,"FDSR");
- AddExState(mapbyte1,32,0,"MPBY");
- AddExState(CHRRAM,8192,0,"CHRR");
- AddExState(&IRQCount, 4, 1, "IRQC");
- AddExState(&IRQLatch, 4, 1, "IQL1");
- AddExState(&IRQa, 1, 0, "IRQA");
-
-
- ResetCartMapping();
-
- SetupCartCHRMapping(0,CHRRAM,8192,1);
- SetupCartMirroring(0,0,0);
-
- return 1;
-}
-
-void FDSClose(void)
-{
-  int fp;
-  int x;
-
-  fp=FCEU_fopen(FDSSaveName,"wb");
-  if(!fp) return;
-
-  if(header[0])                        // Does it have a 16-byte FWNES-style header?
-   if(FCEU_fwrite(header,1,16,fp)!=16) // Write it out.  Should be nicer than fseek()'ing if the file is compressed.  Hopefully...
-    goto fdswerr;
-
-  for(x=0;x<header[4];x++)
-  {
-   if(FCEU_fwrite(diskdata[x],1,65500,fp)!=65500)
-   {
-    fdswerr:
-    FCEU_PrintError("Error writing FDS image \"%s\"!",FDSSaveName);
-    FCEU_fclose(fp);
-    return;
-   }
-  }
-  FreeFDSMemory();
-  FCEU_fclose(fp);
-}
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 2002 Xodnizel\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
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "types.h"\r
+#include "x6502.h"\r
+#include "fce.h"\r
+#include "fds.h"\r
+#include "sound.h"\r
+#include "general.h"\r
+#include "state.h"\r
+#include "file.h"\r
+#include "memory.h"\r
+#include "cart.h"\r
+#include "md5.h"\r
+#include "netplay.h"\r
+\r
+#include "svga.h"\r
+\r
+/*  TODO:  Add code to put a delay in between the time a disk is inserted\r
+       and the when it can be successfully read/written to.  This should\r
+       prevent writes to wrong places OR add code to prevent disk ejects\r
+       when the virtual motor is on(mmm...virtual motor).\r
+*/\r
+\r
+static DECLFR(FDSRead4030);\r
+static DECLFR(FDSRead4031);\r
+static DECLFR(FDSRead4032);\r
+static DECLFR(FDSRead4033);\r
+\r
+static DECLFW(FDSWrite);\r
+\r
+static DECLFW(FDSWaveWrite);\r
+static DECLFR(FDSWaveRead);\r
+\r
+static DECLFR(FDSSRead);\r
+static DECLFW(FDSSWrite);\r
+static DECLFR(FDSBIOSRead);\r
+static DECLFR(FDSRAMRead);\r
+static DECLFW(FDSRAMWrite);\r
+static void FDSInit(void);\r
+static void FP_FASTAPASS(1) FDSFix(int a);\r
+\r
+#define FDSRAM GameMemBlock\r
+#define CHRRAM (GameMemBlock+32768)\r
+\r
+static uint8 FDSRegs[6];\r
+static int32 IRQLatch,IRQCount;\r
+static uint8 IRQa;\r
+static void FDSClose(void);\r
+\r
+static uint8 FDSBIOS[8192];\r
+\r
+/* Original disk data backup, to help in creating save states. */\r
+static uint8 *diskdatao[8]={0,0,0,0,0,0,0,0};\r
+\r
+static uint8 *diskdata[8]={0,0,0,0,0,0,0,0};\r
+\r
+static unsigned int TotalSides;\r
+static uint8 DiskWritten=0;    /* Set to 1 if disk was written to. */\r
+static uint8 writeskip;\r
+static uint32 DiskPtr;\r
+static int32 DiskSeekIRQ;\r
+static uint8 SelectDisk,InDisk;\r
+\r
+#define DC_INC    1\r
+\r
+void FDSGI(int h)\r
+{\r
+ switch(h)\r
+ {\r
+  case GI_CLOSE: FDSClose();break;\r
+  case GI_POWER: FDSInit();break;\r
+ }\r
+}\r
+\r
+static void FDSStateRestore(int version)\r
+{\r
+ int x;\r
+\r
+ setmirror(((FDSRegs[5]&8)>>3)^1);\r
+\r
+ if(version >= 9810)\r
+  for(x=0;x<TotalSides;x++)\r
+  {\r
+   int b;\r
+   for(b=0; b<65500; b++)\r
+    diskdata[x][b] ^= diskdatao[x][b];\r
+  }\r
+\r
+}\r
+\r
+void FDSSound();\r
+void FDSSoundReset(void);\r
+void FDSSoundStateAdd(void);\r
+static void RenderSound(void);\r
+//static void RenderSoundHQ(void);\r
+\r
+static void FDSInit(void)\r
+{\r
+ memset(FDSRegs,0,sizeof(FDSRegs));\r
+ writeskip=DiskPtr=DiskSeekIRQ=0;\r
+ setmirror(1);\r
+\r
+ setprg8r(0,0xe000,0);    // BIOS\r
+ setprg32r(1,0x6000,0);   // 32KB RAM\r
+ setchr8(0);     // 8KB CHR RAM\r
+\r
+ MapIRQHook=FDSFix;\r
+ GameStateRestore=FDSStateRestore;\r
+\r
+ SetReadHandler(0x4030,0x4030,FDSRead4030);\r
+ SetReadHandler(0x4031,0x4031,FDSRead4031);\r
+ SetReadHandler(0x4032,0x4032,FDSRead4032);\r
+ SetReadHandler(0x4033,0x4033,FDSRead4033);\r
+\r
+ SetWriteHandler(0x4020,0x4025,FDSWrite);\r
+\r
+ SetWriteHandler(0x6000,0xdfff,FDSRAMWrite);\r
+ SetReadHandler(0x6000,0xdfff,FDSRAMRead);\r
+ SetReadHandler(0xE000,0xFFFF,FDSBIOSRead);\r
+ IRQCount=IRQLatch=IRQa=0;\r
+\r
+ FDSSoundReset();\r
+ InDisk=0;\r
+ SelectDisk=0;\r
+}\r
+\r
+void FCEU_FDSInsert(void)\r
+{\r
+       if(TotalSides==0)\r
+       {\r
+        FCEU_DispMessage("Not FDS; can't eject disk.");\r
+               return;\r
+       }\r
+       if(InDisk==255)\r
+        {\r
+         FCEU_DispMessage("Disk %d Side %s Inserted",SelectDisk>>1,(SelectDisk&1)?"B":"A");\r
+         InDisk=SelectDisk;\r
+        }\r
+        else\r
+        {\r
+         FCEU_DispMessage("Disk %d Side %s Ejected",SelectDisk>>1,(SelectDisk&1)?"B":"A");\r
+         InDisk=255;\r
+        }\r
+}\r
+/*\r
+void FCEU_FDSEject(void)\r
+{\r
+         InDisk=255;\r
+}\r
+*/\r
+void FCEU_FDSSelect(void)\r
+{\r
+       if(TotalSides==0)\r
+       {\r
+         FCEU_DispMessage("Not FDS; can't select disk.");\r
+         return;\r
+       }\r
+       if(InDisk!=255)\r
+        {\r
+         FCEU_DispMessage("Eject disk before selecting.");\r
+        return;\r
+        }\r
+           SelectDisk=((SelectDisk+1)%TotalSides)&3;\r
+           FCEU_DispMessage("Disk %d Side %c Selected",SelectDisk>>1,(SelectDisk&1)?'B':'A');\r
+}\r
+\r
+static void FP_FASTAPASS(1) FDSFix(int a)\r
+{\r
+ if((IRQa&2) && IRQCount)\r
+ {\r
+  IRQCount-=a;\r
+  if(IRQCount<=0)\r
+  {\r
+   if(!(IRQa&1))\r
+   {\r
+    IRQa&=~2;\r
+    IRQCount=IRQLatch=0;\r
+   }\r
+   else\r
+    IRQCount=IRQLatch;\r
+   //IRQCount=IRQLatch; //0xFFFF;\r
+   X6502_IRQBegin(FCEU_IQEXT);\r
+   //printf("IRQ: %d\n",timestamp);\r
+//   printf("IRQ: %d\n",scanline);\r
+  }\r
+ }\r
+ if(DiskSeekIRQ>0)\r
+ {\r
+  DiskSeekIRQ-=a;\r
+  if(DiskSeekIRQ<=0)\r
+  {\r
+   if(FDSRegs[5]&0x80)\r
+   {\r
+    X6502_IRQBegin(FCEU_IQEXT2);\r
+   }\r
+  }\r
+ }\r
+}\r
+\r
+static DECLFR(FDSRead4030)\r
+{\r
+       uint8 ret=0;\r
+\r
+       /* Cheap hack. */\r
+       if(X.IRQlow&FCEU_IQEXT) ret|=1;\r
+       if(X.IRQlow&FCEU_IQEXT2) ret|=2;\r
+\r
+       if(!fceuindbg)\r
+       {\r
+        X6502_IRQEnd(FCEU_IQEXT);\r
+        X6502_IRQEnd(FCEU_IQEXT2);\r
+       }\r
+       return ret;\r
+}\r
+\r
+static DECLFR(FDSRead4031)\r
+{\r
+       static uint8 z=0;\r
+       if(InDisk!=255)\r
+       {\r
+         z=diskdata[InDisk][DiskPtr];\r
+        if(!fceuindbg)\r
+        {\r
+          if(DiskPtr<64999) DiskPtr++;\r
+          DiskSeekIRQ=150;\r
+          X6502_IRQEnd(FCEU_IQEXT2);\r
+        }\r
+       }\r
+        return z;\r
+}\r
+static DECLFR(FDSRead4032)\r
+{\r
+        uint8 ret;\r
+\r
+        ret=X.DB&~7;\r
+        if(InDisk==255)\r
+         ret|=5;\r
+\r
+        if(InDisk==255 || !(FDSRegs[5]&1) || (FDSRegs[5]&2))\r
+         ret|=2;\r
+        return ret;\r
+}\r
+\r
+static DECLFR(FDSRead4033)\r
+{\r
+       return 0x80; // battery\r
+}\r
+\r
+static DECLFW(FDSRAMWrite)\r
+{\r
+ (FDSRAM-0x6000)[A]=V;\r
+}\r
+\r
+static DECLFR(FDSBIOSRead)\r
+{\r
+ return (FDSBIOS-0xE000)[A];\r
+}\r
+\r
+static DECLFR(FDSRAMRead)\r
+{\r
+ return (FDSRAM-0x6000)[A];\r
+}\r
+\r
+/* Begin FDS sound */\r
+\r
+#define FDSClock (1789772.7272727272727272/2)\r
+\r
+typedef struct {\r
+  int64 cycles;     // Cycles per PCM sample\r
+  int64 count;    // Cycle counter\r
+  int64 envcount;    // Envelope cycle counter\r
+       uint32 b19shiftreg60;\r
+       uint32 b24adder66;\r
+       uint32 b24latch68;\r
+       uint32 b17latch76;\r
+  int32 clockcount;  // Counter to divide frequency by 8.\r
+  uint8 b8shiftreg88;  // Modulation register.\r
+  uint8 amplitude[2];  // Current amplitudes.\r
+       uint8 speedo[2];\r
+       uint8 mwcount;\r
+       uint8 mwstart;\r
+        uint8 mwave[0x20];      // Modulation waveform\r
+        uint8 cwave[0x40];      // Game-defined waveform(carrier)\r
+        uint8 SPSG[0xB];\r
+} FDSSOUND;\r
+\r
+static FDSSOUND fdso;\r
+\r
+#define  SPSG  fdso.SPSG\r
+#define b19shiftreg60  fdso.b19shiftreg60\r
+#define b24adder66  fdso.b24adder66\r
+#define b24latch68  fdso.b24latch68\r
+#define b17latch76  fdso.b17latch76\r
+#define b8shiftreg88  fdso.b8shiftreg88\r
+#define clockcount  fdso.clockcount\r
+#define amplitude  fdso.amplitude\r
+#define speedo    fdso.speedo\r
+\r
+void FDSSoundStateAdd(void)\r
+{\r
+ AddExState(fdso.cwave,64,0,"WAVE");\r
+ AddExState(fdso.mwave,32,0,"MWAV");\r
+ AddExState(amplitude,2,0,"AMPL");\r
+ AddExState(SPSG,0xB,0,"SPSG");\r
+\r
+ AddExState(&b8shiftreg88,1,0,"B88");\r
+\r
+ AddExState(&clockcount, 4, 1, "CLOC");\r
+ AddExState(&b19shiftreg60,4,1,"B60");\r
+ AddExState(&b24adder66,4,1,"B66");\r
+ AddExState(&b24latch68,4,1,"B68");\r
+ AddExState(&b17latch76,4,1,"B76");\r
+\r
+}\r
+\r
+static DECLFR(FDSSRead)\r
+{\r
+ switch(A&0xF)\r
+ {\r
+  case 0x0:return(amplitude[0]|(X.DB&0xC0));\r
+  case 0x2:return(amplitude[1]|(X.DB&0xC0));\r
+ }\r
+ return(X.DB);\r
+}\r
+\r
+static DECLFW(FDSSWrite)\r
+{\r
+ if(FSettings.SndRate)\r
+ {\r
+#if 0\r
+  if(FSettings.soundq>=1)\r
+   RenderSoundHQ();\r
+  else\r
+#endif\r
+   RenderSound();\r
+ }\r
+ A-=0x4080;\r
+ switch(A)\r
+ {\r
+  case 0x0:\r
+  case 0x4: if(V&0x80)\r
+            amplitude[(A&0xF)>>2]=V&0x3F; //)>0x20?0x20:(V&0x3F);\r
+           break;\r
+  case 0x5://printf("$%04x:$%02x\n",A,V);\r
+               break;\r
+  case 0x7: b17latch76=0;SPSG[0x5]=0;//printf("$%04x:$%02x\n",A,V);\r
+               break;\r
+  case 0x8:\r
+          b17latch76=0;\r
+       //   printf("%d:$%02x, $%02x\n",SPSG[0x5],V,b17latch76);\r
+          fdso.mwave[SPSG[0x5]&0x1F]=V&0x7;\r
+           SPSG[0x5]=(SPSG[0x5]+1)&0x1F;\r
+          break;\r
+ }\r
+ //if(A>=0x7 && A!=0x8 && A<=0xF)\r
+ //if(A==0xA || A==0x9)\r
+ //printf("$%04x:$%02x\n",A,V);\r
+ SPSG[A]=V;\r
+}\r
+\r
+// $4080 - Fundamental wave amplitude data register 92\r
+// $4082 - Fundamental wave frequency data register 58\r
+// $4083 - Same as $4082($4083 is the upper 4 bits).\r
+\r
+// $4084 - Modulation amplitude data register 78\r
+// $4086 - Modulation frequency data register 72\r
+// $4087 - Same as $4086($4087 is the upper 4 bits)\r
+\r
+\r
+static void DoEnv()\r
+{\r
+ int x;\r
+\r
+ for(x=0;x<2;x++)\r
+  if(!(SPSG[x<<2]&0x80) && !(SPSG[0x3]&0x40))\r
+  {\r
+   static int counto[2]={0,0};\r
+\r
+   if(counto[x]<=0)\r
+   {\r
+    if(!(SPSG[x<<2]&0x80))\r
+    {\r
+     if(SPSG[x<<2]&0x40)\r
+     {\r
+      if(amplitude[x]<0x3F)\r
+       amplitude[x]++;\r
+     }\r
+     else\r
+     {\r
+      if(amplitude[x]>0)\r
+       amplitude[x]--;\r
+     }\r
+    }\r
+    counto[x]=(SPSG[x<<2]&0x3F);\r
+   }\r
+   else\r
+    counto[x]--;\r
+  }\r
+}\r
+\r
+static DECLFR(FDSWaveRead)\r
+{\r
+ return(fdso.cwave[A&0x3f]|(X.DB&0xC0));\r
+}\r
+\r
+static DECLFW(FDSWaveWrite)\r
+{\r
+ //printf("$%04x:$%02x, %d\n",A,V,SPSG[0x9]&0x80);\r
+ if(SPSG[0x9]&0x80)\r
+  fdso.cwave[A&0x3f]=V&0x3F;\r
+}\r
+\r
+static int ta;\r
+static INLINE void ClockRise(void)\r
+{\r
+ if(!clockcount)\r
+ {\r
+  ta++;\r
+\r
+  b19shiftreg60=(SPSG[0x2]|((SPSG[0x3]&0xF)<<8));\r
+  b17latch76=(SPSG[0x6]|((SPSG[0x07]&0xF)<<8))+b17latch76;\r
+\r
+  if(!(SPSG[0x7]&0x80))\r
+  {\r
+   int t=fdso.mwave[(b17latch76>>13)&0x1F]&7;\r
+   int t2=amplitude[1];\r
+   int adj = 0;\r
+\r
+   if((t&3))\r
+   {\r
+    if((t&4))\r
+     adj -= (t2 * ((4 - (t&3) ) ));\r
+    else\r
+     adj += (t2 * ( (t&3) ));\r
+   }\r
+   adj *= 2;\r
+   if(adj > 0x7F) adj = 0x7F;\r
+   if(adj < -0x80) adj = -0x80;\r
+   //if(adj) printf("%d ",adj);\r
+   b8shiftreg88=0x80 + adj;\r
+  }\r
+  else\r
+  {\r
+   b8shiftreg88=0x80;\r
+  }\r
+ }\r
+ else\r
+ {\r
+  b19shiftreg60<<=1;\r
+  b8shiftreg88>>=1;\r
+ }\r
+// b24adder66=(b24latch68+b19shiftreg60)&0x3FFFFFF;\r
+ b24adder66=(b24latch68+b19shiftreg60)&0x1FFFFFF;\r
+}\r
+\r
+static INLINE void ClockFall(void)\r
+{\r
+ //if(!(SPSG[0x7]&0x80))\r
+ {\r
+  if((b8shiftreg88&1)) // || clockcount==7)\r
+   b24latch68=b24adder66;\r
+ }\r
+ clockcount=(clockcount+1)&7;\r
+}\r
+\r
+static INLINE int32 FDSDoSound(void)\r
+{\r
+ fdso.count+=fdso.cycles;\r
+ if(fdso.count>=((int64)1<<40))\r
+ {\r
+  dogk:\r
+  fdso.count-=(int64)1<<40;\r
+  ClockRise();\r
+  ClockFall();\r
+  fdso.envcount--;\r
+  if(fdso.envcount<=0)\r
+  {\r
+   fdso.envcount+=SPSG[0xA]*3;\r
+   DoEnv();\r
+  }\r
+ }\r
+ if(fdso.count>=32768) goto dogk;\r
+\r
+ // Might need to emulate applying the amplitude to the waveform a bit better...\r
+ {\r
+  int k=amplitude[0];\r
+  if(k>0x20) k=0x20;\r
+  return (fdso.cwave[b24latch68>>19]*k)*4/((SPSG[0x9]&0x3)+2);\r
+ }\r
+}\r
+\r
+static int32 FBC=0;\r
+\r
+static void RenderSound(void)\r
+{\r
+ int32 end, start;\r
+ int32 x;\r
+\r
+ start=FBC;\r
+ end=(SOUNDTS<<16)/soundtsinc;\r
+ if(end<=start)\r
+  return;\r
+ FBC=end;\r
+\r
+ if(!(SPSG[0x9]&0x80))\r
+  for(x=start;x<end;x++)\r
+  {\r
+   uint32 t=FDSDoSound();\r
+   t+=t>>1;\r
+   t>>=4;\r
+   Wave[x>>4]+=t; //(t>>2)-(t>>3); //>>3;\r
+  }\r
+}\r
+\r
+#if 0\r
+static void RenderSoundHQ(void)\r
+{\r
+ int32 x;\r
+\r
+ if(!(SPSG[0x9]&0x80))\r
+  for(x=FBC;x<SOUNDTS;x++)\r
+  {\r
+   uint32 t=FDSDoSound();\r
+   t+=t>>1;\r
+   WaveHi[x]+=t; //(t<<2)-(t<<1);\r
+  }\r
+ FBC=SOUNDTS;\r
+}\r
+#endif\r
+\r
+static void HQSync(int32 ts)\r
+{\r
+ FBC=ts;\r
+}\r
+\r
+void FDSSound(int c)\r
+{\r
+  RenderSound();\r
+  FBC=c;\r
+}\r
+\r
+/*\r
+static DECLFR(FDSBIOSPatch)\r
+{\r
+ if(FDSRegs[5]&0x4)\r
+ {\r
+  X.X=FDSRead4031(0x4031);\r
+  FDSWrite(0x4024,X.A);\r
+  X.A=X.X;\r
+  return(0x60);\r
+ }\r
+ else\r
+ {\r
+  return(0x58);\r
+  //puts("Write");\r
+ }\r
+}\r
+*/\r
+\r
+static void FDS_ESI(void)\r
+{\r
+ if(FSettings.SndRate)\r
+ {\r
+#if 0\r
+  if(FSettings.soundq>=1)\r
+  {\r
+   fdso.cycles=(int64)1<<39;\r
+  }\r
+  else\r
+#endif\r
+  {\r
+   fdso.cycles=((int64)1<<40)*FDSClock;\r
+   fdso.cycles/=FSettings.SndRate *16;\r
+  }\r
+ }\r
+//  fdso.cycles=(int64)32768*FDSClock/(FSettings.SndRate *16);\r
+ SetReadHandler(0x4040,0x407f,FDSWaveRead);\r
+ SetWriteHandler(0x4040,0x407f,FDSWaveWrite);\r
+ SetWriteHandler(0x4080,0x408A,FDSSWrite);\r
+ SetReadHandler(0x4090,0x4092,FDSSRead);\r
+\r
+ //SetReadHandler(0xE7A3,0xE7A3,FDSBIOSPatch);\r
+}\r
+\r
+void FDSSoundReset(void)\r
+{\r
+ memset(&fdso,0,sizeof(fdso));\r
+ FDS_ESI();\r
+ GameExpSound.HiSync=HQSync;\r
+ GameExpSound.HiFill=0;//RenderSoundHQ;\r
+ GameExpSound.Fill=FDSSound;\r
+ GameExpSound.RChange=FDS_ESI;\r
+}\r
+\r
+static DECLFW(FDSWrite)\r
+{\r
+ //extern int scanline;\r
+ //FCEU_printf("$%04x:$%02x, %d\n",A,V,scanline);\r
+ switch(A)\r
+ {\r
+  case 0x4020:\r
+       X6502_IRQEnd(FCEU_IQEXT);\r
+       IRQLatch&=0xFF00;\r
+       IRQLatch|=V;\r
+//  printf("$%04x:$%02x\n",A,V);\r
+        break;\r
+  case 0x4021:\r
+        X6502_IRQEnd(FCEU_IQEXT);\r
+       IRQLatch&=0xFF;\r
+       IRQLatch|=V<<8;\r
+//  printf("$%04x:$%02x\n",A,V);\r
+        break;\r
+  case 0x4022:\r
+       X6502_IRQEnd(FCEU_IQEXT);\r
+       IRQCount=IRQLatch;\r
+       IRQa=V&3;\r
+//  printf("$%04x:$%02x\n",A,V);\r
+        break;\r
+  case 0x4023:break;\r
+  case 0x4024:\r
+        if(InDisk!=255 && !(FDSRegs[5]&0x4) && (FDSRegs[3]&0x1))\r
+        {\r
+         if(DiskPtr>=0 && DiskPtr<65500)\r
+         {\r
+          if(writeskip) writeskip--;\r
+          else if(DiskPtr>=2)\r
+          {\r
+          DiskWritten=1;\r
+           diskdata[InDisk][DiskPtr-2]=V;\r
+          }\r
+         }\r
+        }\r
+        break;\r
+  case 0x4025:\r
+       X6502_IRQEnd(FCEU_IQEXT2);\r
+       if(InDisk!=255)\r
+       {\r
+         if(!(V&0x40))\r
+         {\r
+          if(FDSRegs[5]&0x40 && !(V&0x10))\r
+          {\r
+           DiskSeekIRQ=200;\r
+           DiskPtr-=2;\r
+          }\r
+          if(DiskPtr<0) DiskPtr=0;\r
+         }\r
+         if(!(V&0x4)) writeskip=2;\r
+         if(V&2) {DiskPtr=0;DiskSeekIRQ=200;}\r
+         if(V&0x40) DiskSeekIRQ=200;\r
+       }\r
+        setmirror(((V>>3)&1)^1);\r
+        break;\r
+ }\r
+ FDSRegs[A&7]=V;\r
+}\r
+\r
+static void FreeFDSMemory(void)\r
+{\r
+ int x;\r
+\r
+ for(x=0;x<TotalSides;x++)\r
+  if(diskdata[x])\r
+  {\r
+   free(diskdata[x]);\r
+   diskdata[x]=0;\r
+  }\r
+}\r
+\r
+static int SubLoad(int fp)\r
+{\r
+ struct md5_context md5;\r
+ uint8 header[16];\r
+ int x;\r
+\r
+ FCEU_fread(header,16,1,fp);\r
+\r
+ if(memcmp(header,"FDS\x1a",4))\r
+ {\r
+  if(!(memcmp(header+1,"*NINTENDO-HVC*",14)))\r
+  {\r
+   long t;\r
+   t=FCEU_fgetsize(fp);\r
+   if(t<65500)\r
+    t=65500;\r
+   TotalSides=t/65500;\r
+   FCEU_fseek(fp,0,SEEK_SET);\r
+  }\r
+  else\r
+   return(0);\r
+ }\r
+ else\r
+  TotalSides=header[4];\r
+\r
+ md5_starts(&md5);\r
+\r
+ if(TotalSides>8) TotalSides=8;\r
+ if(TotalSides<1) TotalSides=1;\r
+\r
+ for(x=0;x<TotalSides;x++)\r
+ {\r
+  diskdata[x]=(uint8 *)FCEU_malloc(65500);\r
+  if(!diskdata[x])\r
+  {\r
+   int zol;\r
+   for(zol=0;zol<x;zol++)\r
+    free(diskdata[zol]);\r
+   return 0;\r
+  }\r
+  FCEU_fread(diskdata[x],1,65500,fp);\r
+  md5_update(&md5,diskdata[x],65500);\r
+ }\r
+ md5_finish(&md5,FCEUGameInfo.MD5);\r
+ return(1);\r
+}\r
+\r
+static void PreSave(void)\r
+{\r
+ int x;\r
+\r
+ //if(DiskWritten)\r
+  for(x=0;x<TotalSides;x++)\r
+  {\r
+   int b;\r
+   for(b=0; b<65500; b++)\r
+    diskdata[x][b] ^= diskdatao[x][b];\r
+  }\r
+}\r
+\r
+static void PostSave(void)\r
+{\r
+ int x;\r
+\r
+ //if(DiskWritten)\r
+  for(x=0;x<TotalSides;x++)\r
+  {\r
+   int b;\r
+\r
+   for(b=0; b<65500; b++)\r
+    diskdata[x][b] ^= diskdatao[x][b];\r
+  }\r
+\r
+}\r
+\r
+int FDSLoad(const char *name, int fp)\r
+{\r
+ FILE *zp;\r
+ int x;\r
+ char *fn;\r
+\r
+ FCEU_fseek(fp,0,SEEK_SET);\r
+\r
+ if(!SubLoad(fp))\r
+  return(0);\r
+\r
+\r
+ fn = FCEU_MakeFName(FCEUMKF_FDSROM,0,0);\r
+\r
+ if(!(zp=FCEUD_UTF8fopen(fn,"rb")))\r
+ {\r
+  FCEU_PrintError("FDS BIOS ROM image missing!");\r
+  FreeFDSMemory();\r
+  free(fn);\r
+  return 0;\r
+ }\r
+\r
+ free(fn);\r
+\r
+ if(fread(FDSBIOS,1,8192,zp)!=8192)\r
+ {\r
+  fclose(zp);\r
+  FreeFDSMemory();\r
+  FCEU_PrintError("Error reading FDS BIOS ROM image.");\r
+  return 0;\r
+ }\r
+\r
+ fclose(zp);\r
+\r
+\r
+ {\r
+  int tp;\r
+  char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);\r
+\r
+  int x;\r
+  for(x=0;x<TotalSides;x++)\r
+  {\r
+   diskdatao[x]=(uint8 *)FCEU_malloc(65500);\r
+   memcpy(diskdatao[x],diskdata[x],65500);\r
+  }\r
+\r
+  if((tp=FCEU_fopen(fn,"rb")))\r
+  {\r
+   FreeFDSMemory();\r
+   if(!SubLoad(tp))\r
+   {\r
+    FCEU_PrintError("Error reading auxillary FDS file.");\r
+    free(fn);\r
+    return(0);\r
+   }\r
+   FCEU_fclose(tp);\r
+   DiskWritten=1;  /* For save state handling. */\r
+  }\r
+  free(fn);\r
+ }\r
+\r
+ FCEUGameInfo.type=GIT_FDS;\r
+ GameInterface=FDSGI;\r
+\r
+ SelectDisk=0;\r
+ InDisk=255;\r
+\r
+ ResetExState(PreSave,PostSave);\r
+ FDSSoundStateAdd();\r
+\r
+ for(x=0;x<TotalSides;x++)\r
+ {\r
+  char temp[5];\r
+  sprintf(temp,"DDT%d",x);\r
+  AddExState(diskdata[x],65500,0,temp);\r
+ }\r
+\r
+ AddExState(FDSRAM,32768,0,"FDSR");\r
+ AddExState(FDSRegs,sizeof(FDSRegs),0,"FREG");\r
+ AddExState(CHRRAM,8192,0,"CHRR");\r
+ AddExState(&IRQCount, 4, 1, "IRQC");\r
+ AddExState(&IRQLatch, 4, 1, "IQL1");\r
+ AddExState(&IRQa, 1, 0, "IRQA");\r
+ AddExState(&writeskip,1,0,"WSKI");\r
+ AddExState(&DiskPtr,4,1,"DPTR");\r
+ AddExState(&DiskSeekIRQ,4,1,"DSIR");\r
+ AddExState(&SelectDisk,1,0,"SELD");\r
+ AddExState(&InDisk,1,0,"INDI");\r
+ AddExState(&DiskWritten,1,0,"DSKW");\r
+\r
+ ResetCartMapping();\r
+ SetupCartCHRMapping(0,CHRRAM,8192,1);\r
+ SetupCartMirroring(0,0,0);\r
+ memset(CHRRAM,0,8192);\r
+ memset(FDSRAM,0,32768);\r
+\r
+ FCEU_printf(" Sides: %d\n\n",TotalSides);\r
+\r
+ FCEUI_SetVidSystem(0);\r
+\r
+ return 1;\r
+}\r
+\r
+void FDSClose(void)\r
+{\r
+ FILE *fp;\r
+ int x;\r
+ char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);\r
+\r
+ if(!DiskWritten) return;\r
+\r
+ if(!(fp=FCEUD_UTF8fopen(fn,"wb")))\r
+ {\r
+  free(fn);\r
+  return;\r
+ }\r
+ free(fn);\r
+\r
+ for(x=0;x<TotalSides;x++)\r
+ {\r
+  if(fwrite(diskdata[x],1,65500,fp)!=65500)\r
+  {\r
+   FCEU_PrintError("Error saving FDS image!");\r
+   fclose(fp);\r
+   return;\r
+  }\r
+ }\r
+ FreeFDSMemory();\r
+ fclose(fp);\r
+}\r
diff --git a/fds.h b/fds.h
index 9e526db..4269d70 100644 (file)
--- a/fds.h
+++ b/fds.h
@@ -1,8 +1,5 @@
-void FDSControl(int what);
-
-#define FDS_IDISK  1
-#define FDS_EJECT  2
-#define FDS_SELECT 3
-
-int FDSLoad(char *name, int fp);
-void FDSSoundReset(void);
+void FDSSoundReset(void);\r
+\r
+void FCEU_FDSInsert(void);\r
+//void FCEU_FDSEject(void);\r
+void FCEU_FDSSelect(void);\r
diff --git a/file.h b/file.h
index 3c70f97..fcce1ab 100644 (file)
--- a/file.h
+++ b/file.h
@@ -10,3 +10,5 @@ int FASTAPASS(1) FCEU_fgetc(int stream);
 long FASTAPASS(1) FCEU_fgetsize(int stream);
 int FASTAPASS(1) FCEU_fisarchive(int stream);
 
+#define FCEUD_UTF8fopen fopen
+
index 4b0c0cf..f01bae6 100644 (file)
--- a/general.c
+++ b/general.c
@@ -83,6 +83,11 @@ char *FCEU_MakeFName(int type, int id1, char *cd1)
                       sprintf(((char*)ret),"%s"PSS"snaps"PSS"%d.%s",BaseDirectory,id1,cd1);
                    }
                     break;
+  case FCEUMKF_FDS:if(odirs[FCEUIOD_NV])
+                   sprintf((char*)ret,"%s"PSS"%s.fds",odirs[FCEUIOD_NV],FileBase);
+                  else
+                   sprintf((char*)ret,"%s"PSS"sav"PSS"%s.fds",BaseDirectory,FileBase);
+                  break;
   case FCEUMKF_SAV:if(odirs[FCEUIOD_NV])
                    {
                     sprintf(((char*)ret),"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
index 2a874ff..14ca5f0 100644 (file)
--- a/general.h
+++ b/general.h
@@ -12,3 +12,5 @@ char *FCEU_MakeFName(int type, int id1, char *cd1);
 #define FCEUMKF_FDSROM 5
 #define FCEUMKF_PALETTE        6
 #define FCEUMKF_GGROM  7
+#define FCEUMKF_IPS    8
+#define FCEUMKF_FDS    9
diff --git a/git.h b/git.h
index 5dbc2b7..bbe6405 100644 (file)
--- a/git.h
+++ b/git.h
@@ -1,22 +1,29 @@
-#ifndef __FCEU_GIT
-#define __FCEU_GIT
-/* Mmm...git. Almost as funny as "gimp". */
-#define GIT_CART        0      /* Cart. */
-#define GIT_VSUNI       1      /* VS Unisystem. */
-#define GIT_FDS         2      /* Famicom Disk System. */
-#define GIT_NSF         3      /* NES Sound Format. */
-
-#define GIV_NTSC       0       /* NTSC emulation. */
-#define GIV_PAL                1       /* PAL emulation. */
-#define GIV_USER       2       /* What was set by FCEUI_SetVidSys(). */
-       
-typedef struct {
-       char *name;
-        int type;       /* GIT_* */
-        int vidsys;     /* Current emulated video system; GIV_* */
-        int input[2];   /* Desired input for emulated input ports 1 and 2; -1
-                           for unknown desired input. */
-       int inputfc;    /* Desired Famicom expansion port device. -1 for unknown
-                          desired input. */
-} FCEUGI;
-#endif
+#ifndef __FCEU_GIT\r
+#define __FCEU_GIT\r
+/* Mmm...git. Almost as funny as "gimp". */\r
+#define GIT_CART  0  /* Cart. */\r
+#define GIT_VSUNI       1  /* VS Unisystem. */\r
+#define GIT_FDS   2  /* Famicom Disk System. */\r
+#define GIT_NSF   3  /* NES Sound Format. */\r
+\r
+#define GIV_NTSC  0  /* NTSC emulation. */\r
+#define GIV_PAL    1  /* PAL emulation. */\r
+#define GIV_USER  2  /* What was set by FCEUI_SetVidSys(). */\r
+       \r
+typedef struct {\r
+  uint8 *name;  /* Game name, UTF8 encoding */\r
+\r
+        int type;       /* GIT_* */\r
+        int vidsys;     /* Current emulated video system; GIV_* */\r
+        int input[2];   /* Desired input for emulated input ports 1 and 2; -1\r
+                           for unknown desired input. */\r
+  int inputfc;  /* Desired Famicom expansion port device. -1 for unknown\r
+                          desired input. */\r
+  int cspecial;  /* Special cart expansion: DIP switches, barcode\r
+                          reader, etc.\r
+                       */\r
+       uint8 MD5[16];\r
+  int soundrate;  /* For Ogg Vorbis expansion sound wacky support.  0 for default. */\r
+  int soundchan;  /* Number of sound channels. */\r
+} FCEUGI;\r
+#endif\r
diff --git a/ines-bad.h b/ines-bad.h
new file mode 100644 (file)
index 0000000..20f0cf7
--- /dev/null
@@ -0,0 +1,38 @@
+{ 0xecf78d8a13a030a6LL, "Ai Sensei no Oshiete", INESB_HACKED },
+{ 0x10f90ba5bd55c22eLL, "Alien Syndrome", INESB_HACKED },
+{ 0x4712856d3e12f21fLL, "Akumajou Densetsu", INESB_HACKED },
+{ 0x0d69ab3ad28ad1c2LL, "Banana", INESB_INCOMPLETE },
+{ 0x85d2c348a161cdbfLL, "Bio Senshi Dan", INESB_HACKED },
+{ 0x18fdb7c16aa8cb5cLL, "Bucky O'Hare", INESB_CORRUPT },
+{ 0xe27c48302108d11bLL, "Chibi Maruko Chan", INESB_HACKED },
+{ 0x9d1f505c6ba507bfLL, "Contra", INESB_HACKED },
+{ 0x60936436d3ea0ab6LL, "Crisis Force", INESB_HACKED },
+{ 0xcf31097ddbb03c5dLL, "Crystalis (Prototype)", INESB_CORRUPT },
+{ 0x92080a8ce94200eaLL, "Digital Devil Story II", INESB_HACKED },
+{ 0x97f133d8bc1c28dbLL, "Dragon Ball", INESB_HACKED },
+{ 0x6c2a2f95c2fe4b6eLL, "Dragon Ball", INESB_HACKED },
+{ 0x767aaff62963c58fLL, "Dragon Ball", INESB_HACKED },
+{ 0x500b267abb323005LL, "Dragon Warrior 4", INESB_CORRUPT },
+{ 0x02bdcf375704784bLL, "Erika to Satoru no Yume Bouken", INESB_HACKED },
+{ 0xd4fea9d2633b9186LL, "Famista 91", INESB_HACKED },
+{ 0xfdf8c812839b61f0LL, "Famista 92", INESB_HACKED },
+{ 0xb5bb1d0fb47d0850LL, "Famista 93", INESB_HACKED },
+{ 0x30471e773f7cdc89LL, "Famista 94", INESB_HACKED },
+{ 0x76c5c44ffb4a0bd7LL, "Fantasy Zone", INESB_HACKED },
+{ 0x27da2b0c500dc346LL, "Fire Emblem", INESB_HACKED },
+{ 0xb470bfb90e2b1049LL, "Fire Emblem Gaiden", INESB_HACKED },
+{ 0x23214fe456fba2ceLL, "Ganbare Goemon 2", INESB_HACKED },
+{ 0xbf8b22524e8329d9LL, "Ganbare Goemon Gaiden", INESB_HACKED },
+{ 0xa97041c3da0134e3LL, "Gegege no Kitarou 2", INESB_INCOMPLETE },
+{ 0x805db49a86db5449LL, "Goonies", INESB_HACKED },
+{ 0xc5abdaa65ac49b6bLL, "Gradius 2", INESB_HACKED },
+{ 0x04afae4ad480c11cLL, "Gradius 2", INESB_HACKED },
+{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
+{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
+{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
+{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
+{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },
+{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
+{ 0x103fc85d978b861bLL, "Sweet Home", INESB_CORRUPT },
+{ 0xfffda4407d80885aLL, "Sweet Home", INESB_CORRUPT },
+{ 0, 0, 0 }
diff --git a/ines-correct.h b/ines-correct.h
new file mode 100644 (file)
index 0000000..666cf00
--- /dev/null
@@ -0,0 +1,194 @@
+    {0x9cbadc25,5,8},  /* JustBreed */
+
+{0x6e68e31a,16,8},     /* Dragon Ball 3*/
+{0x3f15d20d,153,8},    /* Famicom Jump 2 */
+    {0x983d8175,157,8},  /* Datach Battle Rush */
+    {0x894efdbc,157,8},  /* Datach Crayon Shin Chan */
+    {0x19e81461,157,8},  /* Datach DBZ */
+    {0xbe06853f,157,8},  /* Datach J-League */
+    {0x0be0a328,157,8},  /* Datach SD Gundam Wars */
+    {0x5b457641,157,8},  /* Datach Ultraman Club */
+    {0xf51a7f46,157,8},  /* Datach Yuu Yuu Hakusho */
+
+    {0xe62e3382,71,-1},  /* Mig-29 Soviet Fighter */
+    {0x21a653c7,4,-1},  /* Super Sky Kid */
+
+{0xdd4d9a62,209,-1},   /* Shin Samurai Spirits 2 */
+    {0x063b1151,209,-1},  /* Power Rangers 4 */
+    {0xdd8ced31,209,-1},  /* Power Rangers 3 */
+
+{0x60bfeb0c,90,-1},     /* MK 2*/
+    {0x0c47946d,210,-1},  /* Chibi Maruko Chan */
+    {0xbd523011,210,-1},  /* Dream Master */
+{0xc247cc80,210,-1},   /* Family Circuit '91 */
+    {0x6ec51de5,210,-1},  /* Famista '92 */
+    {0xadffd64f,210,-1},  /* Famista '93 */
+    {0x429103c9,210,-1},  /* Famista '94 */
+    {0x81b7f1a8,210,-1},  /* Heisei Tensai Bakabon */
+    {0x2447e03b,210,-1},  /* Top Striker */
+    {0x1dc0f740,210,-1},  /* Wagyan Land 2 */
+    {0xd323b806,210,-1},  /* Wagyan Land 3 */
+    {0x07eb2c12,208,-1},  /* Street Fighter IV */
+    {0x96ce586e,189,8},  /* Street Fighter 2 YOKO */
+    {0x7678f1d5,207,8},  /* Fudou Myouou Den */
+    {0x276237b3,206,0},  /* Karnov */
+    {0x4e1c1e3c,206,0},  /* Karnov */
+
+        /* Some entries to sort out the minor 33/48 mess. */
+{0xaebd6549,48,8},     /* Bakushou!! Jinsei Gekijou 3 */
+    {0x6cdc0cd9,48,8},  /* Bubble Bobble 2 */
+    //{0x10e24006,48,8},  /* Flintstones 2 - bad dump? */
+    {0x40c0ad47,48,8},  /* Flintstones 2 */
+    {0xa7b0536c,48,8},  /* Don Doko Don 2 */
+    {0x99c395f9,48,8},  /* Captain Saver */
+    {0x1500e835,48,8},  /* Jetsons (J) */
+
+  {0x637134e8,193,1},  /* Fighting Hero */
+  {0xcbf4366f,158,8},  /* Alien Syndrome (U.S. unlicensed) */
+  {0xb19a55dd,64,8},  /* Road Runner */
+  //{0x3eafd012,116,-1},  /* AV Girl Fighting */
+  {0x1d0f4d6b,2,1},  /* Black Bass thinging */
+  {0xf92be3ec,64,-1},  /* Rolling Thunder */
+  {0x345ee51a,245,-1},  /* DQ4c */
+  {0xf518dd58,7,8},  /* Captain Skyhawk */
+  {0x7ccb12a3,43,-1},  /* SMB2j */
+  {0x6f12afc5,235,-1},  /* Golden Game 150-in-1 */
+        {0xccc03440,156,-1},   
+  {0xc9ee15a7,3,-1},  /* 3 is probably best.  41 WILL NOT WORK. */
+
+    {0x3e1271d5,79,1},  /* Tiles of Fate */
+  {0x8eab381c,113,1},  /* Death Bots */
+
+  {0xd4a76b07,79,0},  /* F-15 City Wars*/
+        {0xa4fbb438,79,0},
+
+  {0x1eb4a920,79,1},  /* Double Strike */
+  {0x345d3a1a,11,1},  /* Castle of Deceit */
+  {0x62ef6c79,232,8},  /* Quattro Sports -Aladdin */
+  {0x5caa3e61,144,1},  /* Death Race */
+  {0xd2699893,88,0},  /*  Dragon Spirit */
+
+{0x2f27cdef,155,8},  /* Tatakae!! Rahmen Man */
+    {0xcfd4a281,155,8},  /* Money Game.  Yay for money! */
+    {0xd1691028,154,8},  /* Devil Man */
+
+  {0xc68363f6,180,0},  /* Crazy Climber */
+  {0xbe939fce,9,1},  /* Punchout*/
+  {0x5e66eaea,13,1},  /* Videomation */
+  {0xaf5d7aa2,-1,0},  /* Clu Clu Land */
+
+{0xc2730c30,34,0},  /* Deadly Towers */
+{0x932ff06e,34,1},  /* Classic Concentration */
+{0x4c7c1af3,34,1},  /* Caesar's Palace */
+        
+{0x15141401,4,8},       /* Asmik Kun Land */
+{0x59280bec,4,8},       /* Jackie Chan */
+{0x4cccd878,4,8},  /* Cat Ninden Teyandee */
+{0x9eefb4b4,4,8},  /* Pachi Slot Adventure 2 */
+{0x5337f73c,4,8},  /* Niji no Silk Road */
+{0x7474ac92,4,8},  /* Kabuki: Quantum Fighter */
+
+{0xbb7c5f7a,89,8},  /* Mito Koumon or something similar */
+
+/* Probably a Namco MMC3-workalike */
+{0xa5e6baf9,4,1|4},  /* Dragon Slayer 4 */
+{0xe40b4973,4,1|4},  /* Metro Cross */
+{0xd97c31b0,4,1|4},  /* Rasaaru Ishii no Childs Quest */
+
+{0x84382231,9,0},  /* Punch Out (J) */
+
+{0xe28f2596,0,1},  /* Pac Land (J) */
+{0xfcdaca80,0,0},  /* Elevator Action */
+{0xe492d45a,0,0},  /* Zippy Race */
+{0x32fa246f,0,0},  /* Tag Team Pro Wrestling */
+{0xc05a365b,0,0},  /* Exed Exes (J) */
+{0xb3c30bea,0,0},  /* Xevious (J) */
+
+{0x804f898a,2,1},      /* Dragon Unit */
+{0xe1b260da,2,1},  /* Argos no Senshi */
+{0x6d65cac6,2,0},  /* Terra Cresta */
+{0x9ea1dc76,2,0},      /* Rainbow Islands */
+{0x28c11d24,2,1},  /* Sukeban Deka */
+{0x02863604,2,1},      /* Sukeban Deka */
+{0x2bb6a0f8,2,1},      /* Sherlock Holmes */
+{0x55773880,2,1},  /* Gilligan's Island */
+{0x419461d0,2,1},  /* Super Cars */
+{0x6e0eb43e,2,1},  /* Puss n Boots */
+{0x266ce198,2,1},  /* City Adventure Touch */
+
+//{0x48349b0b,1,8},      /* Dragon Quest 2 */
+{0xd09b74dc,1,8},  /* Great Tank (J) */
+{0xe8baa782,1,8},  /* Gun Hed (J) */
+{0x970bd9c2,1,8},      /* Hanjuku Hero */
+{0xcd7a2fd7,1,8},  /* Hanjuku Hero */
+{0x63469396,1,8},  /* Hokuto no Ken 4 */
+{0x291bcd7d,1,8},      /* Pachio Kun 2 */
+{0xf74dfc91,1,-1},      /* Win, Lose, or Draw */
+
+        {0x3f56a392,1,8},      /* Captain Ed (J) */
+        {0x078ced30,1,8},      /* Choujin - Ultra Baseball */
+   {0x391aa1b8,1,8},  /* Bloody Warriors (J) */
+   {0x61a852ea,1,8},  /* Battle Stadium - Senbatsu Pro Yakyuu */
+   {0xfe364be5,1,8},  /* Deep Dungeon 4 */
+   {0xd8ee7669,1,8},  /* Adventures of Rad Gravity */
+   {0xa5e8d2cd,1,8},  /* Breakthru */
+   {0xf6fa4453,1,8},  /* Bigfoot */
+   {0x37ba3261,1,8},  /* Back to the Future 2 and 3 */
+   {0x934db14a,1,-1},  /* All-Pro Basketball */
+   {0xe94d5181,1,8},  /* Mirai Senshi - Lios */
+   {0x7156cb4d,1,8},  /* Muppet Adventure Carnival thingy */
+   {0x5b6ca654,1,8},  /* Barbie rev X*/
+   {0x57c12280,1,8},  /* Demon Sword */
+   {0x70f67ab7,1,8},  /* Musashi no Bouken */
+   {0xa9a4ea4c,1,8},  /* Satomi Hakkenden */
+   {0xcc3544b0,1,8},  /* Triathron */
+
+   {0x1d41cc8c,3,1},  /* Gyruss */
+   {0xd8eff0df,3,1},  /* Gradius (J) */
+   {0xdbf90772,3,0},  /* Alpha Mission */
+   {0xd858033d,3,0},  /* Armored Scrum Object */
+   {0xcf322bb3,3,1},  /* John Elway's Quarterback */
+   {0x9bde3267,3,1},  /* Adventures of Dino Riki */
+   {0x02cc3973,3,1},  /* Ninja Kid */
+   {0xb5d28ea2,3,1},  /* Mystery Quest - mapper 3?*/
+   {0xbc065fc3,3,1},  /* Pipe Dream */
+
+   {0x5b837e8d,1,8},  /* Alien Syndrome */
+   {0x283ad224,32,8},  /* Ai Sensei no Oshiete */
+   {0x5555fca3,32,8},  /* "" ""    */
+        {0x243a8735,32,0x10|4}, /* Major League */
+
+{0x6bc65d7e,66,1},  /* Youkai Club*/
+{0xc2df0a00,66,1},  /* Bio Senshi Dan(hacked) */
+{0xbde3ae9b,66,1},  /* Doraemon */
+{0xd26efd78,66,1},  /* SMB Duck Hunt */
+{0x811f06d9,66,1},  /* Dragon Power */
+{0x3293afea,66,1},  /* Mississippi Satsujin Jiken */
+{0xe84274c5,66,1},  /* "" "" */
+{0x9552e8df,66,1},  /* Dragon Ball */
+
+        {0xba51ac6f,78,2},
+   {0x3d1c3137,78,8},  /* Uchuusen - Cosmo Carrier */
+
+   {0xbda8f8e4,152,8},  /* Gegege no Kitarou 2 */
+   {0x026c5fca,152,8},  /* Saint Seiya Ougon Densetsu */
+   {0x0f141525,152,8},  /* Arkanoid 2 (Japanese) */
+   {0xb1a94b82,152,8},  /* Pocket Zaurus */
+
+   {0xbba58be5,70,-1},  /* Family Trainer - Manhattan Police */
+   {0x370ceb65,70,-1},  /* Family Trainer - Meiro Dai Sakusen */
+   {0xdd8ed0f7,70,1},  /* Kamen Rider Club */
+
+   {0x90c773c1,118,-1},  /* Goal! 2 */
+   {0xb9b4d9e0,118,-1},  /* NES Play Action Football */
+   {0x78b657ac,118,-1},  /* Armadillo */
+   {0x37b62d04,118,-1},  /* Ys 3 */
+        {0x07d92c31,118,-1},   /* RPG Jinsei Game */
+   {0x2705eaeb,234,-1},  /* Maxi 15 */
+   {0x404b2e8b,4,2},  /* Rad Racer 2 */
+   {0x2cc381f6,191,-1},  /* Sugoro Quest - Dice no Senshitachi (As).nes */
+   {0x555a555e,191,-1},
+   {0xa912b064,51|0x800,8},  /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */
+   {0xc5e5c5b2,115,-1}, /* Bao Qing Tian (As).nes */
+
+        {0,-1,-1}
diff --git a/ines.c b/ines.c
index 3ffcfce..679fb92 100644 (file)
--- a/ines.c
+++ b/ines.c
-/* FCE Ultra - NES/Famicom Emulator
- *
- * Copyright notice for this file:
- *  Copyright (C) 1998 BERO
- *  Copyright (C) 2002 Ben Parnell
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef GP2X
-#include <unistd.h>
-#endif
-
-#include "types.h"
-#include "x6502.h"
-#include "fce.h"
-#define INESPRIV
-#include "ines.h"
-#include "version.h"
-#include "svga.h"
-#include "general.h"
-#include "state.h"
-#include "file.h"
-#include "memory.h"
-#include "cart.h"
-#include "crc32.h"
-#include "cheat.h"
-
-static DECLFR(VSRead);
-
-static uint8 *trainerpoo=0;
-static uint8 *ROM=NULL;
-uint8 *VROM=NULL;
-
-
-static uint32 ROM_size;
-uint32 VROM_size;
-
-static void CheckVSUni(void);
-static int MMC_init(int type);
-void (*MapClose)(void);
-void (*MapperReset)(void);
-
-static int MapperNo;
-static int SaveGame=0;
-
-static iNES_HEADER head;
-
-/*  MapperReset() is called when the NES is reset(with the reset button).
-    Mapperxxx_init is called when the NES has been powered on.
-*/
-
-static void iNESGI(int h)
-{
- switch(h)
- {
-  case GI_RESETM2:
-               if(MapperReset)
-                MapperReset();
-               break;
-  case GI_POWER:
-               SetReadHandler(0x8000,0xFFFF,CartBR);
-                MMC_init(MapperNo);
-               break;
-  case GI_CLOSE:
-               {
-                FILE *sp;
-
-                if(ROM) {free(ROM);ROM=0;}
-                if(VROM) {free(VROM);VROM=0;}
-
-                if(SaveGame)
-                {
-                 char *soot;
-                 SaveGame=0;
-                 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
-                 sp=fopen(soot,"wb");
-                 if (sp==NULL)
-                  FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
-                 else
-                 {
-                  void *ptr;
-                  uint32 amount;
-                  ptr=WRAM;
-                  amount=8192;
-
-                  if(MapperNo==1)
-                  {
-                    extern uint8 MMC1WRAMsize;
-                    if(MMC1WRAMsize==2) ptr=WRAM+8192;
-                  }
-                  else if(MapperNo==5)
-                  {
-                   extern uint8 MMC5WRAMsize;
-                   if(MMC5WRAMsize==4)
-                    amount=32768;
-                  }
-
-                  fwrite(ptr,1,amount,sp);
-                  fclose(sp);
-#ifdef GP2X
-                  sync();
-#endif
-                 }
-                }
-                if(MapClose) MapClose();
-                if(trainerpoo) {free(trainerpoo);trainerpoo=0;}
-               }
-               break;
-     }
-}
-
-uint32 iNESGameCRC32;
-
-struct CRCMATCH        {
-       uint32 crc;
-       char *name;
-};
-
-static void CheckBad(void)
-{
- int x;
- #define CRCNT 7
- struct CRCMATCH tab[CRCNT]={
-       {0x28d183ac,"Antarctic Adventure"},
-       {0x7095ac65,"Akumajo Densetsu"},
-       {0x1bd7ed5a,"Gradius 2"},
-       {0x81c3aa66,"Crisis Force"},
-       {0xfe3088df,"Fire Emblem Gaiden"},
-       {0xfa8339a5,"Bucky O'Hare"},
-       {0x3c539d78,"Ganbare Goemon 2"},
-       };
-  for(x=0;x<CRCNT;x++)
-   if(tab[x].crc == iNESGameCRC32)
-   {
-    FCEU_PrintError("The copy of the game you have loaded, %s, is a bad dump, has been hacked, or both.  It will not work correctly on FCE Ultra.  Use a good copy of the ROM image instead.",tab[x].name);
-    break;
-   }
-}
-
-struct INPSEL {
-       uint32 crc32;
-       int input1;
-       int input2;
-       int inputfc;
-};
-
-/* This is mostly for my personal use.  So HA. */
-static void SetInput(void)
-{
- static struct INPSEL moo[]=
-       {
-        {0xad9c63e2,SI_GAMEPAD,-1,SIFC_SHADOW},        /* Space Shadow */
-        {0x24598791,-1,SI_ZAPPER,0},   /* Duck Hunt */
-        {0xff24d794,-1,SI_ZAPPER,0},   /* Hogan's Alley */
-        {0xbeb8ab01,-1,SI_ZAPPER,0},   /* Gumshoe */
-        {0xde8fd935,-1,SI_ZAPPER,0},   /* To the Earth */
-        {0xedc3662b,-1,SI_ZAPPER,0},   /* Operation Wolf */
-        {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,0},   /* The Lone Ranger */
-        {0xb8b9aca3,-1,SI_ZAPPER,0},  /* Wild Gunman */
-        {0x5112dc21,-1,SI_ZAPPER,0},  /* Wild Gunman */
-        {0x4318a2f8,-1,SI_ZAPPER,0},  /* Barker Bill's Trick Shooting */
-        {0x5ee6008e,-1,SI_ZAPPER,0},  /* Mechanized Attack */
-        {0x3e58a87e,-1,SI_ZAPPER,0},  /* Freedom Force */
-        {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,0},   /* Shooting Range */
-        {0x74bea652,SI_GAMEPAD,SI_ZAPPER,0},   /* Supergun 3-in-1 */
-        {0x32fb0583,-1,SI_ARKANOID,0}, /* Arkanoid(NES) */
-        {0xd89e5a67,-1,-1,SIFC_ARKANOID}, /* Arkanoid (J) */
-        {0x0f141525,-1,-1,SIFC_ARKANOID}, /* Arkanoid 2(J) */
-
-        {0xf7606810,-1,-1,SIFC_FKB},   /* Family BASIC 2.0A */
-        {0x895037bc,-1,-1,SIFC_FKB},   /* Family BASIC 2.1a */
-        {0xb2530afc,-1,-1,SIFC_FKB},   /* Family BASIC 3.0 */
-        {0,-1,-1,-1}
-       };
- int x=0;
-
- while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0)
- {
-  if(moo[x].crc32==iNESGameCRC32)
-  {
-   FCEUGameInfo.input[0]=moo[x].input1;
-   FCEUGameInfo.input[1]=moo[x].input2;
-   FCEUGameInfo.inputfc=moo[x].inputfc;
-   break;
-  }
-  x++;
- }
-}
-
-struct CHINF {
-       uint32 crc32;
-       int32 mapper;
-       int32 mirror;
-};
-
-#define SAVCNT 14
-static void CheckHInfo(void)
-{
- /* ROM images that have the battery-backed bit set in the header that really
-    don't have battery-backed RAM is not that big of a problem, so I'll
-    treat this differently.
- */
-
- static uint32 savie[SAVCNT]=
-       {
-        0x7cab2e9b,0x3ee43cda,0xe1383deb,      /* Mouryou Senki Madara */
-        0x3b3f88f0,0x2545214c,                 /* Dragon Warrior PRG 0 and 1 */
-        0x8c5a784e,    /* DW 2 */
-        0xa86a5318,    /* DW 3 */
-        0x506e259d,    /* DW 4 */
-        0xcebd2a31,0xb8b88130, /* Final Fantasy */
-        0x466efdc2,    /* FF(J) */
-        0xc9556b36,    /* FF1+2*/
-        0xd29db3c7,    /* FF2 */
-        0x57e220d0,    /* FF3 */
-       };
-
- static struct CHINF moo[]=
-       {
-        {0xc68363f6,180,0},    /* Crazy Climber */
-        {0xbe939fce,9,1},      /* Punchout*/
-        {0x5e66eaea,13,1},     /* Videomation */
-        {0xaf5d7aa2,-1,0},     /* Clu Clu Land */
-
-        {0xc2730c30,34,0},     /* Deadly Towers */
-        {0x932ff06e,34,1},     /* Classic Concentration */
-        {0x4c7c1af3,34,1},     /* Caesar's Palace */
-        {0x9ea1dc76,2,0},      /* Rainbow Islands */
-
-        {0x9eefb4b4,4,8},      /* Pachi Slot Adventure 2 */
-        {0x5337f73c,4,8},      /* Niji no Silk Road */
-        {0x7474ac92,4,8},      /* Kabuki: Quantum Fighter */
-
-        {0x970bd9c2,1,8},      /* Hanjuku Hero */
-
-        {0xbb7c5f7a,89,8},     /* Mito Koumon or something similar */
-        /* Probably a Namco MMC3-workalike */
-        {0xa5e6baf9,4,1|4},    /* Dragon Slayer 4 */
-        {0xe40b4973,4,1|4},    /* Metro Cross */
-         {0xd97c31b0,4,1|4},    /* Rasaaru Ishii no Childs Quest */
-
-        {0x84382231,9,0},      /* Punch Out (J) */
-
-        {0xfcdaca80,0,0},      /* Elevator Action */
-        {0xe492d45a,0,0},      /* Zippy Race */
-        {0x32fa246f,0,0},      /* Tag Team Pro Wrestling */
-        {0x6d65cac6,2,0},      /* Terra Cresta */
-        {0x28c11d24,2,1},      /* Sukeban Deka */
-         {0x02863604,2,1},      /* Sukeban Deka */
-         {0x2bb6a0f8,2,1},      /* Sherlock Holmes */
-        {0x55773880,2,1},      /* Gilligan's Island */
-        {0x419461d0,2,1},      /* Super Cars */
-        {0x6e0eb43e,2,1},      /* Puss n Boots */
-        {0xfc3e5c86,2,1},      /* Trojan */
-
-        {0x291bcd7d,1,8},      /* Pachio Kun 2 */
-        {0xf74dfc91,1,-1},     /* Win, Lose, or Draw */
-
-        {0x59280bec,4,8},      /* Jackie Chan */
-
-        {0xfe364be5,1,8},      /* Deep Dungeon 4 */
-        {0xd8ee7669,1,8},      /* Adventures of Rad Gravity */
-        {0xa5e8d2cd,1,8},      /* Breakthru */
-        {0xf6fa4453,1,8},      /* Bigfoot */
-        {0x37ba3261,1,8},      /* Back to the Future 2 and 3 */
-        {0x934db14a,1,-1},     /* All-Pro Basketball */
-        {0xe94d5181,1,8},      /* Mirai Senshi - Lios */
-        {0x7156cb4d,1,8},      /* Muppet Adventure Carnival thingy */
-        {0x5b6ca654,1,8},      /* Barbie rev X*/
-        {0x57c12280,1,8},      /* Demon Sword */
-
-        {0xcf322bb3,3,1},      /* John Elway's Quarterback */
-        {0x9bde3267,3,1},      /* Adventures of Dino Riki */
-        {0x02cc3973,3,8},      /* Ninja Kid */
-        {0xb5d28ea2,3,1},      /* Mystery Quest - mapper 3?*/
-        {0xbc065fc3,3,1},      /* Pipe Dream */
-
-        {0x5b837e8d,1,8},      /* Alien Syndrome */
-        {0x283ad224,32,8},     /* Ai Sensei no Oshiete */
-        {0x5555fca3,32,8},     /* "" ""                */
-        {0x243a8735,32,0x10|4}, /* Major League */
-
-        {0x6bc65d7e,66,1},     /* Youkai Club*/
-        {0xc2df0a00,66,1},     /* Bio Senshi Dan(hacked) */
-        {0xbde3ae9b,66,1},     /* Doraemon */
-        {0xd26efd78,66,1},     /* SMB Duck Hunt */
-        {0x811f06d9,66,1},     /* Dragon Power */
-
-        {0x3293afea,66,1},     /* Mississippi Satsujin Jiken */
-        {0xe84274c5,66,1},     /* "" "" */
-
-
-        {0x6e68e31a,16,8},     /* Dragon Ball 3*/
-
-        {0xba51ac6f,78,2},
-        {0x3d1c3137,78,8},
-
-        {0xbda8f8e4,152,8},    /* Gegege no Kitarou 2 */
-        {0x026c5fca,152,8},    /* Saint Seiya Ougon Densetsu */
-        {0x0f141525,152,8},    /* Arkanoid 2 (Japanese) */
-        {0xb1a94b82,152,8},    /* Pocket Zaurus */
-
-        {0x3f15d20d,153,8},    /* Famicom Jump 2 */
-
-        {0xbba58be5,70,-1},    /* Family Trainer - Manhattan Police */
-        {0x370ceb65,70,-1},    /* Family Trainer - Meiro Dai Sakusen */
-        {0xdd8ed0f7,70,1},     /* Kamen Rider Club */
-
-        {0x90c773c1,118,-1},   /* Goal! 2 */
-        {0xb9b4d9e0,118,-1},   /* NES Play Action Football */
-        {0x78b657ac,118,-1},   /* Armadillo */
-        {0x37b62d04,118,-1},   /* Ys 3 */
-        {0x07d92c31,118,-1},   /* RPG Jinsei Game */
-        {0x2705eaeb,234,-1},   /* Maxi 15 */
-        {0x404b2e8b,4,2},      /* Rad Racer 2 */
-
-        {0x1356f6a6,4,8},      /* "Cattou Ninden Teyandee" English tranlation.
-                                   Should I have even bothered to do this? */
-        {0x50fd4fd6,4,8},      /* "" "" */
-
-        {0xa912b064,51|0x800,8},       /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */
-        {0,-1,-1}
-       };
- int tofix=0;
- int x=0;
-
- do
- {
-  if(moo[x].crc32==iNESGameCRC32)
-  {
-   if(moo[x].mapper>=0)
-   {
-    if(moo[x].mapper&0x800 && VROM_size)
-    {
-     VROM_size=0;
-     free(VROM);
-     tofix|=8;
-    }
-    if(MapperNo!=(moo[x].mapper&0xFF))
-    {
-     tofix|=1;
-     MapperNo=moo[x].mapper&0xFF;
-    }
-   }
-   if(moo[x].mirror>=0)
-   {
-    if(moo[x].mirror==8)
-    {
-     if(Mirroring==2)  /* Anything but hard-wired(four screen). */
-     {
-      tofix|=2;
-      Mirroring=0;
-     }
-    }
-    else if(Mirroring!=moo[x].mirror)
-    {
-     if(Mirroring!=(moo[x].mirror&~4))
-      if((moo[x].mirror&~4)<=2)        /* Don't complain if one-screen mirroring
-                                  needs to be set(the iNES header can't
-                                  hold this information).
-                               */
-       tofix|=2;
-     Mirroring=moo[x].mirror;
-    }
-   }
-   break;
-  }
-  x++;
- } while(moo[x].mirror>=0 || moo[x].mapper>=0);
-
- for(x=0;x<SAVCNT;x++)
- {
-  if(savie[x]==iNESGameCRC32)
-  {
-   if(!(head.ROM_type&2))
-   {
-    tofix|=4;
-    head.ROM_type|=2;
-   }
-  }
- }
-
- /* Games that use these iNES mappers tend to have the four-screen bit set
-    when it should not be.
- */
- if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2))
- {
-  Mirroring=0;
-  tofix|=2;
- }
-
- if(tofix)
- {
-  char gigastr[768];
-  strcpy(gigastr,"The iNES header contains incorrect information.  For now, the information will be corrected in RAM.  ");
-  if(tofix&1)
-   sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d.  ",MapperNo);
-  if(tofix&2)
-  {
-   char *mstr[3]={"Horizontal","Vertical","Four-screen"};
-   sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\".  ",mstr[Mirroring&3]);
-  }
-  if(tofix&4)
-   strcat(gigastr,"The battery-backed bit should be set.  ");
-  if(tofix&8)
-   strcat(gigastr,"This game should not have any CHR ROM.  ");
-  strcat(gigastr,"\n");
-  FCEUD_PrintError(gigastr);
- }
-}
-
-int iNESLoad(char *name, int fp)
-{
-        FILE *sp;
-
-       if(FCEU_fread(&head,1,16,fp)!=16)
-        return 0;
-
-        if(memcmp(&head,"NES\x1a",4))
-         return 0;
-
-        if(!memcmp((char *)(&head)+0x7,"DiskDude",8))
-        {
-         memset((char *)(&head)+0x7,0,0x9);
-        }
-
-        if(!memcmp((char *)(&head)+0x7,"demiforce",9))
-        {
-         memset((char *)(&head)+0x7,0,0x9);
-        }
-
-        if(!memcmp((char *)(&head)+0xA,"Ni03",4))
-        {
-         if(!memcmp((char *)(&head)+0x7,"Dis",3))
-          memset((char *)(&head)+0x7,0,0x9);
-         else
-          memset((char *)(&head)+0xA,0,0x6);
-        }
-
-        if(!head.ROM_size)
-         head.ROM_size++;
-
-        ROM_size = head.ROM_size;
-        VROM_size = head.VROM_size;
-       ROM_size=uppow2(ROM_size);
-
-        if(VROM_size)
-        VROM_size=uppow2(VROM_size);
-
-        MapperNo = (head.ROM_type>>4);
-        MapperNo|=(head.ROM_type2&0xF0);
-
-        Mirroring = (head.ROM_type&1);
-       if(head.ROM_type&8) Mirroring=2;
-
-        if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
-        return 0;
-
-        if (VROM_size)
-         if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
-        {
-         free(ROM);
-         return 0;
-        }
-
-        memset(ROM,0xFF,ROM_size<<14);
-        if(VROM_size) memset(VROM,0xFF,VROM_size<<13);
-        if(head.ROM_type&4)    /* Trainer */
-       {
-        if(!(trainerpoo=FCEU_malloc(512)))
-         return(0);
-        FCEU_fread(trainerpoo,512,1,fp);
-       }
-       ResetCartMapping();
-       SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);
-        SetupCartPRGMapping(1,WRAM,8192,1);
-
-        FCEU_fread(ROM,0x4000,head.ROM_size,fp);
-
-       if(VROM_size)
-        FCEU_fread(VROM,0x2000,head.VROM_size,fp);
-
-        printf("File %s loaded.\n",name);
-
-       iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);
-       if(VROM_size)
-        iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);
-        printf("\n PRG ROM:  %3d x 16k\n CHR ROM:  %3d x  8k\n ROM CRC32:  %08x\n Mapper:  %d\n Mirroring: %s\n",head.ROM_size,head.VROM_size,iNESGameCRC32,MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal");
-        if(head.ROM_type&2) puts(" Battery-backed.");
-        if(head.ROM_type&4) puts(" Trained.");
-       puts("");
-
-       CheckBad();
-       SetInput();
-       CheckHInfo();
-       CheckVSUni();
-        //if(MapperNo!=4 && MapperNo!=118 && MapperNo!=119) exit(1); // Testing
-
-       /* Must remain here because above functions might change value of
-          VROM_size and free(VROM).
-       */
-       if(VROM_size)
-         SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);
-
-        if(Mirroring==2)
-         SetupCartMirroring(4,1,ExtraNTARAM);
-        else if(Mirroring>=0x10)
-        SetupCartMirroring(2+(Mirroring&1),1,0);
-       else
-         SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);
-
-        if(MapperNo==5) DetectMMC5WRAMSize();
-       else if(MapperNo==1) DetectMMC1WRAMSize();
-
-        if(head.ROM_type&2)
-        {
-         char *soot;
-
-         SaveGame=1;
-         soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
-         sp=fopen(soot,"rb");
-         if(sp!=NULL)
-         {
-         void *ptr;
-         uint32 amount;
-
-         ptr=WRAM;
-         amount=8192;
-         if(MapperNo==1)
-         {
-          extern uint8 MMC1WRAMsize;
-          if(MMC1WRAMsize==2) ptr=WRAM+8192;
-         }
-         else if(MapperNo==5)
-         {
-          extern uint8 MMC5WRAMsize;
-           if(MMC5WRAMsize==4)
-           amount=32768;
-         }
-          if(fread(ptr,1,amount,sp)==amount)
-           printf("  WRAM Save File \"%s\" loaded...\n",soot);
-          fclose(sp);
-         }
-
-   }
-       GameInterface=iNESGI;
-        return 1;
-}
-
-#include       "banksw.h"
-
-
-void FASTAPASS(1) onemir(uint8 V)
-{
-       if(Mirroring==2) return;
-        if(V>1)
-         V=1;
-       Mirroring=0x10|V;
-       setmirror(MI_0+V);
-}
-
-void FASTAPASS(1) MIRROR_SET2(uint8 V)
-{
-       if(Mirroring==2) return;
-       Mirroring=V;
-       setmirror(V);
-}
-
-void FASTAPASS(1) MIRROR_SET(uint8 V)
-{
-       if(Mirroring==2) return;
-       V^=1;
-       Mirroring=V;
-       setmirror(V);
-}
-
-static void NONE_init(void)
-{
-        ROM_BANK16(0x8000,0);
-        ROM_BANK16(0xC000,~0);
-
-        if(VROM_size)
-        VROM_BANK8(0);
-        else
-        setvram8(CHRRAM);
-}
-
-static uint8 secdata[2][32]=
-{
- {
-  0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
-  0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
-  0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
-  0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
- },
- {
-  0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
-  0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- }
-};
-
-static uint8 *secptr;
-
-static void CheckVSUni(void)
-{
-        FCEUGameInfo.type=GIT_VSUNI;
-
-       /* FCE Ultra doesn't complain when headers for these games are bad. */
-       secptr=0;
-       switch(iNESGameCRC32)
-       {
-        default:FCEUGameInfo.type=0;break;
-
-        case 0xffbef374: pale=1;break; /* Castlevania */
-
-        case 0x98e3c75a:
-        case 0x7cff0f84: pale=2;break; /* SMB */
-
-        case 0xef7af338: pale=2;break; /* Ice Climber */
-        case 0xabe1a0c2: FCEUGameInfo.input[0]=SI_ZAPPER;break; /*Duck hunt */
-        case 0x16aa4e2d: pale=7;FCEUGameInfo.input[0]=SI_ZAPPER;break; /* hoganal ^_^ */
-        case 0x2b85420e: pale=3;break; /* Dr Mario */
-
-        case 0xfb0ddde7: pale=2;break;
-        case 0xc95321a8: pale=6;break; /* Excitebike */
-        case 0xb1c4c508: pale=1;break; /* Golf */
-
-        case 0x66471efe: break;
-        case 0xca3e9b1a: pale=7;break; /* Pinball*/
-
-        case 0xf735d926: pale=7; break; /* Gradius */
-
-        case 0x2019fe65:
-        case 0x31678411:MapperNo=68;pale=7;break; /* Platoon */
-
-        case 0x74f713b4:pale=4;break; /* Goonies */
-        case 0x9ae2baa0:pale=5;break; /* Slalom */
-        case 0xe45485a5:secptr=secdata[1];vsdip=0x20;MapperNo=4;break; /* RBI Baseball */
-        case 0x21a653c7:vsdip=0x20;MapperNo=4;break; /* Super Sky Kid */
-         case 0xe9a6f17d:vsdip=0x20;break; /* Tetris */
-
-         case 0x159ef3c1:break; /* Star Luster */
-         case 0x9768e5e0:break; /* Stroke and Match Golf */
-
-        /* FCE Ultra doesn't have correct palettes for the following games. */
-        case 0x0fa322c2:pale=2;break; /* Clu Clu Land */
-
-        case 0x766c2cac:       /* Soccer */
-        case 0x01357944:       /* Battle City */
-        case 0xb2816bf9:break; /* Battle City (Bootleg) */
-
-        case 0x832cf592:FCEUGameInfo.input[0]=SI_ZAPPER;break; /* Freedom Force */
-        case 0x63abf889:break; /* Ladies Golf */
-        case 0x8c0c2df5:pale=2;MapperNo=1;Mirroring=1;break; /* Top Gun */
-        case 0x52c501d0:vsdip=0x80;MapperNo=4;secptr=secdata[0];break;
-                       /* TKO Boxing */
-       }
-
-       if(MapperNo==99)
-        Mirroring=2;
-}
-
-
-static int VSindex;
-
-static DECLFR(VSRead)
-{
- //printf("$%04x, $%04x\n",A,X.PC);
- switch(A)
- {
-  default:
-  case 0x5e00: VSindex=0;return 0xFF;
-  case 0x5e01: return(secptr[(VSindex++)&0x1F]);
- }
-}
-
-static void DoVSHooks(void)
-{
- if(secptr)
-  SetReadHandler(0x5e00,0x5e01,VSRead);
-}
-
-void (*MapInitTab[256])(void)=
-{
-       0,
-       Mapper1_init,Mapper2_init,Mapper3_init,Mapper4_init,
-       Mapper5_init,Mapper6_init,Mapper7_init,Mapper8_init,
-       Mapper9_init,Mapper10_init,Mapper11_init,0,
-       Mapper13_init,0,Mapper15_init,Mapper16_init,
-       Mapper17_init,Mapper18_init,Mapper19_init,0,
-       Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init,
-       Mapper25_init,Mapper26_init,0,0,
-       0,0,0,Mapper32_init,
-       Mapper33_init,Mapper34_init,0,0,
-       0,0,0,Mapper40_init,
-       Mapper41_init,Mapper42_init,Mapper43_init,Mapper44_init,
-       Mapper45_init,Mapper46_init,Mapper47_init,Mapper33_init,Mapper49_init,0,Mapper51_init,Mapper52_init,
-       0,0,0,0,0,0,0,0,
-       0,0,0,Mapper64_init,
-       Mapper65_init,Mapper66_init,Mapper67_init,Mapper68_init,
-       Mapper69_init,Mapper70_init,Mapper71_init,Mapper72_init,
-       Mapper73_init,0,Mapper75_init,Mapper76_init,
-       Mapper77_init,Mapper78_init,Mapper79_init,Mapper80_init,
-       0,Mapper82_init,Mapper83_init,0,
-       Mapper85_init,Mapper86_init,Mapper87_init,Mapper88_init,
-       Mapper89_init,Mapper90_init,0,Mapper92_init,
-       Mapper93_init,Mapper94_init,Mapper95_init,Mapper96_init,
-       Mapper97_init,0,Mapper99_init,0,
-       0,0,0,0,Mapper105_init,0,0,0,
-       0,0,0,Mapper112_init,Mapper113_init,0,0,0,
-       Mapper117_init,Mapper118_init,Mapper119_init,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,Mapper140_init,
-       0,0,0,0,0,0,0,0,
-       0,0,Mapper151_init,Mapper152_init,Mapper153_init,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,Mapper180_init,
-       0,Mapper182_init,0,Mapper184_init,Mapper185_init,0,0,0,
-       Mapper189_init,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,0,0,0,0,
-       0,0,0,0,Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init,
-       Mapper229_init,0,0,Mapper232_init,0,Mapper234_init,Mapper43_init,0,
-       0,0,0,Mapper240_init,0,Mapper242_init,0,0,
-       Mapper245_init,Mapper246_init,0,Mapper248_init,Mapper249_init,Mapper250_init,0,0,0,0,0
-};
-
-static DECLFW(BWRAM)
-{
-                WRAM[A-0x6000]=V;
-}
-
-static DECLFR(AWRAM)
-{
-                return WRAM[A-0x6000];
-}
-
-void (*MapStateRestore)(int version);
-void iNESStateRestore(int version)
-{
- int x;
-
- if(!MapperNo) return;
-
- for(x=0;x<4;x++)
-  setprg8(0x8000+x*8192,PRGBankList[x]);
-
- if(VROM_size)
-  for(x=0;x<8;x++)
-    setchr1(0x400*x,CHRBankList[x]);
-
- switch(Mirroring)
- {
-   case 0:setmirror(MI_H);break;
-   case 1:setmirror(MI_V);break;
-   case 0x12:
-   case 0x10:setmirror(MI_0);break;
-   case 0x13:
-   case 0x11:setmirror(MI_1);break;
- }
- if(MapStateRestore) MapStateRestore(version);
-}
-
-static int MMC_init(int type)
-{
-        int x;
-
-        GameStateRestore=iNESStateRestore;
-        MapClose=0;
-       MapperReset=0;
-        MapStateRestore=0;
-
-        setprg8r(1,0x6000,0);
-
-        SetReadHandler(0x6000,0x7FFF,AWRAM);
-        SetWriteHandler(0x6000,0x7FFF,BWRAM);
-        FCEU_CheatAddRAM(8,0x6000,WRAM);
-
-       /* This statement represents atrocious code.  I need to rewrite
-          all of the iNES mapper code... */
-       IRQCount=IRQLatch=IRQa=0;
-        if(head.ROM_type&2)
-       {
-        extern uint8 MMC5WRAMsize,MMC1WRAMsize;
-        if(type==5 && MMC5WRAMsize==4)
-         memset(GameMemBlock+32768,0,sizeof(GameMemBlock)-32768);
-        else if(type==1 && MMC1WRAMsize==2)
-        {
-         memset(GameMemBlock,0,8192);
-         memset(GameMemBlock+16384,0,sizeof(GameMemBlock)-16384);
-        }
-        else
-          memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192);
-       }
-       else
-         memset(GameMemBlock,0,sizeof(GameMemBlock));
-        if(head.ROM_type&4)
-        memcpy(WRAM+4096,trainerpoo,512);
-
-        NONE_init();
-
-       if(FCEUGameInfo.type==GIT_VSUNI)
-        DoVSHooks();
-        if(type==5)
-        {
-          MMC5HackVROMMask=CHRmask4[0];
-          MMC5HackExNTARAMPtr=MapperExRAM+0x6000;
-          MMC5Hack=1;
-          MMC5HackVROMPTR=VROM;
-          MMC5HackCHRMode=0;
-        }
-        ResetExState();
-        AddExState(WRAM, 8192, 0, "WRAM");
-        if(type==19 || type==5 || type==6 || type==69 || type==85)
-         AddExState(MapperExRAM, 32768, 0, "MEXR");
-        if((!VROM_size || type==6 || type==19 || type==119) &&
-          (type!=13 && type!=96))
-         AddExState(CHRRAM, 8192, 0, "CHRR");
-        if(head.ROM_type&8)
-         AddExState(ExtraNTARAM, 2048, 0, "EXNR");
-
-       /* Exclude some mappers whose emulation code handle save state stuff
-          themselves. */
-       if(type && type!=13 && type!=96)
-       {
-         AddExState(mapbyte1, 32, 0, "MPBY");
-         AddExState(&Mirroring, 1, 0, "MIRR");
-         AddExState(&IRQCount, 4, 1, "IRQC");
-         AddExState(&IRQLatch, 4, 1, "IQL1");
-         AddExState(&IRQa, 1, 0, "IRQA");
-         AddExState(PRGBankList, 4, 0, "PBL");
-         for(x=0;x<8;x++)
-         {
-          char tak[8];
-          sprintf(tak,"CBL%d",x);
-          AddExState(&CHRBankList[x], 2, 1,tak);
-         }
-       }
-
-        if(MapInitTab[type]) MapInitTab[type]();
-        else if(type)
-        {
-         FCEU_PrintError("iNES mapper #%d is not supported at all.",type);
-        }
-        return 1;
-}
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ *  Copyright (C) 1998 BERO\r
+ *  Copyright (C) 2002 Xodnizel\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
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+#include "types.h"\r
+#include "x6502.h"\r
+#include "fce.h"\r
+#include "cart.h"\r
+#include "ppu.h"\r
+\r
+#define INESPRIV\r
+#include "ines.h"\r
+#include "unif.h"\r
+#include "general.h"\r
+#include "state.h"\r
+#include "file.h"\r
+#include "memory.h"\r
+#include "crc32.h"\r
+#include "md5.h"\r
+#include "cheat.h"\r
+#include "vsuni.h"\r
+\r
+#include "driver.h"\r
+#include "svga.h"\r
+\r
+extern SFORMAT FCEUVSUNI_STATEINFO[];\r
+\r
+static uint8 *trainerpoo=0;\r
+static uint8 *ROM=NULL;\r
+//static\r
+uint8 *VROM=NULL;\r
+\r
+static CartInfo iNESCart;\r
+\r
+uint8 iNESMirroring=0;\r
+uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0};\r
+int32 iNESIRQLatch=0,iNESIRQCount=0;\r
+uint8 iNESIRQa=0;\r
+\r
+uint32 ROM_size=0;\r
+uint32 VROM_size=0;\r
+\r
+static void iNESPower(void);\r
+static int NewiNES_Init(int num);\r
+\r
+void (*MapClose)(void);\r
+void (*MapperReset)(void);\r
+\r
+static int MapperNo=0;\r
+\r
+static iNES_HEADER head;\r
+\r
+/*  MapperReset() is called when the NES is reset(with the reset button).\r
+    Mapperxxx_init is called when the NES has been powered on.\r
+*/\r
+\r
+static DECLFR(TrainerRead)\r
+{\r
+ return(trainerpoo[A&0x1FF]);\r
+}\r
+\r
+static void iNESGI(int h)\r
+{\r
+ switch(h)\r
+ {\r
+  case GI_RESETM2:\r
+               if(MapperReset)\r
+                MapperReset();\r
+               if(iNESCart.Reset)\r
+                iNESCart.Reset();\r
+               break;\r
+  case GI_POWER:\r
+                if(iNESCart.Power)\r
+                 iNESCart.Power();\r
+               if(trainerpoo)\r
+               {\r
+                int x;\r
+                for(x=0;x<512;x++)\r
+                {\r
+                 //X6502_DMW(0x7000+x,trainerpoo[x]);\r
+                 //if(X6502_DMR(0x7000+x)!=trainerpoo[x])\r
+                 unsigned int A=0x7000+x;\r
+                 BWrite[A](A,trainerpoo[x]);\r
+                 if(ARead[A](A)!=trainerpoo[x])\r
+                 {\r
+                    SetReadHandler(0x7000,0x71FF,TrainerRead);\r
+                   break;\r
+                 }\r
+                }\r
+               }\r
+               break;\r
+  case GI_CLOSE:\r
+               {\r
+                 FCEU_SaveGameSave(&iNESCart);\r
+\r
+                if(iNESCart.Close) iNESCart.Close();\r
+                if(ROM) {free(ROM);ROM=0;}\r
+                if(VROM) {free(VROM);VROM=0;}\r
+                if(MapClose) MapClose();\r
+                if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;}\r
+               }\r
+               break;\r
+     }\r
+}\r
+\r
+uint32 iNESGameCRC32=0;\r
+\r
+struct CRCMATCH  {\r
+       uint32 crc;\r
+       char *name;\r
+};\r
+\r
+struct INPSEL {\r
+       uint32 crc32;\r
+       int input1;\r
+       int input2;\r
+       int inputfc;\r
+};\r
+\r
+/* This is mostly for my personal use.  So HA. */\r
+static void SetInput(void)\r
+{\r
+ static struct INPSEL moo[]=\r
+       {\r
+         {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER},       /* Nekketsu Kakutou Densetsu */\r
+\r
+#if 0\r
+   {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS},  /* The two "Oeka Kids" games */\r
+   {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS},  /*           */\r
+\r
+   {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,-1},  /* World Class Track Meet */\r
+   {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,-1},  /* Super Team Games */\r
+   {0x61d86167,SI_GAMEPAD,SI_POWERPADB,-1},  /* Street Cop */\r
+   {0x6435c095,SI_GAMEPAD,SI_POWERPADB,-1},      /* Short Order/Eggsplode */\r
+\r
+\r
+   {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER},  /* Top Rider */\r
+\r
+        {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD},    /* Barcode World */\r
+        {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Super Mogura Tataki!! - Pokkun Moguraa */\r
+        {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Rairai Kyonshizu */\r
+        {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Jogging Race */\r
+        {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Athletic World */\r
+\r
+        {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Totsugeki Fuuun Takeshi Jou */\r
+        {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Running Stadium */\r
+        {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Meiro Dai Sakusen */\r
+        // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Fuun Takeshi Jou 2 */\r
+        {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Dai Undoukai */\r
+        {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB},  /* Aerobics Studio */\r
+         {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB},  /* Family Trainer: Manhattan Police */\r
+        {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB},  /* Family Trainer:  Running Stadium */\r
+\r
+        {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING},  /* Gimme a Break ... */\r
+        {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING},  /* Gi