palette change to reflect .15 code
[fceu.git] / vsuni.c
1 /* FCE Ultra - NES/Famicom Emulator\r
2  *\r
3  * Copyright notice for this file:\r
4  *  Copyright (C) 2003 Xodnizel\r
5  *\r
6  * This program is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 2 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * This program is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program; if not, write to the Free Software\r
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19  */\r
20 \r
21 #include <string.h>\r
22 #include <stdio.h>\r
23 \r
24 #include "types.h"\r
25 #include "x6502.h"\r
26 #include "fce.h"\r
27 #include "input.h"\r
28 #include "netplay.h"\r
29 #include "vsuni.h"\r
30 #include "state.h"\r
31 \r
32 #include "svga.h"\r
33 \r
34 #define IOPTION_GUN       0x1\r
35 #define IOPTION_SWAPDIRAB       0x2\r
36 \r
37 #define IOPTION_PREDIP    0x10\r
38 typedef struct\r
39 {\r
40         char *name;\r
41         uint64 md5partial;\r
42         int mapper;\r
43         int mirroring;\r
44         int ppu;\r
45         int ioption;\r
46         int predip;\r
47 } VSUNIENTRY;\r
48 \r
49 VSUNIENTRY *curvs;\r
50 \r
51 static uint8 DIPS=0;\r
52 uint8 vsdip=0;\r
53 \r
54 void FCEUI_VSUniToggleDIPView(void)\r
55 {\r
56  DIPS=!DIPS;\r
57 }\r
58 \r
59 void FCEU_VSUniToggleDIP(int w)\r
60 {\r
61  vsdip^=1<<w;\r
62 }\r
63 \r
64 void FCEUI_VSUniSetDIP(int w, int state)\r
65 {\r
66  if(((vsdip >> w) & 1) != state)\r
67   FCEUI_VSUniToggleDIP(w);\r
68 }\r
69 \r
70 uint8 FCEUI_VSUniGetDIPs(void)\r
71 {\r
72  return(vsdip);\r
73 }\r
74 \r
75 static uint8 secdata[2][32]=\r
76 {\r
77  {\r
78   0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,\r
79   0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,\r
80   0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,\r
81   0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00\r
82  },\r
83  {\r
84   0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,\r
85   0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,\r
86   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\r
87   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00\r
88  }\r
89 };\r
90 \r
91 static uint8 *secptr;\r
92 \r
93 static uint8 VSindex;\r
94 \r
95 static DECLFR(VSSecRead)\r
96 {\r
97  switch(A)\r
98  {\r
99   case 0x5e00: VSindex=0;return X.DB;\r
100   case 0x5e01: return(secptr[(VSindex++)&0x1F]);\r
101  }\r
102  return(0x00);\r
103 }\r
104 uint8 coinon=0;\r
105 \r
106 void FCEU_VSUniCoin(void)\r
107 {\r
108  coinon=6;\r
109 }\r
110 \r
111 static int curppu;\r
112 static int64 curmd5;\r
113 \r
114 #define RP2C04_001      1\r
115 #define RP2C04_002      2\r
116 #define RP2C04_003      3\r
117 #define RP2C05_004      4\r
118 #define RCP2C03B  5\r
119 #define RC2C05_01       6\r
120 #define RC2C05_02       7\r
121 #define RC2C05_03       8\r
122 #define RC2C05_04       9\r
123 \r
124 static readfunc OldReadPPU;\r
125 static writefunc OldWritePPU[2];\r
126 \r
127 static DECLFR(A2002_Gumshoe)\r
128 {\r
129  return( (OldReadPPU(A)&~0x3F) | 0x1C);\r
130 }\r
131 \r
132 static DECLFR(A2002_Topgun)\r
133 {\r
134  return( (OldReadPPU(A)&~0x3F) | 0x1B);\r
135 }\r
136 \r
137 static DECLFR(A2002_MBJ)  // Mighty Bomb Jack\r
138 {\r
139  return( (OldReadPPU(A)&~0x3F) | 0x3D);\r
140 }\r
141 \r
142 static DECLFW(B2000_2001_2C05)\r
143 {\r
144  OldWritePPU[(A&1)^1](A ^ 1, V);\r
145 }\r
146 static uint8 xevselect = 0;\r
147 static DECLFR(XevRead)\r
148 {\r
149  //printf("%04x\n",A);\r
150  if(A == 0x54FF)\r
151  {\r
152   return(0x5);\r
153  }\r
154  else if(A == 0x5678)\r
155  {\r
156   return(xevselect?0:1);\r
157  }\r
158  else if(A == 0x578F)\r
159  {\r
160   return(xevselect?0xd1:0x89);\r
161  }\r
162  else if(A == 0x5567)\r
163  {\r
164   xevselect ^=1;\r
165   return(xevselect?0x37:0x3E);\r
166  }\r
167  return(X.DB);\r
168 }\r
169 \r
170 void FCEU_VSUniSwap(uint8 *j0, uint8 *j1)\r
171 {\r
172  if(curvs->ioption & IOPTION_SWAPDIRAB)\r
173  {\r
174   uint16 t=*j0;\r
175   *j0=(*j0&0xC)|(*j1&0xF3);\r
176   *j1=(*j1&0xC)|(t&0xF3);\r
177  }\r
178 }\r
179 \r
180 void FCEU_VSUniPower(void)\r
181 {\r
182  coinon = 0;\r
183  VSindex = 0;\r
184 \r
185  if(secptr)\r
186   SetReadHandler(0x5e00,0x5e01,VSSecRead);\r
187 \r
188  if(curppu == RC2C05_04)\r
189  {\r
190   OldReadPPU = GetReadHandler(0x2002);\r
191   SetReadHandler(0x2002, 0x2002, A2002_Topgun);\r
192  }\r
193  else if(curppu == RC2C05_03)\r
194  {\r
195   OldReadPPU = GetReadHandler(0x2002);\r
196   SetReadHandler(0x2002, 0x2002, A2002_Gumshoe);\r
197  }\r
198  else if(curppu == RC2C05_02)\r
199  {\r
200   OldReadPPU = GetReadHandler(0x2002);\r
201   SetReadHandler(0x2002, 0x2002, A2002_MBJ);\r
202  }\r
203  if(curppu == RC2C05_04 || curppu == RC2C05_01 || curppu == RC2C05_03 || curppu == RC2C05_02)\r
204  {\r
205   OldWritePPU[0] = GetWriteHandler(0x2000);\r
206   OldWritePPU[1] = GetWriteHandler(0x2001);\r
207   SetWriteHandler(0x2000, 0x2001, B2000_2001_2C05);\r
208  }\r
209  if(curmd5 == 0x2d396247cf58f9faLL) /* Super Xevious */\r
210  {\r
211   SetReadHandler(0x5400,0x57FF,XevRead);\r
212  }\r
213 }\r
214 \r
215 /* Games that will probably not be supported ever(or for a long time), since they require\r
216    dual-system:\r
217 \r
218    Balloon Fight\r
219    VS Mahjong\r
220    VS Tennis\r
221    Wrecking Crew\r
222 */\r
223 \r
224 /* Games/PPU list.  Information copied from MAME.  ROMs are exchangable, so don't take\r
225    this list as "this game must use this PPU".\r
226 \r
227 RP2C04-001:\r
228 - Baseball\r
229 - Freedom Force\r
230 - Gradius\r
231 - Hogan's Alley\r
232 - Mach Rider (Japan, Fighting Course)\r
233 - Pinball\r
234 - Platoon\r
235 - Super Xevious\r
236 \r
237 RP2C04-002:\r
238 - Castlevania\r
239 - Ladies golf\r
240 - Mach Rider (Endurance Course)\r
241 - Raid on Bungeling Bay (Japan)\r
242 - Slalom\r
243 - Stroke N' Match Golf\r
244 - Wrecking Crew\r
245 \r
246 RP2C04-003:\r
247 - Dr mario\r
248 - Excite Bike\r
249 - Goonies\r
250 - Soccer\r
251 - TKO Boxing\r
252 \r
253 RP2c05-004:\r
254 - Clu Clu Land\r
255 - Excite Bike (Japan)\r
256 - Ice Climber\r
257 - Ice Climber Dual (Japan)\r
258 - Super Mario Bros.\r
259 \r
260 Rcp2c03b:\r
261 - Battle City\r
262 - Duck Hunt\r
263 - Mahjang\r
264 - Pinball (Japan)\r
265 - Rbi Baseball\r
266 - Star Luster\r
267 - Stroke and Match Golf (Japan)\r
268 - Super Skykid\r
269 - Tennis\r
270 - Tetris\r
271 \r
272 RC2C05-01:\r
273 - Ninja Jajamaru Kun (Japan)\r
274 \r
275 RC2C05-02:\r
276 - Mighty Bomb Jack (Japan)\r
277 \r
278 RC2C05-03:\r
279 - Gumshoe\r
280 \r
281 RC2C05-04:\r
282 - Top Gun\r
283 */\r
284 \r
285 VSUNIENTRY VSUniGames[]  =\r
286 {\r
287  {"Baseball",    0x691d4200ea42be45LL, 99, 2,RP2C04_001,0},\r
288   {"Battle City",  0x8540949d74c4d0ebLL, 99, 2,RP2C04_001,0},\r
289   {"Battle City(Bootleg)",0x8093cbe7137ac031LL, 99, 2,RP2C04_001,0},\r
290 \r
291   {"Clu Clu Land",  0x1b8123218f62b1eeLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB},\r
292   {"Dr Mario",    0xe1af09c477dc0081LL,  1, 0,RP2C04_003,IOPTION_SWAPDIRAB},\r
293   {"Duck Hunt",    0x47735d1e5f1205bbLL, 99, 2,RCP2C03B  ,IOPTION_GUN},\r
294   {"Excitebike",    0x3dcd1401bcafde77LL, 99, 2,RP2C04_003,0},\r
295   {"Excitebike (J)",    0x7ea51c9d007375f0LL, 99, 2,RP2C05_004,0},\r
296   {"Freedom Force",  0xed96436bd1b5e688LL,  4, 0,RP2C04_001,IOPTION_GUN}, /* Wrong color in game select screen? */\r
297   {"Stroke and Match Golf",0x612325606e82bc66LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x01},\r
298 \r
299   {"Goonies",    0x3b0085c4ff29098eLL, 151,1,RP2C04_003,0},\r
300   {"Gradius",    0x50687ae63bdad976LL,151, 1,RP2C04_001,IOPTION_SWAPDIRAB},\r
301   {"Gumshoe",    0xb8500780bf69ce29LL, 99, 2,RC2C05_03,IOPTION_GUN},\r
302   {"Hogan's Alley",  0xd78b7f0bb621fb45LL, 99, 2,RP2C04_001,IOPTION_GUN},\r
303   {"Ice Climber",  0xd21e999513435e2aLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB},\r
304   {"Ladies Golf",  0x781b24be57ef6785LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1},\r
305 \r
306   {"Mach Rider",  0x015672618af06441LL, 99, 2, RP2C04_002,0},\r
307   {"Mach Rider (J)",  0xa625afb399811a8aLL, 99, 2, RP2C04_001,0},\r
308   {"Mighty Bomb Jack",  0xe6a89f4873fac37bLL, 0, 2, RC2C05_02,0},\r
309   {"Ninja Jajamaru Kun",  0xb26a2c31474099c0LL, 99, 2,RC2C05_01 ,IOPTION_SWAPDIRAB},\r
310   {"Pinball",    0xc5f49d3de7f2e9b8LL, 99, 2,RP2C04_001,IOPTION_PREDIP,0x01},\r
311   {"Pinball (J)",    0x66ab1a3828cc901cLL, 99, 2,RCP2C03B,IOPTION_PREDIP,0x1},\r
312   {"Platoon",    0x160f237351c19f1fLL, 68, 1,RP2C04_001,0},\r
313   {"RBI Baseball",       0x6a02d345812938afLL,  4, 1,RP2C04_001 ,IOPTION_SWAPDIRAB},\r
314   {"Soccer",    0xd4e7a9058780eda3LL, 99, 2,RP2C04_003,IOPTION_SWAPDIRAB},\r
315   {"Star Luster",  0x8360e134b316d94cLL, 99, 2,RCP2C03B  ,0},\r
316   {"Stroke and Match Golf (J)",0x869bb83e02509747LL, 99, 2,RCP2C03B,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1},\r
317   {"Super Sky Kid",  0x78d04c1dd4ec0101LL,  4, 1,RCP2C03B  ,IOPTION_SWAPDIRAB | IOPTION_PREDIP,0x20},\r
318 \r
319   {"Super Xevious",  0x2d396247cf58f9faLL,  206, 0,RP2C04_001,0},\r
320   {"Tetris",    0x531a5e8eea4ce157LL, 99, 2,RCP2C03B  ,IOPTION_PREDIP,0x20},\r
321   {"Top Gun",    0xf1dea36e6a7b531dLL,  2, 0,RC2C05_04 ,0},\r
322   {"VS Castlevania",     0x92fd6909c81305b9LL,  2, 1,RP2C04_002,0},\r
323   {"VS Slalom",    0x4889b5a50a623215LL,  0, 1,RP2C04_002,0},\r
324   {"VS Super Mario Bros",0x39d8cfa788e20b6cLL, 99, 2,RP2C05_004,0},\r
325   {"VS TKO Boxing",  0x6e1ee06171d8ce3aLL,4, 1,RP2C04_003,IOPTION_PREDIP,0x00},\r
326  {0}\r
327 };\r
328 \r
329 void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring)\r
330 {\r
331  VSUNIENTRY *vs = VSUniGames;\r
332 \r
333  while(vs->name)\r
334  {\r
335   if(md5partial == vs->md5partial)\r
336   {\r
337 \r
338    if(vs->ppu < RCP2C03B) pale = vs->ppu;\r
339    //puts(vs->name);\r
340    *MapperNo = vs->mapper;\r
341    *Mirroring = vs->mirroring;\r
342    FCEUGameInfo.type = GIT_VSUNI;\r
343    FCEUGameInfo.cspecial = SIS_VSUNISYSTEM;\r
344    FCEUGameInfo.inputfc = SIFC_NONE;\r
345    curppu = vs->ppu;\r
346    curmd5 = md5partial;\r
347 \r
348    secptr = 0;\r
349 \r
350    {\r
351     static int64 tko=0x6e1ee06171d8ce3aULL, rbi=0x6a02d345812938afULL;\r
352     if(md5partial == tko)\r
353      secptr=secdata[0];\r
354     if(md5partial == rbi)\r
355      secptr = secdata[1];\r
356    }\r
357 \r
358    vsdip = 0x0;\r
359    if(vs->ioption & IOPTION_PREDIP)\r
360    {\r
361     vsdip= vs->predip;\r
362    }\r
363    if(vs->ioption & IOPTION_GUN)\r
364    {\r
365     FCEUGameInfo.input[0] = SI_ZAPPER;\r
366     FCEUGameInfo.input[1] = SI_NONE;\r
367    }\r
368    else\r
369    {\r
370     FCEUGameInfo.input[0] = FCEUGameInfo.input[1] = SI_GAMEPAD;\r
371    }\r
372    curvs = vs;\r
373    return;\r
374   }\r
375   vs++;\r
376  }\r
377 }\r
378 \r
379 void FCEU_VSUniDraw(uint8 *XBuf)\r
380 {\r
381   uint32 *dest;\r
382   int y,x;\r
383 \r
384   if(!DIPS) return;\r
385 \r
386   dest=(uint32 *)(XBuf+256*12+164);\r
387   for(y=24;y;y--,dest+=(256-72)>>2)\r
388   {\r
389    for(x=72>>2;x;x--,dest++)\r
390     *dest=0;\r
391   }\r
392 \r
393   dest=(uint32 *)(XBuf+256*(12+4)+164+6 );\r
394   for(y=16;y;y--,dest+=(256>>2)-16)\r
395    for(x=8;x;x--)\r
396    {\r
397     *dest=0x01010101;\r
398     dest+=2;\r
399    }\r
400 \r
401   dest=(uint32 *)(XBuf+256*(12+4)+164+6 );\r
402   for(x=0;x<8;x++,dest+=2)\r
403   {\r
404    uint32 *da=dest+(256>>2);\r
405 \r
406    if(!((vsdip>>x)&1))\r
407     da+=(256>>2)*10;\r
408    for(y=4;y;y--,da+=256>>2)\r
409     *da=0;\r
410   }\r
411 }\r
412 \r
413 \r
414 SFORMAT FCEUVSUNI_STATEINFO[]={\r
415   { &vsdip, 1, "vsdp"},\r
416   { &coinon, 1, "vscn"},\r
417   { &VSindex, 1, "vsin"},\r
418   { 0}\r
419 };\r