--- /dev/null
+/* FCE Ultra - NES/Famicom Emulator\r
+ *\r
+ * Copyright notice for this file:\r
+ * Copyright (C) 2003 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 <string.h>\r
+#include <stdio.h>\r
+\r
+#include "types.h"\r
+#include "x6502.h"\r
+#include "fce.h"\r
+#include "input.h"\r
+#include "netplay.h"\r
+#include "vsuni.h"\r
+#include "state.h"\r
+\r
+#include "svga.h"\r
+\r
+#define IOPTION_GUN 0x1\r
+#define IOPTION_SWAPDIRAB 0x2\r
+\r
+#define IOPTION_PREDIP 0x10\r
+typedef struct\r
+{\r
+ char *name;\r
+ uint64 md5partial;\r
+ int mapper;\r
+ int mirroring;\r
+ int ppu;\r
+ int ioption;\r
+ int predip;\r
+} VSUNIENTRY;\r
+\r
+VSUNIENTRY *curvs;\r
+\r
+static uint8 DIPS=0;\r
+uint8 vsdip=0;\r
+\r
+void FCEUI_VSUniToggleDIPView(void)\r
+{\r
+ DIPS=!DIPS;\r
+}\r
+\r
+void FCEU_VSUniToggleDIP(int w)\r
+{\r
+ vsdip^=1<<w;\r
+}\r
+\r
+void FCEUI_VSUniSetDIP(int w, int state)\r
+{\r
+ if(((vsdip >> w) & 1) != state)\r
+ FCEUI_VSUniToggleDIP(w);\r
+}\r
+\r
+uint8 FCEUI_VSUniGetDIPs(void)\r
+{\r
+ return(vsdip);\r
+}\r
+\r
+static uint8 secdata[2][32]=\r
+{\r
+ {\r
+ 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,\r
+ 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,\r
+ 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,\r
+ 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00\r
+ },\r
+ {\r
+ 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,\r
+ 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
+ }\r
+};\r
+\r
+static uint8 *secptr;\r
+\r
+static uint8 VSindex;\r
+\r
+static DECLFR(VSSecRead)\r
+{\r
+ switch(A)\r
+ {\r
+ case 0x5e00: VSindex=0;return X.DB;\r
+ case 0x5e01: return(secptr[(VSindex++)&0x1F]);\r
+ }\r
+ return(0x00);\r
+}\r
+uint8 coinon=0;\r
+\r
+void FCEU_VSUniCoin(void)\r
+{\r
+ coinon=6;\r
+}\r
+\r
+static int curppu;\r
+static int64 curmd5;\r
+\r
+#define RP2C04_001 1\r
+#define RP2C04_002 2\r
+#define RP2C04_003 3\r
+#define RP2C05_004 4\r
+#define RCP2C03B 5\r
+#define RC2C05_01 6\r
+#define RC2C05_02 7\r
+#define RC2C05_03 8\r
+#define RC2C05_04 9\r
+\r
+static readfunc OldReadPPU;\r
+static writefunc OldWritePPU[2];\r
+\r
+static DECLFR(A2002_Gumshoe)\r
+{\r
+ return( (OldReadPPU(A)&~0x3F) | 0x1C);\r
+}\r
+\r
+static DECLFR(A2002_Topgun)\r
+{\r
+ return( (OldReadPPU(A)&~0x3F) | 0x1B);\r
+}\r
+\r
+static DECLFR(A2002_MBJ) // Mighty Bomb Jack\r
+{\r
+ return( (OldReadPPU(A)&~0x3F) | 0x3D);\r
+}\r
+\r
+static DECLFW(B2000_2001_2C05)\r
+{\r
+ OldWritePPU[(A&1)^1](A ^ 1, V);\r
+}\r
+static uint8 xevselect = 0;\r
+static DECLFR(XevRead)\r
+{\r
+ //printf("%04x\n",A);\r
+ if(A == 0x54FF)\r
+ {\r
+ return(0x5);\r
+ }\r
+ else if(A == 0x5678)\r
+ {\r
+ return(xevselect?0:1);\r
+ }\r
+ else if(A == 0x578F)\r
+ {\r
+ return(xevselect?0xd1:0x89);\r
+ }\r
+ else if(A == 0x5567)\r
+ {\r
+ xevselect ^=1;\r
+ return(xevselect?0x37:0x3E);\r
+ }\r
+ return(X.DB);\r
+}\r
+\r
+void FCEU_VSUniSwap(uint8 *j0, uint8 *j1)\r
+{\r
+ if(curvs->ioption & IOPTION_SWAPDIRAB)\r
+ {\r
+ uint16 t=*j0;\r
+ *j0=(*j0&0xC)|(*j1&0xF3);\r
+ *j1=(*j1&0xC)|(t&0xF3);\r
+ }\r
+}\r
+\r
+void FCEU_VSUniPower(void)\r
+{\r
+ coinon = 0;\r
+ VSindex = 0;\r
+\r
+ if(secptr)\r
+ SetReadHandler(0x5e00,0x5e01,VSSecRead);\r
+\r
+ if(curppu == RC2C05_04)\r
+ {\r
+ OldReadPPU = GetReadHandler(0x2002);\r
+ SetReadHandler(0x2002, 0x2002, A2002_Topgun);\r
+ }\r
+ else if(curppu == RC2C05_03)\r
+ {\r
+ OldReadPPU = GetReadHandler(0x2002);\r
+ SetReadHandler(0x2002, 0x2002, A2002_Gumshoe);\r
+ }\r
+ else if(curppu == RC2C05_02)\r
+ {\r
+ OldReadPPU = GetReadHandler(0x2002);\r
+ SetReadHandler(0x2002, 0x2002, A2002_MBJ);\r
+ }\r
+ if(curppu == RC2C05_04 || curppu == RC2C05_01 || curppu == RC2C05_03 || curppu == RC2C05_02)\r
+ {\r
+ OldWritePPU[0] = GetWriteHandler(0x2000);\r
+ OldWritePPU[1] = GetWriteHandler(0x2001);\r
+ SetWriteHandler(0x2000, 0x2001, B2000_2001_2C05);\r
+ }\r
+ if(curmd5 == 0x2d396247cf58f9faLL) /* Super Xevious */\r
+ {\r
+ SetReadHandler(0x5400,0x57FF,XevRead);\r
+ }\r
+}\r
+\r
+/* Games that will probably not be supported ever(or for a long time), since they require\r
+ dual-system:\r
+\r
+ Balloon Fight\r
+ VS Mahjong\r
+ VS Tennis\r
+ Wrecking Crew\r
+*/\r
+\r
+/* Games/PPU list. Information copied from MAME. ROMs are exchangable, so don't take\r
+ this list as "this game must use this PPU".\r
+\r
+RP2C04-001:\r
+- Baseball\r
+- Freedom Force\r
+- Gradius\r
+- Hogan's Alley\r
+- Mach Rider (Japan, Fighting Course)\r
+- Pinball\r
+- Platoon\r
+- Super Xevious\r
+\r
+RP2C04-002:\r
+- Castlevania\r
+- Ladies golf\r
+- Mach Rider (Endurance Course)\r
+- Raid on Bungeling Bay (Japan)\r
+- Slalom\r
+- Stroke N' Match Golf\r
+- Wrecking Crew\r
+\r
+RP2C04-003:\r
+- Dr mario\r
+- Excite Bike\r
+- Goonies\r
+- Soccer\r
+- TKO Boxing\r
+\r
+RP2c05-004:\r
+- Clu Clu Land\r
+- Excite Bike (Japan)\r
+- Ice Climber\r
+- Ice Climber Dual (Japan)\r
+- Super Mario Bros.\r
+\r
+Rcp2c03b:\r
+- Battle City\r
+- Duck Hunt\r
+- Mahjang\r
+- Pinball (Japan)\r
+- Rbi Baseball\r
+- Star Luster\r
+- Stroke and Match Golf (Japan)\r
+- Super Skykid\r
+- Tennis\r
+- Tetris\r
+\r
+RC2C05-01:\r
+- Ninja Jajamaru Kun (Japan)\r
+\r
+RC2C05-02:\r
+- Mighty Bomb Jack (Japan)\r
+\r
+RC2C05-03:\r
+- Gumshoe\r
+\r
+RC2C05-04:\r
+- Top Gun\r
+*/\r
+\r
+VSUNIENTRY VSUniGames[] =\r
+{\r
+ {"Baseball", 0x691d4200ea42be45LL, 99, 2,RP2C04_001,0},\r
+ {"Battle City", 0x8540949d74c4d0ebLL, 99, 2,RP2C04_001,0},\r
+ {"Battle City(Bootleg)",0x8093cbe7137ac031LL, 99, 2,RP2C04_001,0},\r
+\r
+ {"Clu Clu Land", 0x1b8123218f62b1eeLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB},\r
+ {"Dr Mario", 0xe1af09c477dc0081LL, 1, 0,RP2C04_003,IOPTION_SWAPDIRAB},\r
+ {"Duck Hunt", 0x47735d1e5f1205bbLL, 99, 2,RCP2C03B ,IOPTION_GUN},\r
+ {"Excitebike", 0x3dcd1401bcafde77LL, 99, 2,RP2C04_003,0},\r
+ {"Excitebike (J)", 0x7ea51c9d007375f0LL, 99, 2,RP2C05_004,0},\r
+ {"Freedom Force", 0xed96436bd1b5e688LL, 4, 0,RP2C04_001,IOPTION_GUN}, /* Wrong color in game select screen? */\r
+ {"Stroke and Match Golf",0x612325606e82bc66LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x01},\r
+\r
+ {"Goonies", 0x3b0085c4ff29098eLL, 151,1,RP2C04_003,0},\r
+ {"Gradius", 0x50687ae63bdad976LL,151, 1,RP2C04_001,IOPTION_SWAPDIRAB},\r
+ {"Gumshoe", 0xb8500780bf69ce29LL, 99, 2,RC2C05_03,IOPTION_GUN},\r
+ {"Hogan's Alley", 0xd78b7f0bb621fb45LL, 99, 2,RP2C04_001,IOPTION_GUN},\r
+ {"Ice Climber", 0xd21e999513435e2aLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB},\r
+ {"Ladies Golf", 0x781b24be57ef6785LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1},\r
+\r
+ {"Mach Rider", 0x015672618af06441LL, 99, 2, RP2C04_002,0},\r
+ {"Mach Rider (J)", 0xa625afb399811a8aLL, 99, 2, RP2C04_001,0},\r
+ {"Mighty Bomb Jack", 0xe6a89f4873fac37bLL, 0, 2, RC2C05_02,0},\r
+ {"Ninja Jajamaru Kun", 0xb26a2c31474099c0LL, 99, 2,RC2C05_01 ,IOPTION_SWAPDIRAB},\r
+ {"Pinball", 0xc5f49d3de7f2e9b8LL, 99, 2,RP2C04_001,IOPTION_PREDIP,0x01},\r
+ {"Pinball (J)", 0x66ab1a3828cc901cLL, 99, 2,RCP2C03B,IOPTION_PREDIP,0x1},\r
+ {"Platoon", 0x160f237351c19f1fLL, 68, 1,RP2C04_001,0},\r
+ {"RBI Baseball", 0x6a02d345812938afLL, 4, 1,RP2C04_001 ,IOPTION_SWAPDIRAB},\r
+ {"Soccer", 0xd4e7a9058780eda3LL, 99, 2,RP2C04_003,IOPTION_SWAPDIRAB},\r
+ {"Star Luster", 0x8360e134b316d94cLL, 99, 2,RCP2C03B ,0},\r
+ {"Stroke and Match Golf (J)",0x869bb83e02509747LL, 99, 2,RCP2C03B,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1},\r
+ {"Super Sky Kid", 0x78d04c1dd4ec0101LL, 4, 1,RCP2C03B ,IOPTION_SWAPDIRAB | IOPTION_PREDIP,0x20},\r
+\r
+ {"Super Xevious", 0x2d396247cf58f9faLL, 206, 0,RP2C04_001,0},\r
+ {"Tetris", 0x531a5e8eea4ce157LL, 99, 2,RCP2C03B ,IOPTION_PREDIP,0x20},\r
+ {"Top Gun", 0xf1dea36e6a7b531dLL, 2, 0,RC2C05_04 ,0},\r
+ {"VS Castlevania", 0x92fd6909c81305b9LL, 2, 1,RP2C04_002,0},\r
+ {"VS Slalom", 0x4889b5a50a623215LL, 0, 1,RP2C04_002,0},\r
+ {"VS Super Mario Bros",0x39d8cfa788e20b6cLL, 99, 2,RP2C05_004,0},\r
+ {"VS TKO Boxing", 0x6e1ee06171d8ce3aLL,4, 1,RP2C04_003,IOPTION_PREDIP,0x00},\r
+ {0}\r
+};\r
+\r
+void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring)\r
+{\r
+ VSUNIENTRY *vs = VSUniGames;\r
+\r
+ while(vs->name)\r
+ {\r
+ if(md5partial == vs->md5partial)\r
+ {\r
+\r
+ if(vs->ppu < RCP2C03B) pale = vs->ppu;\r
+ //puts(vs->name);\r
+ *MapperNo = vs->mapper;\r
+ *Mirroring = vs->mirroring;\r
+ FCEUGameInfo.type = GIT_VSUNI;\r
+ FCEUGameInfo.cspecial = SIS_VSUNISYSTEM;\r
+ FCEUGameInfo.inputfc = SIFC_NONE;\r
+ curppu = vs->ppu;\r
+ curmd5 = md5partial;\r
+\r
+ secptr = 0;\r
+\r
+ {\r
+ static int64 tko=0x6e1ee06171d8ce3aULL, rbi=0x6a02d345812938afULL;\r
+ if(md5partial == tko)\r
+ secptr=secdata[0];\r
+ if(md5partial == rbi)\r
+ secptr = secdata[1];\r
+ }\r
+\r
+ vsdip = 0x0;\r
+ if(vs->ioption & IOPTION_PREDIP)\r
+ {\r
+ vsdip= vs->predip;\r
+ }\r
+ if(vs->ioption & IOPTION_GUN)\r
+ {\r
+ FCEUGameInfo.input[0] = SI_ZAPPER;\r
+ FCEUGameInfo.input[1] = SI_NONE;\r
+ }\r
+ else\r
+ {\r
+ FCEUGameInfo.input[0] = FCEUGameInfo.input[1] = SI_GAMEPAD;\r
+ }\r
+ curvs = vs;\r
+ return;\r
+ }\r
+ vs++;\r
+ }\r
+}\r
+\r
+void FCEU_VSUniDraw(uint8 *XBuf)\r
+{\r
+ uint32 *dest;\r
+ int y,x;\r
+\r
+ if(!DIPS) return;\r
+\r
+ dest=(uint32 *)(XBuf+256*12+164);\r
+ for(y=24;y;y--,dest+=(256-72)>>2)\r
+ {\r
+ for(x=72>>2;x;x--,dest++)\r
+ *dest=0;\r
+ }\r
+\r
+ dest=(uint32 *)(XBuf+256*(12+4)+164+6 );\r
+ for(y=16;y;y--,dest+=(256>>2)-16)\r
+ for(x=8;x;x--)\r
+ {\r
+ *dest=0x01010101;\r
+ dest+=2;\r
+ }\r
+\r
+ dest=(uint32 *)(XBuf+256*(12+4)+164+6 );\r
+ for(x=0;x<8;x++,dest+=2)\r
+ {\r
+ uint32 *da=dest+(256>>2);\r
+\r
+ if(!((vsdip>>x)&1))\r
+ da+=(256>>2)*10;\r
+ for(y=4;y;y--,da+=256>>2)\r
+ *da=0;\r
+ }\r
+}\r
+\r
+\r
+SFORMAT FCEUVSUNI_STATEINFO[]={\r
+ { &vsdip, 1, "vsdp"},\r
+ { &coinon, 1, "vscn"},\r
+ { &VSindex, 1, "vsin"},\r
+ { 0}\r
+};\r