d97315ac |
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 |