compat hacks for this old version of fceu
[fceu.git] / ines.c
... / ...
CommitLineData
1/* FCE Ultra - NES/Famicom Emulator\r
2*\r
3* Copyright notice for this file:\r
4* Copyright (C) 1998 BERO\r
5* Copyright (C) 2002 Xodnizel\r
6*\r
7* This program is free software; you can redistribute it and/or modify\r
8* it under the terms of the GNU General Public License as published by\r
9* the Free Software Foundation; either version 2 of the License, or\r
10* (at your option) any later version.\r
11*\r
12* This program is distributed in the hope that it will be useful,\r
13* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
15* GNU General Public License for more details.\r
16*\r
17* You should have received a copy of the GNU General Public License\r
18* along with this program; if not, write to the Free Software\r
19* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\r
20*/\r
21\r
22#include <stdio.h>\r
23#include <stdlib.h>\r
24#include <string.h>\r
25\r
26#include "types.h"\r
27#include "x6502.h"\r
28#include "fce.h"\r
29#include "cart.h"\r
30#include "ppu.h"\r
31\r
32#define INESPRIV\r
33#include "ines.h"\r
34#include "unif.h"\r
35#include "state.h"\r
36#include "file.h"\r
37#include "general.h"\r
38#include "memory.h"\r
39#include "crc32.h"\r
40#include "md5.h"\r
41#include "cheat.h"\r
42#include "vsuni.h"\r
43#include "driver.h"\r
44#include "svga.h"\r
45\r
46extern SFORMAT FCEUVSUNI_STATEINFO[];\r
47\r
48//mbg merge 6/29/06 - these need to be global\r
49uint8 *trainerpoo=0;\r
50uint8 *ROM = NULL;\r
51uint8 *VROM = NULL;\r
52struct iNES_HEADER head;\r
53\r
54\r
55\r
56static CartInfo iNESCart;\r
57\r
58uint8 iNESMirroring=0;\r
59uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0};\r
60int32 iNESIRQLatch=0,iNESIRQCount=0;\r
61uint8 iNESIRQa=0;\r
62\r
63uint32 ROM_size=0;\r
64uint32 VROM_size=0;\r
65//char LoadedRomFName[2048]; //mbg merge 7/17/06 added\r
66\r
67static int CHRRAMSize = -1;\r
68static void iNESPower(void);\r
69static int NewiNES_Init(int num);\r
70\r
71void (*MapClose)(void);\r
72void (*MapperReset)(void);\r
73\r
74static int MapperNo=0;\r
75\r
76/* MapperReset() is called when the NES is reset(with the reset button).\r
77Mapperxxx_init is called when the NES has been powered on.\r
78*/\r
79\r
80\r
81static DECLFR(TrainerRead)\r
82{\r
83 return(trainerpoo[A&0x1FF]);\r
84}\r
85\r
86static void iNES_ExecPower()\r
87{\r
88 if(CHRRAMSize != -1)\r
89 FCEU_MemoryRand(VROM,CHRRAMSize);\r
90\r
91 if(iNESCart.Power)\r
92 iNESCart.Power();\r
93\r
94 if(trainerpoo)\r
95 {\r
96 int x;\r
97 for(x=0;x<512;x++)\r
98 {\r
99 //X6502_DMW(0x7000+x,trainerpoo[x]);\r
100 //if(X6502_DMR(0x7000+x)!=trainerpoo[x])\r
101 unsigned int A=0x7000+x;\r
102 BWrite[A](A,trainerpoo[x]);\r
103 if(ARead[A](A)!=trainerpoo[x])\r
104 {\r
105 SetReadHandler(0x7000,0x71FF,TrainerRead);\r
106 break;\r
107 }\r
108 }\r
109 }\r
110}\r
111\r
112static void iNESGI(int h, void *param)\r
113{\r
114 switch(h)\r
115 {\r
116 case GI_RESETSAVE:\r
117 //FCEU_ClearGameSave(&iNESCart);\r
118 break;\r
119\r
120 case GI_RESETM2:\r
121 if(MapperReset)\r
122 MapperReset();\r
123 if(iNESCart.Reset)\r
124 iNESCart.Reset();\r
125 break;\r
126 case GI_POWER:\r
127 iNES_ExecPower();\r
128 \r
129 break;\r
130 case GI_CLOSE:\r
131 {\r
132 FCEU_SaveGameSave(&iNESCart);\r
133\r
134 if(iNESCart.Close) iNESCart.Close();\r
135 if(ROM) {free(ROM); ROM = NULL;}\r
136 if(VROM) {free(VROM); VROM = NULL;}\r
137 if(MapClose) MapClose();\r
138 if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;}\r
139 }\r
140 break;\r
141 case GI_INFOSTRING:\r
142 {\r
143 int MapperNo;\r
144 MapperNo = (head.ROM_type>>4);\r
145 MapperNo|=(head.ROM_type2&0xF0);\r
146 sprintf(param, "iNES, %s, Mapper: %d%s%s", PAL?"PAL":"NTSC",\r
147 MapperNo, (head.ROM_type&2)?", BB":"", (head.ROM_type&4)?", T":"");\r
148 }\r
149 break;\r
150 }\r
151}\r
152\r
153uint32 iNESGameCRC32=0;\r
154\r
155struct CRCMATCH {\r
156 uint32 crc;\r
157 char *name;\r
158};\r
159\r
160struct INPSEL {\r
161 uint32 crc32;\r
162 int input1;\r
163 int input2;\r
164 int inputfc;\r
165};\r
166\r
167static void SetInput(void)\r
168{\r
169 static struct INPSEL moo[]=\r
170 {\r
171 {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, // Nekketsu Kakutou Densetsu\r
172\r
173 {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, // The two "Oeka Kids" games\r
174 {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, //\r
175\r
176 {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // World Class Track Meet\r
177 {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Super Team Games\r
178 {0x61d86167,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Street Cop\r
179 {0x6435c095,SI_GAMEPAD,SI_POWERPADB,SIFC_UNSET}, // Short Order/Eggsplode\r
180\r
181\r
182 {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, // Top Rider\r
183\r
184 {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, // Barcode World\r
185 {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Super Mogura Tataki!! - Pokkun Moguraa\r
186 {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Rairai Kyonshizu\r
187 {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Jogging Race\r
188 {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, // Athletic World\r
189\r
190 {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Totsugeki Fuuun Takeshi Jou\r
191 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Running Stadium\r
192 {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Meiro Dai Sakusen\r
193 // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Fuun Takeshi Jou 2\r
194 {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Dai Undoukai\r
195 {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Aerobics Studio\r
196 {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Manhattan Police\r
197 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, // Family Trainer: Running Stadium\r
198\r
199 {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ...\r
200 {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, // Gimme a Break ... 2\r
201\r
202 {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong 2\r
203 {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, // Ide Yousuke Meijin no Jissen Mahjong\r
204\r
205 {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic\r
206 {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Olympic (Gentei Ban)\r
207 {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, // Hyper Sports\r
208 {0xad9c63e2,SI_GAMEPAD,SI_UNSET,SIFC_SHADOW}, // Space Shadow\r
209\r
210 {0x24598791,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Duck Hunt\r
211 {0xff24d794,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Hogan's Alley\r
212 {0xbeb8ab01,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gumshoe\r
213 {0xde8fd935,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // To the Earth\r
214 {0xedc3662b,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf\r
215 {0x2a6559a1,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Operation Wolf (J)\r
216 {0x4e959173,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Gotcha! - The Sport!\r
217\r
218 {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // The Lone Ranger\r
219 {0xb8b9aca3,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman\r
220 {0x5112dc21,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Wild Gunman\r
221 {0x4318a2f8,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Barker Bill's Trick Shooting\r
222 {0x5ee6008e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Mechanized Attack\r
223 {0x3e58a87e,SI_UNSET,SI_ZAPPER,SIFC_NONE}, // Freedom Force\r
224 {0xe9a7fe9e,SI_UNSET,SI_MOUSE,SIFC_NONE}, // Educational Computer 2000 //mbg merge 7/17/06 added -- appears to be from newer MM build\r
225 {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Shooting Range\r
226 {0x74bea652,SI_GAMEPAD,SI_ZAPPER,SIFC_NONE}, // Supergun 3-in-1\r
227 {0x32fb0583,SI_UNSET,SI_ARKANOID,SIFC_NONE}, // Arkanoid(NES)\r
228 {0xd89e5a67,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid (J)\r
229 {0x0f141525,SI_UNSET,SI_UNSET,SIFC_ARKANOID}, // Arkanoid 2(J)\r
230\r
231 {0x912989dc,SI_UNSET,SI_UNSET,SIFC_FKB}, // Playbox BASIC\r
232 {0xf7606810,SI_UNSET,SI_UNSET,SIFC_FKB}, // Family BASIC 2.0A\r
233 {0x895037bc,SI_UNSET,SI_UNSET,SIFC_FKB}, // Family BASIC 2.1a\r
234 {0xb2530afc,SI_UNSET,SI_UNSET,SIFC_FKB}, // Family BASIC 3.0\r
235 {0x82f1fb96,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Subor 1.0 Russian\r
236 {0xabb2f974,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Study and Game 32-in-1\r
237 {0xd5d6eac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Edu (As)\r
238 {0x589b6b0d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV20\r
239 {0x5e073a1b,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // Supor English (Chinese)\r
240 {0x8b265862,SI_UNSET,SI_UNSET,SIFC_SUBORKB},\r
241 {0x41401c6d,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // SuporV40\r
242 {0x41ef9ac4,SI_UNSET,SI_UNSET,SIFC_SUBORKB},\r
243 {0x368c19a8,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Study Cartridge\r
244 {0x543ab532,SI_UNSET,SI_UNSET,SIFC_SUBORKB}, // LIKO Color Lines\r
245 {0,SI_UNSET,SI_UNSET,SIFC_UNSET}\r
246 };\r
247 int x=0;\r
248\r
249 while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0)\r
250 {\r
251 if(moo[x].crc32==iNESGameCRC32)\r
252 {\r
253 GameInfo->input[0]=moo[x].input1;\r
254 GameInfo->input[1]=moo[x].input2;\r
255 GameInfo->inputfc=moo[x].inputfc;\r
256 break;\r
257 }\r
258 x++;\r
259 }\r
260}\r
261\r
262#define INESB_INCOMPLETE 1\r
263#define INESB_CORRUPT 2\r
264#define INESB_HACKED 4\r
265\r
266struct BADINF {\r
267 uint64 md5partial;\r
268 char *name;\r
269 uint32 type;\r
270};\r
271\r
272\r
273static struct BADINF BadROMImages[]=\r
274{\r
275#include "ines-bad.h"\r
276};\r
277\r
278void CheckBad(uint64 md5partial)\r
279{\r
280 int x;\r
281\r
282 x=0;\r
283 //printf("0x%llx\n",md5partial);\r
284 while(BadROMImages[x].name)\r
285 {\r
286 if(BadROMImages[x].md5partial == md5partial)\r
287 {\r
288 FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly in FCEUX.", BadROMImages[x].name);\r
289 return;\r
290 }\r
291 x++;\r
292 }\r
293\r
294}\r
295\r
296\r
297struct CHINF {\r
298 uint32 crc32;\r
299 int32 mapper;\r
300 int32 mirror;\r
301 const char* params;\r
302};\r
303\r
304void MapperInit()\r
305{\r
306 if(NewiNES_Init(MapperNo))\r
307 {\r
308\r
309 }\r
310 else\r
311 {\r
312 iNESCart.Power=iNESPower;\r
313 if(head.ROM_type&2)\r
314 {\r
315 iNESCart.SaveGame[0]=WRAM;\r
316 iNESCart.SaveGameLen[0]=8192;\r
317 }\r
318 }\r
319}\r
320\r
321#if 0\r
322static const TMasterRomInfo sMasterRomInfo[] = {\r
323 { 0x62b51b108a01d2beLL, "bonus=0" }, //4-in-1 (FK23C8021)[p1][!].nes\r
324 { 0x8bb48490d8d22711LL, "bonus=0" }, //4-in-1 (FK23C8033)[p1][!].nes\r
325 { 0xc75888d7b48cd378LL, "bonus=0" }, //4-in-1 (FK23C8043)[p1][!].nes\r
326 { 0xf81a376fa54fdd69LL, "bonus=0" }, //4-in-1 (FK23Cxxxx, S-0210A PCB)[p1][!].nes\r
327 { 0xa37eb9163e001a46LL, "bonus=0" }, //4-in-1 (FK23C8026) [p1][!].nes\r
328 { 0xde5ce25860233f7eLL, "bonus=0" }, //4-in-1 (FK23C8045) [p1][!].nes\r
329 { 0x5b3aa4cdc484a088LL, "bonus=0" }, //4-in-1 (FK23C8056) [p1][!].nes\r
330 { 0x9342bf9bae1c798aLL, "bonus=0" }, //4-in-1 (FK23C8079) [p1][!].nes\r
331 { 0x164eea6097a1e313LL, "busc=1" }, //Cybernoid - The Fighting Machine (U)[!].nes -- needs bus conflict emulation\r
332};\r
333const TMasterRomInfo* MasterRomInfo;\r
334TMasterRomInfoParams MasterRomInfoParams;\r
335#endif\r
336\r
337static void CheckHInfo(void)\r
338{\r
339 /* ROM images that have the battery-backed bit set in the header that really\r
340 don't have battery-backed RAM is not that big of a problem, so I'll\r
341 treat this differently by only listing games that should have battery-backed RAM.\r
342\r
343 Lower 64 bits of the MD5 hash.\r
344 */\r
345\r
346 static uint64 savie[]=\r
347 {\r
348 0x498c10dc463cfe95LL, /* Battle Fleet */\r
349 0x6917ffcaca2d8466LL, /* Famista '90 */\r
350\r
351 0xd63dcc68c2b20adcLL, /* Final Fantasy J */\r
352 0x012df596e2b31174LL, /* Final Fantasy 1+2 */\r
353 0xf6b359a720549ecdLL, /* Final Fantasy 2 */\r
354 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */\r
355\r
356 0x2ee3417ba8b69706LL, /* Hydlide 3*/\r
357\r
358 0xebbce5a54cf3ecc0LL, /* Justbreed */\r
359\r
360 0x6a858da551ba239eLL, /* Kaijuu Monogatari */\r
361 0xa40666740b7d22feLL, /* Mindseeker */\r
362\r
363 0x77b811b2760104b9LL, /* Mouryou Senki Madara */\r
364\r
365 0x11b69122efe86e8cLL, /* RPG Jinsei Game */\r
366\r
367 0xa70b495314f4d075LL, /* Ys 3 */\r
368\r
369\r
370 0xc04361e499748382LL, /* AD&D Heroes of the Lance */\r
371 0xb72ee2337ced5792LL, /* AD&D Hillsfar */\r
372 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */\r
373\r
374 0x854d7947a3177f57LL, /* Crystalis */\r
375\r
376 0xb0bcc02c843c1b79LL, /* DW */\r
377 0x4a1f5336b86851b6LL, /* DW */\r
378\r
379 0x2dcf3a98c7937c22LL, /* DW 2 */\r
380 0x733026b6b72f2470LL, /* Dw 3 */\r
381 0x98e55e09dfcc7533LL, /* DW 4*/\r
382 0x8da46db592a1fcf4LL, /* Faria */\r
383 0x91a6846d3202e3d6LL, /* Final Fantasy */\r
384 0xedba17a2c4608d20LL, /* "" */\r
385\r
386 0x94b9484862a26cbaLL, /* Legend of Zelda */\r
387 0x04a31647de80fdabLL, /* "" */\r
388\r
389 0x9aa1dc16c05e7de5LL, /* Startropics */\r
390 0x1b084107d0878bd0LL, /* Startropics 2*/\r
391\r
392 0x836c0ff4f3e06e45LL, /* Zelda 2 */\r
393\r
394 0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */\r
395\r
396 0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */\r
397 };\r
398\r
399 static struct CHINF moo[]=\r
400 {\r
401#include "ines-correct.h"\r
402 };\r
403 int tofix=0;\r
404 int x;\r
405 uint64 partialmd5=0;\r
406\r
407 for(x=0;x<8;x++)\r
408 {\r
409 partialmd5 |= (uint64)iNESCart.MD5[15-x] << (x*8);\r
410 //printf("%16llx\n",partialmd5);\r
411 }\r
412 CheckBad(partialmd5);\r
413\r
414#if 0\r
415 MasterRomInfo = NULL;\r
416 MasterRomInfoParams = TMasterRomInfoParams();\r
417 for(int i=0;i<ARRAY_SIZE(sMasterRomInfo);i++)\r
418 {\r
419 const TMasterRomInfo& info = sMasterRomInfo[i];\r
420 if(info.md5lower != partialmd5)\r
421 continue;\r
422 \r
423 MasterRomInfo = &info;\r
424 if(!info.params) break;\r
425 \r
426 std::vector<std::string> toks = tokenize_str(info.params,",");\r
427 for(int j=0;j<(int)toks.size();j++)\r
428 {\r
429 std::vector<std::string> parts = tokenize_str(toks[j],"=");\r
430 MasterRomInfoParams[parts[0]] = parts[1];\r
431 }\r
432 break;\r
433 }\r
434#endif\r
435\r
436 x=0;\r
437\r
438 do\r
439 {\r
440 if(moo[x].crc32==iNESGameCRC32)\r
441 {\r
442 if(moo[x].mapper>=0)\r
443 {\r
444 if(moo[x].mapper&0x800 && VROM_size)\r
445 {\r
446 VROM_size=0;\r
447 free(VROM);\r
448 VROM = NULL;\r
449 tofix|=8;\r
450 }\r
451 if(MapperNo!=(moo[x].mapper&0xFF))\r
452 {\r
453 tofix|=1;\r
454 MapperNo=moo[x].mapper&0xFF;\r
455 }\r
456 }\r
457 if(moo[x].mirror>=0)\r
458 {\r
459 if(moo[x].mirror==8)\r
460 {\r
461 if(Mirroring==2) /* Anything but hard-wired(four screen). */\r
462 {\r
463 tofix|=2;\r
464 Mirroring=0;\r
465 }\r
466 }\r
467 else if(Mirroring!=moo[x].mirror)\r
468 {\r
469 if(Mirroring!=(moo[x].mirror&~4))\r
470 if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring\r
471 needs to be set(the iNES header can't\r
472 hold this information).\r
473 */\r
474 tofix|=2;\r
475 Mirroring=moo[x].mirror;\r
476 }\r
477 }\r
478 break;\r
479 }\r
480 x++;\r
481 } while(moo[x].mirror>=0 || moo[x].mapper>=0);\r
482\r
483 x=0;\r
484 while(savie[x] != 0)\r
485 {\r
486 if(savie[x] == partialmd5)\r
487 {\r
488 if(!(head.ROM_type&2))\r
489 {\r
490 tofix|=4;\r
491 head.ROM_type|=2;\r
492 }\r
493 }\r
494 x++;\r
495 }\r
496\r
497 /* Games that use these iNES mappers tend to have the four-screen bit set\r
498 when it should not be.\r
499 */\r
500 if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2))\r
501 {\r
502 Mirroring=0;\r
503 tofix|=2;\r
504 }\r
505\r
506 /* Four-screen mirroring implicitly set. */\r
507 if(MapperNo==99)\r
508 Mirroring=2;\r
509\r
510 if(tofix)\r
511 {\r
512 char gigastr[768];\r
513 strcpy(gigastr,"The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");\r
514 if(tofix&1)\r
515 sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d. ",MapperNo);\r
516 if(tofix&2)\r
517 {\r
518 char *mstr[3]={"Horizontal","Vertical","Four-screen"};\r
519 sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]);\r
520 }\r
521 if(tofix&4)\r
522 strcat(gigastr,"The battery-backed bit should be set. ");\r
523 if(tofix&8)\r
524 strcat(gigastr,"This game should not have any CHR ROM. ");\r
525 strcat(gigastr,"\n");\r
526 FCEU_printf("%s",gigastr);\r
527 }\r
528}\r
529\r
530typedef struct {\r
531 int mapper;\r
532 void (*init)(CartInfo *);\r
533} NewMI;\r
534\r
535//this is for games that is not the a power of 2\r
536//mapper based for now...\r
537//not really accurate but this works since games\r
538//that are not in the power of 2 tends to come\r
539//in obscure mappers themselves which supports such\r
540//size\r
541static int not_power2[] =\r
542{\r
543 228\r
544};\r
545typedef struct {\r
546 char* name;\r
547 int number;\r
548 void (*init)(CartInfo *);\r
549} BMAPPINGLocal;\r
550\r
551static BMAPPINGLocal bmap[] = {\r
552 {"NROM", 0, NROM_Init},\r
553 {"MMC1", 1, Mapper1_Init},\r
554 {"UNROM", 2, UNROM_Init},\r
555 {"CNROM", 3, CNROM_Init},\r
556 {"MMC3", 4, Mapper4_Init},\r
557 {"MMC5", 5, Mapper5_Init},\r
558// {6, Mapper6_Init},\r
559 {"ANROM", 7, ANROM_Init},\r
560 {"", 8, Mapper8_Init}, // Nogaems, it's worthless\r
561// {9, Mapper9_Init},\r
562// {10, Mapper10_Init},\r
563 {"Color Dreams", 11, Mapper11_Init},\r
564 {"", 12, Mapper12_Init},\r
565 {"CPROM", 13, CPROM_Init},\r
566// {14, Mapper14_Init},\r
567 {"100-in1", 15, Mapper15_Init},\r
568 {"Bandai", 16, Mapper16_Init},\r
569 {"", 17, Mapper17_Init},\r
570 {"", 18, Mapper18_Init},\r
571 {"Namcot 106", 19, Mapper19_Init},\r
572// {20, Mapper20_Init},\r
573// {21, Mapper21_Init},\r
574// {22, Mapper22_Init},\r
575 {"Konami VRC2 type B", 23, Mapper23_Init},\r
576// {24, Mapper24_Init},\r
577// {25, Mapper25_Init},\r
578// {26, Mapper26_Init},\r
579// {27, Mapper27_Init},\r
580// {28, Mapper28_Init},\r
581// {29, Mapper29_Init},\r
582// {30, Mapper30_Init},\r
583// {31, Mapper31_Init},\r
584// {32, Mapper32_Init},\r
585// {33, Mapper33_Init},\r
586 {"", 34, Mapper34_Init},\r
587 {"Wario Land 2", 35, UNLSC127_Init}, // Wario Land 2\r
588 {"TXC Policeman", 36, Mapper36_Init}, // TXC Policeman\r
589 {"", 37, Mapper37_Init},\r
590 {"Bit Corp. Crime Busters", 38, Mapper38_Init}, // Bit Corp. Crime Busters\r
591// {39, Mapper39_Init},\r
592// {40, Mapper40_Init},\r
593// {41, Mapper41_Init},\r
594// {42, Mapper42_Init},\r
595 {"", 43, Mapper43_Init},\r
596 {"", 44, Mapper44_Init},\r
597 {"", 45, Mapper45_Init},\r
598// {46, Mapper46_Init},\r
599 {"", 47, Mapper47_Init},\r
600// {48, Mapper48_Init},\r
601 {"", 49, Mapper49_Init},\r
602// {50, Mapper50_Init},\r
603// {51, Mapper51_Init},\r
604 {"", 52, Mapper52_Init},\r
605// {53, Mapper53_Init},\r
606// {54, Mapper54_Init},\r
607// {55, Mapper55_Init},\r
608// {56, Mapper56_Init},\r
609 {"", 57, Mapper57_Init},\r
610 {"", 58, BMCGK192_Init},\r
611// {59, Mapper59_Init},\r
612 {"", 60, BMCD1038_Init},\r
613// {61, Mapper61_Init},\r
614// {62, Mapper62_Init},\r
615// {63, Mapper63_Init},\r
616// {64, Mapper64_Init},\r
617// {65, Mapper65_Init},\r
618 {"MHROM", 66, MHROM_Init},\r
619// {67, Mapper67_Init},\r
620 {"Sunsoft Mapper #4", 68, Mapper68_Init},\r
621// {69, Mapper69_Init},\r
622 {"", 70, Mapper70_Init},\r
623// {71, Mapper71_Init},\r
624// {72, Mapper72_Init},\r
625// {73, Mapper73_Init},\r
626 {"", 74, Mapper74_Init},\r
627// {75, Mapper75_Init},\r
628// {76, Mapper76_Init},\r
629// {77, Mapper77_Init},\r
630 {"Irem 74HC161/32", 78, Mapper78_Init},\r
631// {79, Mapper79_Init},\r
632// {80, Mapper80_Init},\r
633// {81, Mapper81_Init},\r
634 {"", 82, Mapper82_Init},\r
635 {"", 83, Mapper83_Init},\r
636// {84, Mapper84_Init},\r
637// {85, Mapper85_Init},\r
638 {"", 86, Mapper86_Init},\r
639 {"", 87, Mapper87_Init},\r
640 {"", 88, Mapper88_Init},\r
641 {"", 89, Mapper89_Init},\r
642 {"", 90, Mapper90_Init},\r
643 {"", 91, Mapper91_Init},\r
644 {"", 92, Mapper92_Init},\r
645 {"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init},\r
646 {"", 94, Mapper94_Init},\r
647 {"", 95, Mapper95_Init},\r
648 {"", 96, Mapper96_Init},\r
649 {"", 97, Mapper97_Init},\r
650// {98, Mapper98_Init},\r
651 {"", 99, Mapper99_Init},\r
652// {100, Mapper100_Init},\r
653 {"", 101, Mapper101_Init},\r
654// {102, Mapper102_Init},\r
655 {"", 103, Mapper103_Init},\r
656// {104, Mapper104_Init},\r
657 {"", 105, Mapper105_Init},\r
658 {"", 106, Mapper106_Init},\r
659 {"", 107, Mapper107_Init},\r
660 {"", 108, Mapper108_Init},\r
661// {109, Mapper109_Init},\r
662// {110, Mapper110_Init},\r
663// {111, Mapper111_Init},\r
664 {"", 112, Mapper112_Init},\r
665 {"", 113, Mapper113_Init},\r
666 {"", 114, Mapper114_Init},\r
667 {"", 115, Mapper115_Init},\r
668 {"UNLSL12", 116, UNLSL12_Init},\r
669 {"", 117, Mapper117_Init},\r
670 {"TSKROM", 118, TKSROM_Init},\r
671 {"", 119, Mapper119_Init},\r
672 {"", 120, Mapper120_Init},\r
673 {"", 121, Mapper121_Init},\r
674// {122, Mapper122_Init},\r
675 {"UNLH2288", 123, UNLH2288_Init},\r
676// {124, Mapper124_Init},\r
677// {125, Mapper125_Init},\r
678// {126, Mapper126_Init},\r
679// {127, Mapper127_Init},\r
680// {128, Mapper128_Init},\r
681// {129, Mapper129_Init},\r
682// {130, Mapper130_Init},\r
683// {131, Mapper131_Init},\r
684 {"UNL22211", 132, UNL22211_Init},\r
685 {"SA72008", 133, SA72008_Init},\r
686 {"", 134, Mapper134_Init},\r
687// {135, Mapper135_Init},\r
688 {"TCU02", 136, TCU02_Init},\r
689 {"S8259D", 137, S8259D_Init},\r
690 {"S8259B", 138, S8259B_Init},\r
691 {"S8259C", 139, S8259C_Init},\r
692 {"", 140, Mapper140_Init},\r
693 {"S8259A", 141, S8259A_Init},\r
694 {"UNLKS7032", 142, UNLKS7032_Init},\r
695 {"TCA01", 143, TCA01_Init},\r
696 {"", 144, Mapper144_Init},\r
697 {"SA72007", 145, SA72007_Init},\r
698 {"SA0161M", 146, SA0161M_Init},\r
699 {"TCU01", 147, TCU01_Init},\r
700 {"SA0037", 148, SA0037_Init},\r
701 {"SA0036", 149, SA0036_Init},\r
702 {"S74LS374N", 150, S74LS374N_Init},\r
703 {"", 151, Mapper151_Init},\r
704 {"", 152, Mapper152_Init},\r
705 {"", 153, Mapper153_Init},\r
706 {"", 154, Mapper154_Init},\r
707 {"", 155, Mapper155_Init},\r
708 {"", 156, Mapper156_Init},\r
709 {"", 157, Mapper157_Init},\r
710// {158, Mapper158_Init},\r
711// {159, Mapper159_Init},\r
712 {"SA009", 160, SA009_Init},\r
713// {161, Mapper161_Init},\r
714 {"", 162, UNLFS304_Init},\r
715 {"", 163, Mapper163_Init},\r
716 {"", 164, Mapper164_Init},\r
717 {"", 165, Mapper165_Init},\r
718// {166, Mapper166_Init},\r
719// {167, Mapper167_Init},\r
720 {"", 168, Mapper168_Init},\r
721// {169, Mapper169_Init},\r
722 {"", 171, Mapper171_Init},\r
723 {"", 172, Mapper172_Init},\r
724 {"", 173, Mapper173_Init},\r
725 {"", 175, Mapper175_Init},\r
726// {174, Mapper174_Init},\r
727 {"", 175, Mapper175_Init},\r
728 {"BMCFK23C", 176, BMCFK23C_Init},\r
729 {"", 177, Mapper177_Init},\r
730 {"", 178, Mapper178_Init},\r
731// {179, Mapper179_Init},\r
732 {"", 180, Mapper180_Init},\r
733 {"", 181, Mapper181_Init},\r
734// {"", 182, Mapper182_Init}, // identical to 114\r
735 {"", 183, Mapper183_Init},\r
736 {"", 184, Mapper184_Init},\r
737 {"", 185, Mapper185_Init},\r
738 {"", 186, Mapper186_Init},\r
739 {"", 187, Mapper187_Init},\r
740 {"", 188, Mapper188_Init},\r
741 {"", 189, Mapper189_Init},\r
742// {190, Mapper190_Init},\r
743 {"", 191, Mapper191_Init},\r
744 {"", 192, Mapper192_Init},\r
745 {"", 193, Mapper193_Init},\r
746 {"", 194, Mapper194_Init},\r
747 {"", 195, Mapper195_Init},\r
748 {"", 196, Mapper196_Init},\r
749 {"", 197, Mapper197_Init},\r
750 {"", 198, Mapper198_Init},\r
751 {"", 199, Mapper199_Init},\r
752 {"", 200, Mapper200_Init},\r
753// {201, Mapper201_Init},\r
754// {202, Mapper202_Init},\r
755// {203, Mapper203_Init},\r
756// {204, Mapper204_Init},\r
757 {"", 205, Mapper205_Init},\r
758 {"DEIROM", 206, DEIROM_Init},\r
759// {207, Mapper207_Init},\r
760 {"", 208, Mapper208_Init},\r
761 {"", 209, Mapper209_Init},\r
762 {"", 210, Mapper210_Init},\r
763 {"", 211, Mapper211_Init},\r
764// {212, Mapper212_Init},\r
765// {213, Mapper213_Init},\r
766// {214, Mapper214_Init},\r
767 {"", 215, UNL8237_Init},\r
768 {"", 216, Mapper216_Init},\r
769// {"", 217, Mapper217_Init},\r
770// {218, Mapper218_Init},\r
771 {"UNLA9746", 219, UNLA9746_Init},\r
772 {"", 220, UNLKS7057_Init}, // DEBUG mapper\r
773 {"UNLN625092", 221, UNLN625092_Init},\r
774 {"", 222, Mapper222_Init},\r
775// {223, Mapper223_Init},\r
776// {224, Mapper224_Init},\r
777 {"", 225, Mapper225_Init},\r
778 {"", 226, Mapper226_Init},\r
779// {227, Mapper227_Init},\r
780// {228, Mapper228_Init},\r
781// {229, Mapper229_Init},\r
782// {230, Mapper230_Init},\r
783// {231, Mapper231_Init},\r
784// {232, Mapper232_Init},\r
785 {"BMC42in1r", 233, BMC42in1r_Init},\r
786// {234, Mapper234_Init},\r
787 {"", 235, Mapper235_Init},\r
788// {236, Mapper236_Init},\r
789// {237, Mapper237_Init},\r
790 {"UNL6035052", 238, UNL6035052_Init},\r
791// {239, Mapper239_Init},\r
792 {"", 240, Mapper240_Init},\r
793// {241, Mapper241_Init},\r
794// {242, Mapper242_Init},\r
795 {"S74LS374NA", 243, S74LS374NA_Init},\r
796// {244, Mapper244_Init},\r
797 {"", 245, Mapper245_Init},\r
798// {246, Mapper246_Init},\r
799// {247, Mapper247_Init},\r
800// {248, Mapper248_Init},\r
801 {"", 249, Mapper249_Init},\r
802 {"", 250, Mapper250_Init},\r
803// {251, Mapper251_Init},\r
804// {252, Mapper252_Init},\r
805 {"", 253, Mapper253_Init},\r
806 {"", 254, Mapper254_Init},\r
807// {255, Mapper255_Init},\r
808 {"", 0, 0}\r
809};\r
810\r
811void cleanup(struct iNES_HEADER *this)\r
812{\r
813 if(!memcmp((char *)(this)+0x7,"DiskDude",8))\r
814 {\r
815 memset((char *)(this)+0x7,0,0x9);\r
816 }\r
817\r
818 if(!memcmp((char *)(this)+0x7,"demiforce",9))\r
819 {\r
820 memset((char *)(this)+0x7,0,0x9);\r
821 }\r
822\r
823 if(!memcmp((char *)(this)+0xA,"Ni03",4))\r
824 {\r
825 if(!memcmp((char *)(this)+0x7,"Dis",3))\r
826 memset((char *)(this)+0x7,0,0x9);\r
827 else\r
828 memset((char *)(this)+0xA,0,0x6);\r
829 }\r
830}\r
831\r
832int iNESLoad(const char *name, int fp, int OverwriteVidMode)\r
833{\r
834 struct md5_context md5;\r
835\r
836 if(FCEU_fread(&head,1,16,fp)!=16)\r
837 return 0;\r
838\r
839 if(memcmp(&head,"NES\x1a",4))\r
840 return 0;\r
841\r
842 cleanup(&head);\r
843\r
844 memset(&iNESCart,0,sizeof(iNESCart));\r
845\r
846 MapperNo = (head.ROM_type>>4);\r
847 MapperNo|=(head.ROM_type2&0xF0);\r
848 Mirroring = (head.ROM_type&1);\r
849\r
850\r
851 // int ROM_size=0;\r
852 if(!head.ROM_size)\r
853 {\r
854 // FCEU_PrintError("No PRG ROM!");\r
855 // return(0);\r
856 ROM_size=256;\r
857 //head.ROM_size++;\r
858 }\r
859 else\r
860 ROM_size=uppow2(head.ROM_size);\r
861\r
862 // ROM_size = head.ROM_size;\r
863 VROM_size = head.VROM_size;\r
864\r
865 int round = 1;\r
866 int i;\r
867 for (i = 0; i != sizeof(not_power2)/sizeof(not_power2[0]); ++i)\r
868 {\r
869 //for games not to the power of 2, so we just read enough\r
870 //prg rom from it, but we have to keep ROM_size to the power of 2\r
871 //since PRGCartMapping wants ROM_size to be to the power of 2\r
872 //so instead if not to power of 2, we just use head.ROM_size when\r
873 //we use FCEU_read\r
874 if (not_power2[i] == MapperNo)\r
875 {\r
876 round = 0;\r
877 break;\r
878 }\r
879 }\r
880\r
881 if(VROM_size)\r
882 VROM_size=uppow2(VROM_size);\r
883\r
884\r
885 if(head.ROM_type&8) Mirroring=2;\r
886\r
887 if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;\r
888\r
889 if(VROM_size)\r
890 {\r
891 if((VROM = (uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)\r
892 {\r
893 free(ROM);\r
894 ROM = NULL;\r
895 return 0;\r
896 }\r
897 }\r
898 memset(ROM,0xFF,ROM_size<<14);\r
899 if(VROM_size) memset(VROM,0xFF,VROM_size<<13);\r
900 if(head.ROM_type&4) /* Trainer */\r
901 {\r
902 trainerpoo=(uint8 *)FCEU_gmalloc(512);\r
903 FCEU_fread(trainerpoo,512,1,fp);\r
904 }\r
905\r
906 ResetCartMapping();\r
907 ResetExState(0,0);\r
908\r
909 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);\r
910 // SetupCartPRGMapping(1,WRAM,8192,1); // ?\r
911\r
912 FCEU_fread(ROM,0x4000,(round) ? ROM_size : head.ROM_size,fp);\r
913\r
914 if(VROM_size)\r
915 FCEU_fread(VROM,0x2000,head.VROM_size,fp);\r
916\r
917 md5_starts(&md5);\r
918 md5_update(&md5,ROM,ROM_size<<14);\r
919\r
920 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);\r
921\r
922 if(VROM_size)\r
923 {\r
924 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);\r
925 md5_update(&md5,VROM,VROM_size<<13);\r
926 }\r
927 md5_finish(&md5,iNESCart.MD5);\r
928 memcpy(&GameInfo->MD5,&iNESCart.MD5,sizeof(iNESCart.MD5));\r
929\r
930 iNESCart.CRC32=iNESGameCRC32;\r
931\r
932 FCEU_printf(" PRG ROM: %3d x 16KiB\n CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08lx\n",\r
933 (round) ? ROM_size : head.ROM_size, head.VROM_size,\r
934 (unsigned long)iNESGameCRC32);\r
935\r
936 {\r
937 int x;\r
938 FCEU_printf(" ROM MD5: 0x");\r
939 for(x=0;x<16;x++)\r
940 FCEU_printf("%02x",iNESCart.MD5[x]);\r
941 FCEU_printf("\n");\r
942 }\r
943\r
944 char* mappername = "Not Listed";\r
945 int mappertest;\r
946\r
947 for(mappertest=0;mappertest< (sizeof bmap / sizeof bmap[0]) - 1;mappertest++)\r
948 {\r
949 if (bmap[mappertest].number == MapperNo) {\r
950 mappername = bmap[mappertest].name;\r
951 break;\r
952 }\r
953 }\r
954\r
955 FCEU_printf(" Mapper #: %d\n Mapper name: %s\n Mirroring: %s\n",\r
956 MapperNo, mappername, Mirroring==2?"None (Four-screen)":Mirroring?"Vertical":"Horizontal");\r
957\r
958 FCEU_printf(" Battery-backed: %s\n", (head.ROM_type&2)?"Yes":"No");\r
959 FCEU_printf(" Trained: %s\n", (head.ROM_type&4)?"Yes":"No");\r
960 // (head.ROM_type&8) = Mirroring: None(Four-screen)\r
961\r
962 SetInput();\r
963 CheckHInfo();\r
964 {\r
965 int x;\r
966 uint64 partialmd5=0;\r
967\r
968 for(x=0;x<8;x++)\r
969 {\r
970 partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);\r
971 }\r
972\r
973 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);\r
974 }\r
975 /* Must remain here because above functions might change value of\r
976 VROM_size and free(VROM).\r
977 */\r
978 if(VROM_size)\r
979 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);\r
980\r
981 if(Mirroring==2)\r
982 SetupCartMirroring(4,1,ExtraNTARAM);\r
983 else if(Mirroring>=0x10)\r
984 SetupCartMirroring(2+(Mirroring&1),1,0);\r
985 else\r
986 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);\r
987\r
988 iNESCart.battery=(head.ROM_type&2)?1:0;\r
989 iNESCart.mirror=Mirroring;\r
990\r
991 //if(MapperNo != 18) {\r
992 // if(ROM) free(ROM);\r
993 // if(VROM) free(VROM);\r
994 // ROM=VROM=0;\r
995 // return(0);\r
996 // }\r
997\r
998\r
999 GameInfo->mappernum = MapperNo;\r
1000 MapperInit();\r
1001 FCEU_LoadGameSave(&iNESCart);\r
1002\r
1003 //strcpy(LoadedRomFName,name); //bbit edited: line added\r
1004\r
1005 // Extract Filename only. Should account for Windows/Unix this way.\r
1006 if (strrchr(name, '/')) {\r
1007 name = strrchr(name, '/') + 1;\r
1008 } else if(strrchr(name, '\\')) {\r
1009 name = strrchr(name, '\\') + 1;\r
1010 }\r
1011\r
1012 GameInterface=iNESGI;\r
1013 FCEU_printf("\n");\r
1014\r
1015 // since apparently the iNES format doesn't store this information,\r
1016 // guess if the settings should be PAL or NTSC from the ROM name\r
1017 // TODO: MD5 check against a list of all known PAL games instead?\r
1018 if(OverwriteVidMode)\r
1019 {\r
1020 if(strstr(name,"(E)") || strstr(name,"(e)")\r
1021 || strstr(name,"(F)") || strstr(name,"(f)")\r
1022 || strstr(name,"(G)") || strstr(name,"(g)")\r
1023 || strstr(name,"(I)") || strstr(name,"(i)"))\r
1024 FCEUI_SetVidSystem(1);\r
1025 else\r
1026 FCEUI_SetVidSystem(0);\r
1027 }\r
1028 return 1;\r
1029}\r
1030\r
1031\r
1032//bbit edited: the whole function below was added\r
1033int iNesSave(){\r
1034 FILE *fp;\r
1035 char name[2048];\r
1036\r
1037 if(GameInfo->type != GIT_CART)return 0;\r
1038 if(GameInterface!=iNESGI)return 0;\r
1039\r
1040 //strcpy(name,LoadedRomFName);\r
1041 if (strcmp(name+strlen(name)-4,".nes") != 0) { //para edit\r
1042 strcat(name,".nes");\r
1043 }\r
1044\r
1045 fp = fopen(name,"wb");\r
1046\r
1047 if(fwrite(&head,1,16,fp)!=16)\r
1048 {\r
1049 fclose(fp);\r
1050 return 0;\r
1051 }\r
1052\r
1053 if(head.ROM_type&4) /* Trainer */\r
1054 {\r
1055 fwrite(trainerpoo,512,1,fp);\r
1056 }\r
1057\r
1058 fwrite(ROM,0x4000,ROM_size,fp);\r
1059\r
1060 if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);\r
1061 fclose(fp);\r
1062\r
1063 return 1;\r
1064}\r
1065\r
1066int iNesSaveAs(char* name)\r
1067{\r
1068 //adelikat: TODO: iNesSave() and this have pretty much the same code, outsource the common code to a single function\r
1069 FILE *fp;\r
1070\r
1071 if(GameInfo->type != GIT_CART)return 0;\r
1072 if(GameInterface != iNESGI)return 0;\r
1073\r
1074 fp = fopen(name,"wb");\r
1075\r
1076 if(fwrite(&head,1,16,fp)!=16)\r
1077 {\r
1078 fclose(fp);\r
1079 return 0;\r
1080 }\r
1081\r
1082 if(head.ROM_type&4) /* Trainer */\r
1083 {\r
1084 fwrite(trainerpoo,512,1,fp);\r
1085 }\r
1086\r
1087 fwrite(ROM,0x4000,ROM_size,fp);\r
1088\r
1089 if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);\r
1090 fclose(fp);\r
1091\r
1092 return 1;\r
1093}\r
1094\r
1095//para edit: added function below\r
1096#if 0\r
1097char *iNesShortFName() {\r
1098 char *ret;\r
1099\r
1100 if (!(ret = strrchr(LoadedRomFName,'\\'))) {\r
1101 if (!(ret = strrchr(LoadedRomFName,'/'))) return 0;\r
1102 }\r
1103 return ret+1;\r
1104}\r
1105#endif\r
1106\r
1107void VRAM_BANK1(uint32 A, uint8 V)\r
1108{\r
1109 V&=7;\r
1110 PPUCHRRAM|=(1<<(A>>10));\r
1111 CHRBankList[(A)>>10]=V;\r
1112 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);\r
1113}\r
1114\r
1115void VRAM_BANK4(uint32 A, uint32 V)\r
1116{\r
1117 V&=1;\r
1118 PPUCHRRAM|=(0xF<<(A>>10));\r
1119 CHRBankList[(A)>>10]=(V<<2);\r
1120 CHRBankList[((A)>>10)+1]=(V<<2)+1;\r
1121 CHRBankList[((A)>>10)+2]=(V<<2)+2;\r
1122 CHRBankList[((A)>>10)+3]=(V<<2)+3;\r
1123 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);\r
1124}\r
1125void VROM_BANK1(uint32 A,uint32 V)\r
1126{\r
1127 setchr1(A,V);\r
1128 CHRBankList[(A)>>10]=V;\r
1129}\r
1130\r
1131void VROM_BANK2(uint32 A,uint32 V)\r
1132{\r
1133 setchr2(A,V);\r
1134 CHRBankList[(A)>>10]=(V<<1);\r
1135 CHRBankList[((A)>>10)+1]=(V<<1)+1;\r
1136}\r
1137\r
1138void VROM_BANK4(uint32 A, uint32 V)\r
1139{\r
1140 setchr4(A,V);\r
1141 CHRBankList[(A)>>10]=(V<<2);\r
1142 CHRBankList[((A)>>10)+1]=(V<<2)+1;\r
1143 CHRBankList[((A)>>10)+2]=(V<<2)+2;\r
1144 CHRBankList[((A)>>10)+3]=(V<<2)+3;\r
1145}\r
1146\r
1147void VROM_BANK8(uint32 V)\r
1148{\r
1149 setchr8(V);\r
1150 CHRBankList[0]=(V<<3);\r
1151 CHRBankList[1]=(V<<3)+1;\r
1152 CHRBankList[2]=(V<<3)+2;\r
1153 CHRBankList[3]=(V<<3)+3;\r
1154 CHRBankList[4]=(V<<3)+4;\r
1155 CHRBankList[5]=(V<<3)+5;\r
1156 CHRBankList[6]=(V<<3)+6;\r
1157 CHRBankList[7]=(V<<3)+7;\r
1158}\r
1159\r
1160void ROM_BANK8(uint32 A, uint32 V)\r
1161{\r
1162 setprg8(A,V);\r
1163 if(A>=0x8000)\r
1164 PRGBankList[((A-0x8000)>>13)]=V;\r
1165}\r
1166\r
1167void ROM_BANK16(uint32 A, uint32 V)\r
1168{\r
1169 setprg16(A,V);\r
1170 if(A>=0x8000)\r
1171 {\r
1172 PRGBankList[((A-0x8000)>>13)]=V<<1;\r
1173 PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1;\r
1174 }\r
1175}\r
1176\r
1177void ROM_BANK32(uint32 V)\r
1178{\r
1179 setprg32(0x8000,V);\r
1180 PRGBankList[0]=V<<2;\r
1181 PRGBankList[1]=(V<<2)+1;\r
1182 PRGBankList[2]=(V<<2)+2;\r
1183 PRGBankList[3]=(V<<2)+3;\r
1184}\r
1185\r
1186void onemir(uint8 V)\r
1187{\r
1188 if(Mirroring==2) return;\r
1189 if(V>1)\r
1190 V=1;\r
1191 Mirroring=0x10|V;\r
1192 setmirror(MI_0+V);\r
1193}\r
1194\r
1195void MIRROR_SET2(uint8 V)\r
1196{\r
1197 if(Mirroring==2) return;\r
1198 Mirroring=V;\r
1199 setmirror(V);\r
1200}\r
1201\r
1202void MIRROR_SET(uint8 V)\r
1203{\r
1204 if(Mirroring==2) return;\r
1205 V^=1;\r
1206 Mirroring=V;\r
1207 setmirror(V);\r
1208}\r
1209\r
1210static void NONE_init(void)\r
1211{\r
1212 ROM_BANK16(0x8000,0);\r
1213 ROM_BANK16(0xC000,~0);\r
1214\r
1215 if(VROM_size)\r
1216 VROM_BANK8(0);\r
1217 else\r
1218 setvram8(CHRRAM);\r
1219}\r
1220\r
1221void (*MapInitTab[256])(void)=\r
1222{\r
1223 0,\r
1224 0,\r
1225 0, //Mapper2_init,\r
1226 0, //Mapper3_init,\r
1227 0,\r
1228 0,\r
1229 Mapper6_init,\r
1230 0, //Mapper7_init,\r
1231 0, //Mapper8_init,\r
1232 Mapper9_init,\r
1233 Mapper10_init,\r
1234 0, //Mapper11_init,\r
1235 0, \r
1236 0, //Mapper13_init,\r
1237 0,\r
1238 0, //Mapper15_init,\r
1239 0, //Mapper16_init,\r
1240 0, //Mapper17_init,\r
1241 0, //Mapper18_init,\r
1242 0,\r
1243 0,\r
1244 Mapper21_init,\r
1245 Mapper22_init,\r
1246 0, //Mapper23_init,\r
1247 Mapper24_init,\r
1248 Mapper25_init,\r
1249 Mapper26_init,\r
1250 Mapper27_init,\r
1251 0,\r
1252 0,\r
1253 0,\r
1254 0,\r
1255 Mapper32_init,\r
1256 Mapper33_init,\r
1257 0, //Mapper34_init,\r
1258 0,\r
1259 0,\r
1260 0,\r
1261 0,\r
1262 0,\r
1263 Mapper40_init,\r
1264 Mapper41_init,\r
1265 Mapper42_init,\r
1266 0, //Mapper43_init,\r
1267 0,\r
1268 0,\r
1269 Mapper46_init,\r
1270 0,\r
1271 Mapper48_init,\r
1272 0,\r
1273 Mapper50_init,\r
1274 Mapper51_init,\r
1275 0,\r
1276 0,\r
1277 0,\r
1278 0,\r
1279 0,\r
1280 0, //Mapper57_init,\r
1281 0, //Mapper58_init,\r
1282 Mapper59_init,\r
1283 0, //Mapper60_init,\r
1284 Mapper61_init,\r
1285 Mapper62_init,\r
1286 0,\r
1287 Mapper64_init,\r
1288 Mapper65_init,\r
1289 0, //Mapper66_init,\r
1290 Mapper67_init,\r
1291 0, //Mapper68_init,\r
1292 Mapper69_init,\r
1293 0, //Mapper70_init,\r
1294 Mapper71_init,\r
1295 Mapper72_init,\r
1296 Mapper73_init,\r
1297 0,\r
1298 Mapper75_init,\r
1299 Mapper76_init,\r
1300 Mapper77_init,\r
1301 0, //Mapper78_init,\r
1302 Mapper79_init,\r
1303 Mapper80_init,\r
1304 0,\r
1305 0, //Mapper82_init,\r
1306 0, //Mapper83_init,\r
1307 0,\r
1308 Mapper85_init,\r
1309 0, //Mapper86_init,\r
1310 0, //Mapper87_init,\r
1311 0, //Mapper88_init,\r
1312 0, //Mapper89_init,\r
1313 0,\r
1314 0, //Mapper91_init,\r
1315 0, //Mapper92_init,\r
1316 0, //Mapper93_init,\r
1317 0, //Mapper94_init,\r
1318 0,\r
1319 0, //Mapper96_init,\r
1320 0, //Mapper97_init,\r
1321 0,\r
1322 0, //Mapper99_init,\r
1323 0,\r
1324 0,\r
1325 0,\r
1326 0,\r
1327 0,\r
1328 0,\r
1329 0,\r
1330 0, //Mapper107_init,\r
1331 0,\r
1332 0,\r
1333 0,\r
1334 0,\r
1335 0,\r
1336 0, //Mapper113_init,\r
1337 0,\r
1338 0,\r
1339 0, //Mapper116_init,\r
1340 0, //Mapper117_init,\r
1341 0,\r
1342 0,\r
1343 0,\r
1344 0,\r
1345 0,\r
1346 0,\r
1347 0,\r
1348 0,\r
1349 0,\r
1350 0,\r
1351 0,\r
1352 0,\r
1353 0,\r
1354 0,\r
1355 0,\r
1356 0,\r
1357 0,\r
1358 0,\r
1359 0,\r
1360 0,\r
1361 0,\r
1362 0,\r
1363 0, //Mapper140_init,\r
1364 0,\r
1365 0,\r
1366 0,\r
1367 0, //Mapper144_init,\r
1368 0,\r
1369 0,\r
1370 0,\r
1371 0,\r
1372 0,\r
1373 0,\r
1374 0, //Mapper151_init,\r
1375 0, //Mapper152_init,\r
1376 0, //Mapper153_init,\r
1377 0, //Mapper154_init,\r
1378 0,\r
1379 0, //Mapper156_init,\r
1380 0, //Mapper157_init,\r
1381 0, //Mapper158_init, removed\r
1382 0,\r
1383 0,\r
1384 0,\r
1385 0,\r
1386 0,\r
1387 0,\r
1388 0,\r
1389 Mapper166_init,\r
1390 Mapper167_init,\r
1391 0,\r
1392 0,\r
1393 0,\r
1394 0,\r
1395 0,\r
1396 0,\r
1397 0,\r
1398 0,\r
1399 0,\r
1400 0,\r
1401 0,\r
1402 0,\r
1403 0, //Mapper180_init,\r
1404 0,\r
1405 0,\r
1406 0,\r
1407 0, //Mapper184_init,\r
1408 0, //Mapper185_init,\r
1409 0,\r
1410 0,\r
1411 0,\r
1412 0, //Mapper189_init,\r
1413 0,\r
1414 0, //Mapper191_init,\r
1415 0,\r
1416 0, //Mapper193_init,\r
1417 0,\r
1418 0,\r
1419 0,\r
1420 0,\r
1421 0,\r
1422 0,\r
1423 0, //Mapper200_init,\r
1424 Mapper201_init,\r
1425 Mapper202_init,\r
1426 Mapper203_init,\r
1427 Mapper204_init,\r
1428 0,\r
1429 0,\r
1430 Mapper207_init,\r
1431 0,\r
1432 0,\r
1433 0,\r
1434 0, //Mapper211_init,\r
1435 Mapper212_init,\r
1436 Mapper213_init,\r
1437 Mapper214_init,\r
1438 0,\r
1439 0,\r
1440 0,\r
1441 0,\r
1442 0,\r
1443 0,\r
1444 0,\r
1445 0,\r
1446 0,\r
1447 0,\r
1448 0, //Mapper225_init,\r
1449 0, //Mapper226_init,\r
1450 Mapper227_init,\r
1451 Mapper228_init,\r
1452 Mapper229_init,\r
1453 Mapper230_init,\r
1454 Mapper231_init,\r
1455 Mapper232_init,\r
1456 0,\r
1457 Mapper234_init,\r
1458 0, //Mapper235_init,\r
1459 0,\r
1460 0,\r
1461 0,\r
1462 0,\r
1463 0, //Mapper240_init,\r
1464 Mapper241_init,\r
1465 Mapper242_init,\r
1466 0,\r
1467 Mapper244_init,\r
1468 0,\r
1469 Mapper246_init,\r
1470 0,\r
1471 0,\r
1472 0,\r
1473 0,\r
1474 0,\r
1475 0,\r
1476 0,\r
1477 0,\r
1478 Mapper255_init\r
1479};\r
1480\r
1481static DECLFW(BWRAM)\r
1482{\r
1483 WRAM[A-0x6000]=V;\r
1484}\r
1485\r
1486static DECLFR(AWRAM)\r
1487{\r
1488 return WRAM[A-0x6000];\r
1489}\r
1490\r
1491\r
1492void (*MapStateRestore)(int version);\r
1493void iNESStateRestore(int version)\r
1494{\r
1495 int x;\r
1496\r
1497 if(!MapperNo) return;\r
1498\r
1499 for(x=0;x<4;x++)\r
1500 setprg8(0x8000+x*8192,PRGBankList[x]);\r
1501\r
1502 if(VROM_size)\r
1503 for(x=0;x<8;x++)\r
1504 setchr1(0x400*x,CHRBankList[x]);\r
1505\r
1506 if(0) switch(Mirroring)\r
1507 {\r
1508 case 0:setmirror(MI_H);break;\r
1509 case 1:setmirror(MI_V);break;\r
1510 case 0x12:\r
1511 case 0x10:setmirror(MI_0);break;\r
1512 case 0x13:\r
1513 case 0x11:setmirror(MI_1);break;\r
1514 }\r
1515 if(MapStateRestore) MapStateRestore(version);\r
1516}\r
1517\r
1518static void iNESPower(void)\r
1519{\r
1520 int x;\r
1521 int type=MapperNo;\r
1522\r
1523 SetReadHandler(0x8000,0xFFFF,CartBR);\r
1524 GameStateRestore=iNESStateRestore;\r
1525 MapClose=0;\r
1526 MapperReset=0;\r
1527 MapStateRestore=0;\r
1528\r
1529 setprg8r(1,0x6000,0);\r
1530\r
1531 SetReadHandler(0x6000,0x7FFF,AWRAM);\r
1532#ifdef ASM_6502\r
1533 // asm code needs pages to be set again..\r
1534 Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;\r
1535#endif\r
1536 SetWriteHandler(0x6000,0x7FFF,BWRAM);\r
1537 FCEU_CheatAddRAM(8,0x6000,WRAM);\r
1538\r
1539 /* This statement represents atrocious code. I need to rewrite\r
1540 all of the iNES mapper code... */\r
1541 IRQCount=IRQLatch=IRQa=0;\r
1542 if(head.ROM_type&2)\r
1543 memset(GameMemBlock+8192,0,GAME_MEM_BLOCK_SIZE-8192);\r
1544 else\r
1545 memset(GameMemBlock,0,GAME_MEM_BLOCK_SIZE);\r
1546\r
1547 NONE_init();\r
1548 ResetExState(0,0);\r
1549\r
1550 if(GameInfo->type == GIT_VSUNI)\r
1551 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
1552\r
1553 AddExState(WRAM, 8192, 0, "WRAM");\r
1554 if(type==19 || type==6 || type==69 || type==85 || type==96)\r
1555 AddExState(MapperExRAM, 32768, 0, "MEXR");\r
1556 if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96))\r
1557 AddExState(CHRRAM, 8192, 0, "CHRR");\r
1558 if(head.ROM_type&8)\r
1559 AddExState(ExtraNTARAM, 2048, 0, "EXNR");\r
1560\r
1561 /* Exclude some mappers whose emulation code handle save state stuff\r
1562 themselves. */\r
1563 if(type && type!=13 && type!=96)\r
1564 {\r
1565 AddExState(mapbyte1, 32, 0, "MPBY");\r
1566 AddExState(&Mirroring, 1, 0, "MIRR");\r
1567 AddExState(&IRQCount, 4, 1, "IRQC");\r
1568 AddExState(&IRQLatch, 4, 1, "IQL1");\r
1569 AddExState(&IRQa, 1, 0, "IRQA");\r
1570 AddExState(PRGBankList, 4, 0, "PBL");\r
1571 for(x=0;x<8;x++)\r
1572 {\r
1573 char tak[8];\r
1574 sprintf(tak,"CBL%d",x);\r
1575 AddExState(&CHRBankList[x], 2, 1,tak);\r
1576 }\r
1577 }\r
1578\r
1579 if(MapInitTab[type]) MapInitTab[type]();\r
1580 else if(type)\r
1581 {\r
1582 FCEU_PrintError("iNES mapper #%d is not supported at all.",type);\r
1583 }\r
1584}\r
1585\r
1586static int NewiNES_Init(int num)\r
1587{\r
1588 BMAPPINGLocal *tmp=bmap;\r
1589\r
1590 CHRRAMSize = -1;\r
1591\r
1592 if(GameInfo->type == GIT_VSUNI)\r
1593 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
1594\r
1595 while(tmp->init)\r
1596 {\r
1597 if(num==tmp->number)\r
1598 {\r
1599 UNIFchrrama=0; // need here for compatibility with UNIF mapper code\r
1600 if(!VROM_size)\r
1601 {\r
1602 if(num==13)\r
1603 {\r
1604 CHRRAMSize=16384;\r
1605 }\r
1606 else\r
1607 {\r
1608 CHRRAMSize=8192;\r
1609 }\r
1610 if((VROM = (uint8 *)FCEU_malloc(CHRRAMSize)) == NULL) return 0;\r
1611 FCEU_MemoryRand(VROM,CHRRAMSize);\r
1612\r
1613 UNIFchrrama=VROM;\r
1614 SetupCartCHRMapping(0,VROM,CHRRAMSize,1);\r
1615 AddExState(VROM,CHRRAMSize, 0, "CHRR");\r
1616 }\r
1617 if(head.ROM_type&8)\r
1618 AddExState(ExtraNTARAM, 2048, 0, "EXNR");\r
1619 tmp->init(&iNESCart);\r
1620 return 1;\r
1621 }\r
1622 tmp++;\r
1623 }\r
1624 return 0;\r
1625}\r
1626\r
1627// vim:ts=4\r