updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support...
[fceu.git] / unif.c
diff --git a/unif.c b/unif.c
index bcd2d3d..e5bb8e1 100644 (file)
--- a/unif.c
+++ b/unif.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
- */
-
-/* TODO:  Battery backup file saving, mirror force */
-/* **INCOMPLETE**                                 */
-/* Override stuff: CHR RAM instead of CHR ROM,
-                  mirroring.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifdef GP2X
-#include <unistd.h>
-#endif
-
-
-#include       "types.h"
-#include        "fce.h"
-#include        "unif.h"
-#include        "version.h"
-#include       "svga.h"
-#include        "general.h"
-#include       "state.h"
-#include       "endian.h"
-#include       "file.h"
-#include       "cart.h"
-#include       "memory.h"
-#include       "input.h"
-
-typedef struct {
-           char ID[4];
-           uint32 info;
-} UNIF_HEADER;
-
-typedef struct {
-           char *name;
-           void (*init)(void);
-          int flags;
-} BMAPPING;
-
-typedef struct {
-           char *name;
-           int (*init)(int fp);
-} BFMAPPING;
-
-void (*BoardClose)(void);
-void (*BoardPower)(void);
-void (*BoardReset)(void);
-
-static int vramo;
-static int mirrortodo;
-int UNIFbattery;
-static char *boardname;
-static char *sboardname;
-char *UNIFchrrama;
-
-static UNIF_HEADER unhead;
-static UNIF_HEADER uchead;
-
-
-static uint8 *malloced[32];
-
-static int FixRomSize(uint32 size, uint32 minimum)
-{
-  int x=1;
-
-  if(size<minimum)
-   return minimum;
-  while(x<size)
-   x<<=1;
-  return x;
-}
-
-static void FreeUNIF(void)
-{
- int x;
- if(UNIFchrrama)
-  {free(UNIFchrrama);UNIFchrrama=0;}
- if(boardname)
-  {free(boardname);boardname=0;}
- for(x=0;x<32;x++)
- {
-  if(malloced[x])
-   {free(malloced[x]);malloced[x]=0;}
- }
-}
-
-static void ResetUNIF(void)
-{
- int x;
- for(x=0;x<32;x++)
-  malloced[x]=0;
- vramo=0;
- UNIFbattery=0;
- boardname=0;
- mirrortodo=0;
- BoardReset=BoardPower=BoardClose=0;
- UNIFchrrama=0;
-}
-
-static uint8 exntar[2048];
-
-static void MooMirroring(void)
-{
- if(mirrortodo<0x4)
-  SetupCartMirroring(mirrortodo,1,0);
- else if(mirrortodo==0x4)
- {
-  SetupCartMirroring(4,1,exntar);
-  AddExState(exntar, 2048, 0,"EXNR");
- }
- else
-  SetupCartMirroring(0,0,0);
-}
-
-static int DoMirroring(int fp)
-{
- uint8 t;
- t=FCEU_fgetc(fp);
- mirrortodo=t;
-
- {
-  static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};
-  if(t<6)
-   printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);
- }
- return(1);
-}
-
-static int CTRL(int fp)
-{
- int t;
-
- if((t=FCEU_fgetc(fp))==EOF)
-  return(0);
- /* The information stored in this byte isn't very helpful, but it's
-    better than nothing...maybe.
- */
-
- if(t&1) FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_GAMEPAD;
- else FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_NONE;
-
- if(t&2) FCEUGameInfo.input[1]=SI_ZAPPER;
- else if(t&0x10) FCEUGameInfo.input[1]=SI_POWERPAD;
-
- return(1);
-}
-
-static int TVCI(int fp)
-{
- int t;
- if( (t=FCEU_fgetc(fp)) ==EOF)
-  return(0);
- if(t<=2)
- {
-  char *stuffo[3]={"NTSC","PAL","NTSC and PAL"};
-  if(t==0)
-   FCEUGameInfo.vidsys=GIV_NTSC;
-  else if(t==1)
-   FCEUGameInfo.vidsys=GIV_PAL;
-  printf(" TV Standard Compatibility: %s\n",stuffo[t]);
- }
- return(1);
-}
-
-static int EnableBattery(int fp)
-{
- puts(" Battery-backed.");
- if(FCEU_fgetc(fp)==EOF)
-  return(0);
- UNIFbattery=1;
- return(1);
-}
-
-static int LoadPRG(int fp)
-{
- int z,t;
- z=uchead.ID[3]-'0';
-
- if(z<0 || z>15)
-  return(0);
- printf(" PRG ROM %d size: %d",z,(int) uchead.info);
- if(malloced[z])
-  free(malloced[z]);
- t=FixRomSize(uchead.info,2048);
- if(!(malloced[z]=FCEU_malloc(t)))
-  return(0);
- memset(malloced[z]+uchead.info,0xFF,t-uchead.info);
- if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info)
- {
-  puts("Read Error!");
-  return(0);
- }
- else
-  puts("");
-
- SetupCartPRGMapping(z,malloced[z],t,0);
- return(1);
-}
-
-static int SetBoardName(int fp)
-{
- if(!(boardname=FCEU_malloc(uchead.info+1)))
-  return(0);
- FCEU_fread(boardname,1,uchead.info,fp);
- boardname[uchead.info]=0;
- printf(" Board name: %s\n",boardname);
- sboardname=boardname;
- if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4))
-  sboardname+=4;
- return(1);
-}
-
-static int LoadCHR(int fp)
-{
- int z,t;
- z=uchead.ID[3]-'0';
- if(z<0 || z>15)
-  return(0);
- printf(" CHR ROM %d size: %d",z,(int) uchead.info);
- if(malloced[16+z])
-  free(malloced[16+z]);
- t=FixRomSize(uchead.info,8192);
- if(!(malloced[16+z]=FCEU_malloc(t)))
-  return(0);
- memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info);
- if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info)
- {
-  puts("Read Error!");
-  return(0);
- }
- else
-  puts("");
-
- SetupCartCHRMapping(z,malloced[16+z],t,0);
- return(1);
-}
-
-
-#define BMCFLAG_FORCE4 1
-#define BMCFLAG_CHRROK 2       // Ok for generic UNIF code to make available
-                               // 8KB of CHR RAM if no CHR ROM is present.
-#define BMC 48
-
-BMAPPING bmap[BMC] = {
-
-/* Sachen Carts */
- { "TC-U01-1.5M", TCU01_Init,0},
- { "Sachen-8259B", S8259B_Init,BMCFLAG_CHRROK},
- { "Sachen-8259A", S8259A_Init,BMCFLAG_CHRROK},
- { "Sachen-74LS374N", S74LS374N_Init,0},
- { "SA-016-1M", SA0161M_Init,0},
- { "SA-72007", SA72007_Init,0},
- { "SA-72008", SA72008_Init,0},
- { "SA-0036", SA0036_Init,0},
- { "SA-0037", SA0037_Init,0},
-
- { "H2288", H2288_Init,0},
-// /* AVE carts. */
-// { "MB-91", MB91_Init,0},    // DeathBots
-// { "NINA-06", NINA06_Init,0},        // F-15 City War
-// { "NINA-03", NINA03_Init,0},        // Tiles of Fate
-// { "NINA-001", NINA001_Init,0}, // Impossible Mission 2
-
- { "HKROM", HKROM_Init,0},
-
- { "EWROM", EWROM_Init,0},
- { "EKROM", EKROM_Init,0},
- { "ELROM", ELROM_Init,0},
- { "ETROM", ETROM_Init,0},
-
- { "SAROM", SAROM_Init,0},
- { "SBROM", SBROM_Init,0},
- { "SCROM", SCROM_Init,0},
- { "SEROM", SEROM_Init,0},
- { "SGROM", SGROM_Init,0},
- { "SKROM", SKROM_Init,0},
- { "SLROM", SLROM_Init,0},
- { "SL1ROM", SL1ROM_Init,0},
- { "SNROM", SNROM_Init,0},
- { "SOROM", SOROM_Init,0},
-
- { "TGROM", TGROM_Init,0},
- { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4},
- { "TFROM", TFROM_Init,0},
- { "TLROM", TLROM_Init,0},
- { "TKROM", TKROM_Init,0},
- { "TSROM", TSROM_Init,0},
-
- { "TLSROM", TLSROM_Init,0},
- { "TKSROM", TKSROM_Init,0},
- { "TQROM", TQROM_Init,0},
- { "TVROM", TLROM_Init,BMCFLAG_FORCE4},
-
- { "CPROM", CPROM_Init,0},
- { "CNROM", CNROM_Init,0},
- { "NROM", NROM256_Init,0 },
- { "RROM", NROM128_Init,0 },
- { "RROM-128", NROM128_Init,0 },
- { "NROM-128", NROM128_Init,0 },
- { "NROM-256", NROM256_Init,0 },
- { "MHROM", MHROM_Init,0},
- { "UNROM", UNROM_Init,0},
- { "MARIO1-MALEE2", MALEE_Init,0},
- { "Supervision16in1", Supervision16_Init,0},
- { "NovelDiamond9999999in1", Novel_Init,0},
- { "Super24in1SC03", Super24_Init,0}
-};
-
-#define BMF 7
-BFMAPPING bfunc[BMF] = {
- { "CTRL", CTRL },
- { "TVCI", TVCI },
- { "BATR", EnableBattery },
- { "MIRR", DoMirroring },
- { "PRG",  LoadPRG },
- { "CHR",  LoadCHR },
- { "MAPR", SetBoardName }
-};
-
-int LoadUNIFChunks(int fp)
-{
-   int x;
-   int t;
-   for(;;)
-   {
-    t=FCEU_fread(&uchead,1,4,fp);
-    if(t<4)
-    {
-     if(t>0)
-      return 0;
-     return 1;
-    }
-    if(!(FCEU_read32(&uchead.info,fp)))
-     return 0;
-    t=0;
-    for(x=0;x<BMF;x++)
-    {
-     if(memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name)))
-      continue;
-     if(!bfunc[x].init(fp))
-      return 0;
-     t=1;
-     break;
-    }
-    if(!t)
-     if(FCEU_fseek(fp,uchead.info,SEEK_CUR))
-      return(0);
-   }
-}
-
-static int InitializeBoard(void)
-{
-   int x;
-
-   for(x=0;x<BMC;x++)
-   {
-    if(strcmp(sboardname,bmap[x].name)) continue;
-    if(!malloced[16] && (bmap[x].flags&BMCFLAG_CHRROK))
-    {
-     UNIFchrrama=FCEU_malloc(8192);
-     if((malloced[16]=(uint8 *)UNIFchrrama))
-     {
-      SetupCartCHRMapping(0,(uint8 *)UNIFchrrama,8192,1);
-      AddExState(UNIFchrrama, 8192, 0,"CHRR");
-     }
-     else
-      return(-1);
-    }
-    if(bmap[x].flags&BMCFLAG_FORCE4)
-     mirrortodo=4;
-    MooMirroring();
-    bmap[x].init();
-    return(1);
-   }
-   FCEU_PrintError("Board type not supported.");
-   return(0);
-}
-
-static void UNIFGI(int h)
-{
- switch(h)
- {
-  case GI_RESETM2:
-               if(BoardReset) BoardReset();
-               break;
-  case GI_POWER:
-                if(BoardPower) BoardPower();
-               if(UNIFchrrama) memset(UNIFchrrama,0,8192);
-               break;
-  case GI_CLOSE:
-                if(BoardClose)
-                 BoardClose();
-                FreeUNIF();
-                break;
- }
-}
-
-int UNIFLoad(char *name, int fp)
-{
-        FCEU_fseek(fp,0,SEEK_SET);
-        FCEU_fread(&unhead,1,4,fp);
-        if(memcmp(&unhead,"UNIF",4))
-         return 0;
-
-       ResetCartMapping();
-
-        ResetExState();
-        ResetUNIF();
-        if(!FCEU_read32(&unhead.info,fp))
-        goto aborto;
-        if(FCEU_fseek(fp,0x20,SEEK_SET)<0)
-        goto aborto;
-        if(!LoadUNIFChunks(fp))
-        goto aborto;
-        if(!InitializeBoard())
-        goto aborto;
-
-        GameInterface=UNIFGI;
-        return 1;
-
-       aborto:
-
-       FreeUNIF();
-       ResetUNIF();
-       return 0;
-}
-
-static FILE *fssp=0;
-
-void UNIFOpenWRAM(int t, char *ext, int override)
-{
- if(UNIFbattery|override)
- {
-  fssp=fopen(FCEU_MakeFName(FCEUMKF_SAV,0,(ext?ext:"sav")),(t==UOW_RD)?"rb":"wb");
- }
-}
-
-void UNIFWriteWRAM(uint8 *p, int size)
-{
- if(fssp)
-  fwrite(p, size, 1, fssp);
-}
-
-void UNIFReadWRAM(uint8 *p, int size)
-{
- if(fssp)
-  fread(p, size, 1, fssp);
-}
-void UNIFCloseWRAM(void)
-{
- if(fssp)
-  fclose(fssp);
- fssp=0;
-#ifdef GP2X
- sync();
-#endif
-}
+/* 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
+/* TODO:  Battery backup file saving, mirror force    */\r
+/* **INCOMPLETE**             */\r
+/* Override stuff: CHR RAM instead of CHR ROM,   mirroring. */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <string.h>\r
+\r
+\r
+#include  "types.h"\r
+#include  "fce.h"\r
+#include  "cart.h"\r
+#include  "unif.h"\r
+#include  "ines.h"\r
+#include  "general.h"\r
+#include  "state.h"\r
+#include  "endian.h"\r
+#include  "file.h"\r
+#include  "memory.h"\r
+#include  "input.h"\r
+#include  "md5.h"\r
+\r
+#include  "svga.h"\r
+\r
+typedef struct {\r
+           char ID[4];\r
+           uint32 info;\r
+} UNIF_HEADER;\r
+\r
+typedef struct {\r
+           char *name;\r
+           void (*init)(CartInfo *);\r
+          int flags;\r
+} BMAPPING;\r
+\r
+typedef struct {\r
+           char *name;\r
+           int (*init)(int fp);\r
+} BFMAPPING;\r
+\r
+static CartInfo UNIFCart;\r
+\r
+static int vramo;\r
+static int mirrortodo;\r
+static uint8 *boardname;\r
+static uint8 *sboardname;\r
+\r
+static uint32 CHRRAMSize;\r
+uint8 *UNIFchrrama=0;\r
+\r
+static UNIF_HEADER unhead;\r
+static UNIF_HEADER uchead;\r
+\r
+\r
+static uint8 *malloced[32];\r
+static uint32 mallocedsizes[32];\r
+\r
+static int FixRomSize(uint32 size, uint32 minimum)\r
+{\r
+  int x=1;\r
+\r
+  if(size<minimum)\r
+   return minimum;\r
+  while(x<size)\r
+   x<<=1;\r
+  return x;\r
+}\r
+\r
+static void FreeUNIF(void)\r
+{\r
+ int x;\r
+ if(UNIFchrrama)\r
+  {free(UNIFchrrama);UNIFchrrama=0;}\r
+ if(boardname)\r
+  {free(boardname);boardname=0;}\r
+ for(x=0;x<32;x++)\r
+ {\r
+  if(malloced[x])\r
+   {free(malloced[x]);malloced[x]=0;}\r
+ }\r
+}\r
+\r
+static void ResetUNIF(void)\r
+{\r
+ int x;\r
+ for(x=0;x<32;x++)\r
+  malloced[x]=0;\r
+ vramo=0;\r
+ boardname=0;\r
+ mirrortodo=0;\r
+ memset(&UNIFCart,0,sizeof(UNIFCart));\r
+ UNIFchrrama=0;\r
+}\r
+\r
+static uint8 exntar[2048];\r
+\r
+static void MooMirroring(void)\r
+{\r
+ if(mirrortodo<0x4)\r
+  SetupCartMirroring(mirrortodo,1,0);\r
+ else if(mirrortodo==0x4)\r
+ {\r
+  SetupCartMirroring(4,1,exntar);\r
+  AddExState(exntar, 2048, 0,"EXNR");\r
+ }\r
+ else\r
+  SetupCartMirroring(0,0,0);\r
+}\r
+\r
+static int DoMirroring(int fp)\r
+{\r
+ uint8 t;\r
+ t=FCEU_fgetc(fp);\r
+ mirrortodo=t;\r
+\r
+ {\r
+  static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};\r
+  if(t<6)\r
+   FCEU_printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);\r
+ }\r
+ return(1);\r
+}\r
+\r
+static int NAME(int fp)\r
+{\r
+ char namebuf[100];\r
+ int index;\r
+ int t;\r
+\r
+ FCEU_printf(" Name: ");\r
+ index=0;\r
+\r
+ while((t=FCEU_fgetc(fp))>0)\r
+  if(index<99)\r
+   namebuf[index++]=t;\r
+\r
+ namebuf[index]=0;\r
+ FCEU_printf("%s\n",namebuf);\r
+\r
+ if(!FCEUGameInfo.name)\r
+ {\r
+  FCEUGameInfo.name=malloc(strlen(namebuf)+1);\r
+  strcpy((char *)FCEUGameInfo.name,namebuf);\r
+ }\r
+ return(1);\r
+}\r
+static int DINF(int fp)\r
+{\r
+ char name[100], method[100];\r
+ uint8 d, m;\r
+ uint16 y;\r
+ int t;\r
+\r
+ if(FCEU_fread(name,1,100,fp)!=100)\r
+  return(0);\r
+ if((t=FCEU_fgetc(fp))==EOF) return(0);\r
+ d=t;\r
+ if((t=FCEU_fgetc(fp))==EOF) return(0);\r
+ m=t;\r
+ if((t=FCEU_fgetc(fp))==EOF) return(0);\r
+ y=t;\r
+ if((t=FCEU_fgetc(fp))==EOF) return(0);\r
+ y|=t<<8;\r
+ if(FCEU_fread(method,1,100,fp)!=100)\r
+  return(0);\r
+ name[99]=method[99]=0;\r
+ FCEU_printf(" Dumped by: %s\n",name);\r
+ FCEU_printf(" Dumped with: %s\n",method);\r
+ {\r
+  char *months[12]={"January","February","March","April","May","June","July",\r
+                   "August","September","October","November","December"};\r
+  FCEU_printf(" Dumped on: %s %d, %d\n",months[(m-1)%12],d,y);\r
+ }\r
+ return(1);\r
+}\r
+\r
+static int CTRL(int fp)\r
+{\r
+ int t;\r
+\r
+ if((t=FCEU_fgetc(fp))==EOF)\r
+  return(0);\r
+ /* The information stored in this byte isn't very helpful, but it's\r
+    better than nothing...maybe.\r
+ */\r
+\r
+ if(t&1) FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_GAMEPAD;\r
+ else FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_NONE;\r
+\r
+ if(t&2) FCEUGameInfo.input[1]=SI_ZAPPER;\r
+ //else if(t&0x10) FCEUGameInfo->input[1]=SI_POWERPAD;\r
+\r
+ return(1);\r
+}\r
+\r
+static int TVCI(int fp)\r
+{\r
+ int t;\r
+ if( (t=FCEU_fgetc(fp)) ==EOF)\r
+  return(0);\r
+ if(t<=2)\r
+ {\r
+  char *stuffo[3]={"NTSC","PAL","NTSC and PAL"};\r
+  if(t==0)\r
+  {\r
+   FCEUGameInfo.vidsys=GIV_NTSC;\r
+   FCEUI_SetVidSystem(0);\r
+  }\r
+  else if(t==1)\r
+  {\r
+   FCEUGameInfo.vidsys=GIV_PAL;\r
+   FCEUI_SetVidSystem(1);\r
+  }\r
+  FCEU_printf(" TV Standard Compatibility: %s\n",stuffo[t]);\r
+ }\r
+ return(1);\r
+}\r
+\r
+static int EnableBattery(int fp)\r
+{\r
+ FCEU_printf(" Battery-backed.\n");\r
+ if(FCEU_fgetc(fp)==EOF)\r
+  return(0);\r
+ UNIFCart.battery=1;\r
+ return(1);\r
+}\r
+\r
+static int LoadPRG(int fp)\r
+{\r
+ int z,t;\r
+ z=uchead.ID[3]-'0';\r
+\r
+ if(z<0 || z>15)\r
+  return(0);\r
+ FCEU_printf(" PRG ROM %d size: %d",z,(int) uchead.info);\r
+ if(malloced[z])\r
+  free(malloced[z]);\r
+ t=FixRomSize(uchead.info,2048);\r
+ if(!(malloced[z]=(uint8 *)FCEU_malloc(t)))\r
+  return(0);\r
+ mallocedsizes[z]=t;\r
+ memset(malloced[z]+uchead.info,0xFF,t-uchead.info);\r
+ if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info)\r
+ {\r
+  FCEU_printf("Read Error!\n");\r
+  return(0);\r
+ }\r
+ else\r
+  FCEU_printf("\n");\r
+\r
+ SetupCartPRGMapping(z,malloced[z],t,0);\r
+ return(1);\r
+}\r
+\r
+static int SetBoardName(int fp)\r
+{\r
+ if(!(boardname=(uint8 *)FCEU_malloc(uchead.info+1)))\r
+  return(0);\r
+ FCEU_fread(boardname,1,uchead.info,fp);\r
+ boardname[uchead.info]=0;\r
+ FCEU_printf(" Board name: %s\n",boardname);\r
+ sboardname=boardname;\r
+ if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4))\r
+  sboardname+=4;\r
+ return(1);\r
+}\r
+\r
+static int LoadCHR(int fp)\r
+{\r
+ int z,t;\r
+ z=uchead.ID[3]-'0';\r
+ if(z<0 || z>15)\r
+  return(0);\r
+ FCEU_printf(" CHR ROM %d size: %d",z,(int) uchead.info);\r
+ if(malloced[16+z])\r
+  free(malloced[16+z]);\r
+ t=FixRomSize(uchead.info,8192);\r
+ if(!(malloced[16+z]=(uint8 *)FCEU_malloc(t)))\r
+  return(0);\r
+ mallocedsizes[16+z]=t;\r
+ memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info);\r
+ if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info)\r
+ {\r
+  FCEU_printf("Read Error!\n");\r
+  return(0);\r
+ }\r
+ else\r
+  FCEU_printf("\n");\r
+\r
+ SetupCartCHRMapping(z,malloced[16+z],t,0);\r
+ return(1);\r
+}\r
+\r
+\r
+#define BMCFLAG_FORCE4 1\r
+#define BMCFLAG_16KCHRR  2\r
+#define BMCFLAG_32KCHRR  4\r
+\r
+static BMAPPING bmap[] = {\r
+\r
+/* Sachen Carts */\r
+ { "TC-U01-1.5M", TCU01_Init,0},\r
+ { "Sachen-8259A", S8259A_Init,0},\r
+ { "Sachen-8259B", S8259B_Init,0},\r
+ { "Sachen-8259C", S8259C_Init,0},\r
+ { "Sachen-8259D", S8259D_Init,0},\r
+ { "Sachen-74LS374N", S74LS374N_Init,0},\r
+ { "Sachen-74LS374NA", S74LS374NA_Init,0}, //seems to be custom mapper\r
+ { "SA-016-1M", SA0161M_Init,0},\r
+ { "SA-72007", SA72007_Init,0},\r
+ { "SA-72008", SA72008_Init,0},\r
+ { "SA-0036", SA0036_Init,0},\r
+ { "SA-0037", SA0037_Init,0},\r
+ { "SA-NROM", TCA01_Init,0},\r
+\r
+ { "H2288", UNLH2288_Init,0},\r
+ { "8237", UNL8237_Init,0},\r
+\r
+// /* AVE carts. */\r
+// { "MB-91", MB91_Init,0},  // DeathBots\r
+// { "NINA-06", NINA06_Init,0},  // F-15 City War\r
+// { "NINA-03", NINA03_Init,0},  // Tiles of Fate\r
+// { "NINA-001", NINA001_Init,0}, // Impossible Mission 2\r
+\r
+ { "HKROM", HKROM_Init,0},\r
+\r
+ { "EWROM", EWROM_Init,0},\r
+ { "EKROM", EKROM_Init,0},\r
+ { "ELROM", ELROM_Init,0},\r
+ { "ETROM", ETROM_Init,0},\r
+\r
+ { "SAROM", SAROM_Init,0},\r
+ { "SBROM", SBROM_Init,0},\r
+ { "SCROM", SCROM_Init,0},\r
+ { "SEROM", SEROM_Init,0},\r
+ { "SGROM", SGROM_Init,0},\r
+ { "SKROM", SKROM_Init,0},\r
+ { "SLROM", SLROM_Init,0},\r
+ { "SL1ROM", SL1ROM_Init,0},\r
+ { "SNROM", SNROM_Init,0},\r
+ { "SOROM", SOROM_Init,0},\r
+\r
+ { "TGROM", TGROM_Init,0},\r
+ { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4},\r
+\r
+ { "TEROM", TEROM_Init,0},\r
+ { "TFROM", TFROM_Init,0},\r
+ { "TLROM", TLROM_Init,0},\r
+ { "TKROM", TKROM_Init,0},\r
+ { "TSROM", TSROM_Init,0},\r
+\r
+ { "TLSROM", TLSROM_Init,0},\r
+ { "TKSROM", TKSROM_Init,0},\r
+ { "TQROM", TQROM_Init,0},\r
+ { "TVROM", TLROM_Init,BMCFLAG_FORCE4},\r
+\r
+ { "CPROM", CPROM_Init,BMCFLAG_16KCHRR},\r
+ { "CNROM", CNROM_Init,0},\r
+ { "GNROM", GNROM_Init,0},\r
+ { "NROM", NROM256_Init,0 },\r
+ { "RROM", NROM128_Init,0 },\r
+ { "RROM-128", NROM128_Init,0 },\r
+ { "NROM-128", NROM128_Init,0 },\r
+ { "NROM-256", NROM256_Init,0 },\r
+ { "MHROM", MHROM_Init,0},\r
+ { "UNROM", UNROM_Init,0},\r
+ { "MARIO1-MALEE2", MALEE_Init,0},\r
+\r
+ { "CC-21", UNLCC21_Init,0},\r
+\r
+ { "8157", UNL8157_Init,0},\r
+ { "Supervision16in1", Supervision16_Init,0},\r
+ { "NovelDiamond9999999in1", Novel_Init,0},\r
+ { "Super24in1SC03", Super24_Init,0},\r
+ { "SuperHIK8in1", Mapper45_Init,0},\r
+ { "DREAMTECH01", DreamTech01_Init,0},\r
+ { "KONAMI-QTAI", Mapper190_Init,0},\r
+ {0,0,0}\r
+};\r
+\r
+static BFMAPPING bfunc[] = {\r
+ { "CTRL", CTRL },\r
+ { "TVCI", TVCI },\r
+ { "BATR", EnableBattery },\r
+ { "MIRR", DoMirroring },\r
+ { "PRG",  LoadPRG },\r
+ { "CHR",  LoadCHR },\r
+ { "NAME", NAME  },\r
+ { "MAPR", SetBoardName },\r
+ { "DINF", DINF },\r
+ { 0, 0 }\r
+};\r
+\r
+int LoadUNIFChunks(int fp)\r
+{\r
+   int x;\r
+   int t;\r
+   for(;;)\r
+   {\r
+    t=FCEU_fread(&uchead,1,4,fp);\r
+    if(t<4)\r
+    {\r
+     if(t>0)\r
+      return 0;\r
+     return 1;\r
+    }\r
+    if(!(FCEU_read32(&uchead.info,fp)))\r
+     return 0;\r
+    t=0;\r
+    x=0;\r
+       //printf("Funky: %s\n",((uint8 *)&uchead));\r
+    while(bfunc[x].name)\r
+    {\r
+     if(!memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name)))\r
+     {\r
+      if(!bfunc[x].init(fp))\r
+       return 0;\r
+      t=1;\r
+      break;\r
+     }\r
+     x++;\r
+    }\r
+    if(!t)\r
+     if(FCEU_fseek(fp,uchead.info,SEEK_CUR))\r
+      return(0);\r
+   }\r
+}\r
+\r
+static int InitializeBoard(void)\r
+{\r
+   int x=0;\r
+\r
+   if(!sboardname) return(0);\r
+\r
+   while(bmap[x].name)\r
+   {\r
+    if(!strcmp((char *)sboardname,(char *)bmap[x].name))\r
+    {\r
+     if(!malloced[16])\r
+     {\r
+      if(bmap[x].flags & BMCFLAG_16KCHRR)\r
+        CHRRAMSize = 16384;\r
+      else\r
+  CHRRAMSize = 8192;\r
+      if((UNIFchrrama=(uint8 *)FCEU_malloc(CHRRAMSize)))\r
+      {\r
+       SetupCartCHRMapping(0,UNIFchrrama,CHRRAMSize,1);\r
+       AddExState(UNIFchrrama, CHRRAMSize, 0,"CHRR");\r
+      }\r
+      else\r
+       return(-1);\r
+     }\r
+     if(bmap[x].flags&BMCFLAG_FORCE4)\r
+      mirrortodo=4;\r
+     MooMirroring();\r
+     bmap[x].init(&UNIFCart);\r
+     return(1);\r
+    }\r
+    x++;\r
+   }\r
+   FCEU_PrintError("Board type not supported.");\r
+   return(0);\r
+}\r
+\r
+static void UNIFGI(int h)\r
+{\r
+ switch(h)\r
+ {\r
+  case GI_RESETM2:\r
+                if(UNIFCart.Reset)\r
+                 UNIFCart.Reset();\r
+               break;\r
+  case GI_POWER:\r
+                if(UNIFCart.Power)\r
+                 UNIFCart.Power();\r
+               if(UNIFchrrama) memset(UNIFchrrama,0,8192);\r
+               break;\r
+  case GI_CLOSE:\r
+                FCEU_SaveGameSave(&UNIFCart);\r
+               if(UNIFCart.Close)\r
+                UNIFCart.Close();\r
+                FreeUNIF();\r
+                break;\r
+ }\r
+}\r
+\r
+int UNIFLoad(const char *name, int fp)\r
+{\r
+        FCEU_fseek(fp,0,SEEK_SET);\r
+        FCEU_fread(&unhead,1,4,fp);\r
+        if(memcmp(&unhead,"UNIF",4))\r
+         return 0;\r
+\r
+       ResetCartMapping();\r
+\r
+        ResetExState(0,0);\r
+        ResetUNIF();\r
+        if(!FCEU_read32(&unhead.info,fp))\r
+        goto aborto;\r
+        if(FCEU_fseek(fp,0x20,SEEK_SET)<0)\r
+        goto aborto;\r
+        if(!LoadUNIFChunks(fp))\r
+        goto aborto;\r
+       {\r
+        int x;\r
+        struct md5_context md5;\r
+\r
+        md5_starts(&md5);\r
+\r
+        for(x=0;x<32;x++)\r
+         if(malloced[x])\r
+         {\r
+          md5_update(&md5,malloced[x],mallocedsizes[x]);\r
+         }\r
+         md5_finish(&md5,UNIFCart.MD5);\r
+          FCEU_printf(" ROM MD5:  0x");\r
+          for(x=0;x<16;x++)\r
+           FCEU_printf("%02x",UNIFCart.MD5[x]);\r
+          FCEU_printf("\n");\r
+         memcpy(FCEUGameInfo.MD5,UNIFCart.MD5,sizeof(UNIFCart.MD5));\r
+       }\r
+\r
+        if(!InitializeBoard())\r
+        goto aborto;\r
+\r
+       FCEU_LoadGameSave(&UNIFCart);\r
+        GameInterface=UNIFGI;\r
+        return 1;\r
+\r
+       aborto:\r
+\r
+       FreeUNIF();\r
+       ResetUNIF();\r
+\r
+\r
+       return 0;\r
+}\r