release r2, update credits
[fceu.git] / ines.c
CommitLineData
d97315ac 1/* FCE Ultra - NES/Famicom Emulator\r
386f5371 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
d97315ac 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
d97315ac 35#include "state.h"\r
36#include "file.h"\r
386f5371 37#include "general.h"\r
d97315ac 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
d97315ac 43#include "driver.h"\r
44#include "svga.h"\r
45\r
46extern SFORMAT FCEUVSUNI_STATEINFO[];\r
47\r
386f5371 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
d97315ac 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
386f5371 65//char LoadedRomFName[2048]; //mbg merge 7/17/06 added\r
d97315ac 66\r
386f5371 67static int CHRRAMSize = -1;\r
d97315ac 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
d97315ac 76/* MapperReset() is called when the NES is reset(with the reset button).\r
386f5371 77Mapperxxx_init is called when the NES has been powered on.\r
d97315ac 78*/\r
79\r
386f5371 80\r
d97315ac 81static DECLFR(TrainerRead)\r
82{\r
386f5371 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
d97315ac 110}\r
111\r
c4980f9e 112static void iNESGI(int h, void *param)\r
d97315ac 113{\r
386f5371 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
d97315ac 121 if(MapperReset)\r
386f5371 122 MapperReset();\r
d97315ac 123 if(iNESCart.Reset)\r
386f5371 124 iNESCart.Reset();\r
125 break;\r
126 case GI_POWER:\r
127 iNES_ExecPower();\r
128 \r
d97315ac 129 break;\r
386f5371 130 case GI_CLOSE:\r
d97315ac 131 {\r
386f5371 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
d97315ac 139 }\r
140 break;\r
386f5371 141 case GI_INFOSTRING:\r
c4980f9e 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
386f5371 150 }\r
d97315ac 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
d97315ac 167static void SetInput(void)\r
168{\r
386f5371 169 static struct INPSEL moo[]=\r
d97315ac 170 {\r
386f5371 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
d97315ac 246 };\r
386f5371 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
d97315ac 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
386f5371 275#include "ines-bad.h"\r
d97315ac 276};\r
277\r
278void CheckBad(uint64 md5partial)\r
279{\r
386f5371 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
d97315ac 293\r
294}\r
295\r
296\r
297struct CHINF {\r
298 uint32 crc32;\r
299 int32 mapper;\r
300 int32 mirror;\r
386f5371 301 const char* params;\r
d97315ac 302};\r
303\r
386f5371 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
d97315ac 337static void CheckHInfo(void)\r
338{\r
386f5371 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
d97315ac 342\r
386f5371 343 Lower 64 bits of the MD5 hash.\r
344 */\r
d97315ac 345\r
386f5371 346 static uint64 savie[]=\r
d97315ac 347 {\r
386f5371 348 0x498c10dc463cfe95LL, /* Battle Fleet */\r
349 0x6917ffcaca2d8466LL, /* Famista '90 */\r
d97315ac 350\r
386f5371 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
d97315ac 355\r
386f5371 356 0x2ee3417ba8b69706LL, /* Hydlide 3*/\r
d97315ac 357\r
386f5371 358 0xebbce5a54cf3ecc0LL, /* Justbreed */\r
d97315ac 359\r
386f5371 360 0x6a858da551ba239eLL, /* Kaijuu Monogatari */\r
361 0xa40666740b7d22feLL, /* Mindseeker */\r
d97315ac 362\r
386f5371 363 0x77b811b2760104b9LL, /* Mouryou Senki Madara */\r
d97315ac 364\r
386f5371 365 0x11b69122efe86e8cLL, /* RPG Jinsei Game */\r
d97315ac 366\r
386f5371 367 0xa70b495314f4d075LL, /* Ys 3 */\r
d97315ac 368\r
369\r
386f5371 370 0xc04361e499748382LL, /* AD&D Heroes of the Lance */\r
371 0xb72ee2337ced5792LL, /* AD&D Hillsfar */\r
372 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */\r
d97315ac 373\r
386f5371 374 0x854d7947a3177f57LL, /* Crystalis */\r
d97315ac 375\r
386f5371 376 0xb0bcc02c843c1b79LL, /* DW */\r
377 0x4a1f5336b86851b6LL, /* DW */\r
d97315ac 378\r
386f5371 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
d97315ac 385\r
386f5371 386 0x94b9484862a26cbaLL, /* Legend of Zelda */\r
387 0x04a31647de80fdabLL, /* "" */\r
d97315ac 388\r
386f5371 389 0x9aa1dc16c05e7de5LL, /* Startropics */\r
390 0x1b084107d0878bd0LL, /* Startropics 2*/\r
d97315ac 391\r
386f5371 392 0x836c0ff4f3e06e45LL, /* Zelda 2 */\r
d97315ac 393\r
386f5371 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
d97315ac 397 };\r
398\r
386f5371 399 static struct CHINF moo[]=\r
d97315ac 400 {\r
386f5371 401#include "ines-correct.h"\r
d97315ac 402 };\r
386f5371 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
d97315ac 528}\r
529\r
530typedef struct {\r
531 int mapper;\r
532 void (*init)(CartInfo *);\r
533} NewMI;\r
534\r
386f5371 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
43725da7 558// {6, Mapper6_Init},\r
386f5371 559 {"ANROM", 7, ANROM_Init},\r
43725da7 560 {"", 8, Mapper8_Init}, // Nogaems, it's worthless\r
561// {9, Mapper9_Init},\r
562// {10, Mapper10_Init},\r
386f5371 563 {"Color Dreams", 11, Mapper11_Init},\r
564 {"", 12, Mapper12_Init},\r
565 {"CPROM", 13, CPROM_Init},\r
43725da7 566// {14, Mapper14_Init},\r
386f5371 567 {"100-in1", 15, Mapper15_Init},\r
568 {"Bandai", 16, Mapper16_Init},\r
43725da7 569 {"", 17, Mapper17_Init},\r
570 {"", 18, Mapper18_Init},\r
386f5371 571 {"Namcot 106", 19, Mapper19_Init},\r
43725da7 572// {20, Mapper20_Init},\r
573// {21, Mapper21_Init},\r
574// {22, Mapper22_Init},\r
386f5371 575 {"Konami VRC2 type B", 23, Mapper23_Init},\r
43725da7 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
386f5371 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
43725da7 591// {39, Mapper39_Init},\r
592// {40, Mapper40_Init},\r
593// {41, Mapper41_Init},\r
594// {42, Mapper42_Init},\r
386f5371 595 {"", 43, Mapper43_Init},\r
596 {"", 44, Mapper44_Init},\r
597 {"", 45, Mapper45_Init},\r
43725da7 598// {46, Mapper46_Init},\r
386f5371 599 {"", 47, Mapper47_Init},\r
43725da7 600// {48, Mapper48_Init},\r
386f5371 601 {"", 49, Mapper49_Init},\r
43725da7 602// {50, Mapper50_Init},\r
603// {51, Mapper51_Init},\r
386f5371 604 {"", 52, Mapper52_Init},\r
43725da7 605// {53, Mapper53_Init},\r
606// {54, Mapper54_Init},\r
607// {55, Mapper55_Init},\r
608// {56, Mapper56_Init},\r
386f5371 609 {"", 57, Mapper57_Init},\r
610 {"", 58, BMCGK192_Init},\r
43725da7 611// {59, Mapper59_Init},\r
386f5371 612 {"", 60, BMCD1038_Init},\r
43725da7 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
386f5371 618 {"MHROM", 66, MHROM_Init},\r
43725da7 619// {67, Mapper67_Init},\r
386f5371 620 {"Sunsoft Mapper #4", 68, Mapper68_Init},\r
43725da7 621// {69, Mapper69_Init},\r
386f5371 622 {"", 70, Mapper70_Init},\r
43725da7 623// {71, Mapper71_Init},\r
624// {72, Mapper72_Init},\r
625// {73, Mapper73_Init},\r
386f5371 626 {"", 74, Mapper74_Init},\r
43725da7 627// {75, Mapper75_Init},\r
628// {76, Mapper76_Init},\r
629// {77, Mapper77_Init},\r
386f5371 630 {"Irem 74HC161/32", 78, Mapper78_Init},\r
43725da7 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
386f5371 639 {"", 87, Mapper87_Init},\r
640 {"", 88, Mapper88_Init},\r
43725da7 641 {"", 89, Mapper89_Init},\r
386f5371 642 {"", 90, Mapper90_Init},\r
43725da7 643 {"", 91, Mapper91_Init},\r
644 {"", 92, Mapper92_Init},\r
386f5371 645 {"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init},\r
646 {"", 94, Mapper94_Init},\r
647 {"", 95, Mapper95_Init},\r
43725da7 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
386f5371 653 {"", 101, Mapper101_Init},\r
43725da7 654// {102, Mapper102_Init},\r
386f5371 655 {"", 103, Mapper103_Init},\r
43725da7 656// {104, Mapper104_Init},\r
386f5371 657 {"", 105, Mapper105_Init},\r
658 {"", 106, Mapper106_Init},\r
659 {"", 107, Mapper107_Init},\r
660 {"", 108, Mapper108_Init},\r
43725da7 661// {109, Mapper109_Init},\r
662// {110, Mapper110_Init},\r
663// {111, Mapper111_Init},\r
386f5371 664 {"", 112, Mapper112_Init},\r
665 {"", 113, Mapper113_Init},\r
666 {"", 114, Mapper114_Init},\r
667 {"", 115, Mapper115_Init},\r
43725da7 668 {"UNLSL12", 116, UNLSL12_Init},\r
386f5371 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
43725da7 674// {122, Mapper122_Init},\r
386f5371 675 {"UNLH2288", 123, UNLH2288_Init},\r
43725da7 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
386f5371 684 {"UNL22211", 132, UNL22211_Init},\r
685 {"SA72008", 133, SA72008_Init},\r
686 {"", 134, Mapper134_Init},\r
43725da7 687// {135, Mapper135_Init},\r
386f5371 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
43725da7 703 {"", 151, Mapper151_Init},\r
386f5371 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
43725da7 709 {"", 157, Mapper157_Init},\r
710// {158, Mapper158_Init},\r
711// {159, Mapper159_Init},\r
386f5371 712 {"SA009", 160, SA009_Init},\r
43725da7 713// {161, Mapper161_Init},\r
714 {"", 162, UNLFS304_Init},\r
386f5371 715 {"", 163, Mapper163_Init},\r
716 {"", 164, Mapper164_Init},\r
717 {"", 165, Mapper165_Init},\r
43725da7 718// {166, Mapper166_Init},\r
719// {167, Mapper167_Init},\r
720 {"", 168, Mapper168_Init},\r
721// {169, Mapper169_Init},\r
386f5371 722 {"", 171, Mapper171_Init},\r
723 {"", 172, Mapper172_Init},\r
724 {"", 173, Mapper173_Init},\r
725 {"", 175, Mapper175_Init},\r
43725da7 726// {174, Mapper174_Init},\r
727 {"", 175, Mapper175_Init},\r
728 {"BMCFK23C", 176, BMCFK23C_Init},\r
386f5371 729 {"", 177, Mapper177_Init},\r
730 {"", 178, Mapper178_Init},\r
43725da7 731// {179, Mapper179_Init},\r
386f5371 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
43725da7 742// {190, Mapper190_Init},\r
386f5371 743 {"", 191, Mapper191_Init},\r
744 {"", 192, Mapper192_Init},\r
43725da7 745 {"", 193, Mapper193_Init},\r
386f5371 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
43725da7 753// {201, Mapper201_Init},\r
754// {202, Mapper202_Init},\r
755// {203, Mapper203_Init},\r
756// {204, Mapper204_Init},\r
386f5371 757 {"", 205, Mapper205_Init},\r
758 {"DEIROM", 206, DEIROM_Init},\r
43725da7 759// {207, Mapper207_Init},\r
386f5371 760 {"", 208, Mapper208_Init},\r
761 {"", 209, Mapper209_Init},\r
762 {"", 210, Mapper210_Init},\r
763 {"", 211, Mapper211_Init},\r
43725da7 764// {212, Mapper212_Init},\r
765// {213, Mapper213_Init},\r
766// {214, Mapper214_Init},\r
386f5371 767 {"", 215, UNL8237_Init},\r
768 {"", 216, Mapper216_Init},\r
769// {"", 217, Mapper217_Init},\r
43725da7 770// {218, Mapper218_Init},\r
386f5371 771 {"UNLA9746", 219, UNLA9746_Init},\r
43725da7 772 {"", 220, UNLKS7057_Init}, // DEBUG mapper\r
386f5371 773 {"UNLN625092", 221, UNLN625092_Init},\r
774 {"", 222, Mapper222_Init},\r
43725da7 775// {223, Mapper223_Init},\r
776// {224, Mapper224_Init},\r
777 {"", 225, Mapper225_Init},\r
386f5371 778 {"", 226, Mapper226_Init},\r
43725da7 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
386f5371 787 {"", 235, Mapper235_Init},\r
43725da7 788// {236, Mapper236_Init},\r
789// {237, Mapper237_Init},\r
386f5371 790 {"UNL6035052", 238, UNL6035052_Init},\r
43725da7 791// {239, Mapper239_Init},\r
386f5371 792 {"", 240, Mapper240_Init},\r
43725da7 793// {241, Mapper241_Init},\r
794// {242, Mapper242_Init},\r
386f5371 795 {"S74LS374NA", 243, S74LS374NA_Init},\r
43725da7 796// {244, Mapper244_Init},\r
386f5371 797 {"", 245, Mapper245_Init},\r
43725da7 798// {246, Mapper246_Init},\r
799// {247, Mapper247_Init},\r
800// {248, Mapper248_Init},\r
386f5371 801 {"", 249, Mapper249_Init},\r
802 {"", 250, Mapper250_Init},\r
43725da7 803// {251, Mapper251_Init},\r
804// {252, Mapper252_Init},\r
386f5371 805 {"", 253, Mapper253_Init},\r
806 {"", 254, Mapper254_Init},\r
43725da7 807// {255, Mapper255_Init},\r
386f5371 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
d97315ac 833{\r
386f5371 834 struct md5_context md5;\r
d97315ac 835\r
836 if(FCEU_fread(&head,1,16,fp)!=16)\r
386f5371 837 return 0;\r
d97315ac 838\r
386f5371 839 if(memcmp(&head,"NES\x1a",4))\r
840 return 0;\r
841\r
842 cleanup(&head);\r
d97315ac 843\r
844 memset(&iNESCart,0,sizeof(iNESCart));\r
845\r
386f5371 846 MapperNo = (head.ROM_type>>4);\r
847 MapperNo|=(head.ROM_type2&0xF0);\r
848 Mirroring = (head.ROM_type&1);\r
d97315ac 849\r
d97315ac 850\r
386f5371 851 // int ROM_size=0;\r
852 if(!head.ROM_size)\r
d97315ac 853 {\r
386f5371 854 // FCEU_PrintError("No PRG ROM!");\r
855 // return(0);\r
856 ROM_size=256;\r
857 //head.ROM_size++;\r
d97315ac 858 }\r
386f5371 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
d97315ac 864\r
386f5371 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
d97315ac 880\r
386f5371 881 if(VROM_size)\r
882 VROM_size=uppow2(VROM_size);\r
d97315ac 883\r
d97315ac 884\r
885 if(head.ROM_type&8) Mirroring=2;\r
886\r
386f5371 887 if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;\r
d97315ac 888\r
386f5371 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
d97315ac 901 {\r
386f5371 902 trainerpoo=(uint8 *)FCEU_gmalloc(512);\r
903 FCEU_fread(trainerpoo,512,1,fp);\r
d97315ac 904 }\r
905\r
906 ResetCartMapping();\r
907 ResetExState(0,0);\r
908\r
909 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);\r
386f5371 910 // SetupCartPRGMapping(1,WRAM,8192,1); // ?\r
d97315ac 911\r
386f5371 912 FCEU_fread(ROM,0x4000,(round) ? ROM_size : head.ROM_size,fp);\r
d97315ac 913\r
914 if(VROM_size)\r
386f5371 915 FCEU_fread(VROM,0x2000,head.VROM_size,fp);\r
d97315ac 916\r
386f5371 917 md5_starts(&md5);\r
918 md5_update(&md5,ROM,ROM_size<<14);\r
d97315ac 919\r
920 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);\r
921\r
922 if(VROM_size)\r
923 {\r
386f5371 924 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);\r
925 md5_update(&md5,VROM,VROM_size<<13);\r
d97315ac 926 }\r
927 md5_finish(&md5,iNESCart.MD5);\r
386f5371 928 memcpy(&GameInfo->MD5,&iNESCart.MD5,sizeof(iNESCart.MD5));\r
d97315ac 929\r
930 iNESCart.CRC32=iNESGameCRC32;\r
931\r
386f5371 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
d97315ac 935\r
386f5371 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
d97315ac 961\r
962 SetInput();\r
963 CheckHInfo();\r
964 {\r
386f5371 965 int x;\r
966 uint64 partialmd5=0;\r
d97315ac 967\r
386f5371 968 for(x=0;x<8;x++)\r
969 {\r
970 partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);\r
971 }\r
d97315ac 972\r
386f5371 973 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);\r
d97315ac 974 }\r
975 /* Must remain here because above functions might change value of\r
386f5371 976 VROM_size and free(VROM).\r
d97315ac 977 */\r
978 if(VROM_size)\r
386f5371 979 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);\r
d97315ac 980\r
386f5371 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
d97315ac 985 else\r
386f5371 986 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);\r
d97315ac 987\r
988 iNESCart.battery=(head.ROM_type&2)?1:0;\r
989 iNESCart.mirror=Mirroring;\r
990\r
991 //if(MapperNo != 18) {\r
386f5371 992 // if(ROM) free(ROM);\r
993 // if(VROM) free(VROM);\r
994 // ROM=VROM=0;\r
995 // return(0);\r
d97315ac 996 // }\r
997\r
d97315ac 998\r
386f5371 999 GameInfo->mappernum = MapperNo;\r
1000 MapperInit();\r
d97315ac 1001 FCEU_LoadGameSave(&iNESCart);\r
1002\r
386f5371 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
d97315ac 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
386f5371 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
d97315ac 1091\r
1092 return 1;\r
1093}\r
1094\r
386f5371 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
d97315ac 1108{\r
386f5371 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
d97315ac 1113}\r
1114\r
386f5371 1115void VRAM_BANK4(uint32 A, uint32 V)\r
d97315ac 1116{\r
386f5371 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
d97315ac 1124}\r
386f5371 1125void VROM_BANK1(uint32 A,uint32 V)\r
d97315ac 1126{\r
386f5371 1127 setchr1(A,V);\r
1128 CHRBankList[(A)>>10]=V;\r
d97315ac 1129}\r
1130\r
386f5371 1131void VROM_BANK2(uint32 A,uint32 V)\r
d97315ac 1132{\r
386f5371 1133 setchr2(A,V);\r
1134 CHRBankList[(A)>>10]=(V<<1);\r
1135 CHRBankList[((A)>>10)+1]=(V<<1)+1;\r
d97315ac 1136}\r
1137\r
386f5371 1138void VROM_BANK4(uint32 A, uint32 V)\r
d97315ac 1139{\r
386f5371 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
d97315ac 1145}\r
1146\r
386f5371 1147void VROM_BANK8(uint32 V)\r
d97315ac 1148{\r
386f5371 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
d97315ac 1158}\r
1159\r
386f5371 1160void ROM_BANK8(uint32 A, uint32 V)\r
d97315ac 1161{\r
386f5371 1162 setprg8(A,V);\r
1163 if(A>=0x8000)\r
1164 PRGBankList[((A-0x8000)>>13)]=V;\r
d97315ac 1165}\r
1166\r
386f5371 1167void ROM_BANK16(uint32 A, uint32 V)\r
d97315ac 1168{\r
386f5371 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
d97315ac 1175}\r
1176\r
386f5371 1177void ROM_BANK32(uint32 V)\r
d97315ac 1178{\r
386f5371 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
d97315ac 1184}\r
1185\r
386f5371 1186void onemir(uint8 V)\r
d97315ac 1187{\r
1188 if(Mirroring==2) return;\r
386f5371 1189 if(V>1)\r
1190 V=1;\r
d97315ac 1191 Mirroring=0x10|V;\r
1192 setmirror(MI_0+V);\r
1193}\r
1194\r
386f5371 1195void MIRROR_SET2(uint8 V)\r
d97315ac 1196{\r
1197 if(Mirroring==2) return;\r
1198 Mirroring=V;\r
1199 setmirror(V);\r
1200}\r
1201\r
386f5371 1202void MIRROR_SET(uint8 V)\r
d97315ac 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
386f5371 1212 ROM_BANK16(0x8000,0);\r
1213 ROM_BANK16(0xC000,~0);\r
d97315ac 1214\r
386f5371 1215 if(VROM_size)\r
1216 VROM_BANK8(0);\r
1217 else\r
1218 setvram8(CHRRAM);\r
d97315ac 1219}\r
43725da7 1220\r
d97315ac 1221void (*MapInitTab[256])(void)=\r
1222{\r
43725da7 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
386f5371 1238 0, //Mapper15_init,\r
1239 0, //Mapper16_init,\r
43725da7 1240 0, //Mapper17_init,\r
1241 0, //Mapper18_init,\r
1242 0,\r
1243 0,\r
1244 Mapper21_init,\r
1245 Mapper22_init,\r
386f5371 1246 0, //Mapper23_init,\r
43725da7 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
386f5371 1376 0, //Mapper153_init,\r
43725da7 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
d97315ac 1479};\r
1480\r
1481static DECLFW(BWRAM)\r
1482{\r
386f5371 1483 WRAM[A-0x6000]=V;\r
d97315ac 1484}\r
1485\r
1486static DECLFR(AWRAM)\r
1487{\r
386f5371 1488 return WRAM[A-0x6000];\r
d97315ac 1489}\r
1490\r
d97315ac 1491\r
1492void (*MapStateRestore)(int version);\r
1493void iNESStateRestore(int version)\r
1494{\r
386f5371 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
d97315ac 1516}\r
1517\r
1518static void iNESPower(void)\r
1519{\r
386f5371 1520 int x;\r
d97315ac 1521 int type=MapperNo;\r
1522\r
386f5371 1523 SetReadHandler(0x8000,0xFFFF,CartBR);\r
1524 GameStateRestore=iNESStateRestore;\r
1525 MapClose=0;\r
d97315ac 1526 MapperReset=0;\r
386f5371 1527 MapStateRestore=0;\r
d97315ac 1528\r
386f5371 1529 setprg8r(1,0x6000,0);\r
d97315ac 1530\r
386f5371 1531 SetReadHandler(0x6000,0x7FFF,AWRAM);\r
e7f52878 1532#ifdef ASM_6502\r
386f5371 1533 // asm code needs pages to be set again..\r
1534 Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;\r
e7f52878 1535#endif\r
386f5371 1536 SetWriteHandler(0x6000,0x7FFF,BWRAM);\r
1537 FCEU_CheatAddRAM(8,0x6000,WRAM);\r
d97315ac 1538\r
1539 /* This statement represents atrocious code. I need to rewrite\r
386f5371 1540 all of the iNES mapper code... */\r
d97315ac 1541 IRQCount=IRQLatch=IRQa=0;\r
386f5371 1542 if(head.ROM_type&2)\r
1543 memset(GameMemBlock+8192,0,GAME_MEM_BLOCK_SIZE-8192);\r
d97315ac 1544 else\r
386f5371 1545 memset(GameMemBlock,0,GAME_MEM_BLOCK_SIZE);\r
d97315ac 1546\r
386f5371 1547 NONE_init();\r
1548 ResetExState(0,0);\r
d97315ac 1549\r
386f5371 1550 if(GameInfo->type == GIT_VSUNI)\r
1551 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
d97315ac 1552\r
386f5371 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
d97315ac 1560\r
1561 /* Exclude some mappers whose emulation code handle save state stuff\r
386f5371 1562 themselves. */\r
d97315ac 1563 if(type && type!=13 && type!=96)\r
1564 {\r
386f5371 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
d97315ac 1577 }\r
1578\r
386f5371 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
d97315ac 1584}\r
1585\r
386f5371 1586static int NewiNES_Init(int num)\r
1587{\r
1588 BMAPPINGLocal *tmp=bmap;\r
d97315ac 1589\r
386f5371 1590 CHRRAMSize = -1;\r
d97315ac 1591\r
386f5371 1592 if(GameInfo->type == GIT_VSUNI)\r
1593 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
e2d0dd92 1594\r
386f5371 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
d97315ac 1625}\r
6587f346 1626\r
386f5371 1627// vim:ts=4\r