merge mapper code from FCEUX
[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
558 {"ANROM", 7, ANROM_Init},\r
559 {"Color Dreams", 11, Mapper11_Init},\r
560 {"", 12, Mapper12_Init},\r
561 {"CPROM", 13, CPROM_Init},\r
562 {"100-in1", 15, Mapper15_Init},\r
563 {"Bandai", 16, Mapper16_Init},\r
564 {"Namcot 106", 19, Mapper19_Init},\r
565 {"Konami VRC2 type B", 23, Mapper23_Init},\r
566 {"Wario Land 2", 35, UNLSC127_Init}, // Wario Land 2\r
567 {"TXC Policeman", 36, Mapper36_Init}, // TXC Policeman\r
568 {"", 37, Mapper37_Init},\r
569 {"Bit Corp. Crime Busters", 38, Mapper38_Init}, // Bit Corp. Crime Busters\r
570 {"", 43, Mapper43_Init},\r
571 {"", 44, Mapper44_Init},\r
572 {"", 45, Mapper45_Init},\r
573 {"", 47, Mapper47_Init},\r
574 {"", 49, Mapper49_Init},\r
575 {"", 52, Mapper52_Init},\r
576 {"", 57, Mapper57_Init},\r
577 {"", 58, BMCGK192_Init},\r
578 {"", 60, BMCD1038_Init},\r
579 {"MHROM", 66, MHROM_Init},\r
580 {"Sunsoft Mapper #4", 68, Mapper68_Init},\r
581 {"", 70, Mapper70_Init},\r
582 {"", 74, Mapper74_Init},\r
583 {"Irem 74HC161/32", 78, Mapper78_Init},\r
584 {"", 87, Mapper87_Init},\r
585 {"", 88, Mapper88_Init},\r
586 {"", 90, Mapper90_Init},\r
587 {"Sunsoft UNROM", 93, SUNSOFT_UNROM_Init},\r
588 {"", 94, Mapper94_Init},\r
589 {"", 95, Mapper95_Init},\r
590 {"", 101, Mapper101_Init},\r
591 {"", 103, Mapper103_Init},\r
592 {"", 105, Mapper105_Init},\r
593 {"", 106, Mapper106_Init},\r
594 {"", 107, Mapper107_Init},\r
595 {"", 108, Mapper108_Init},\r
596 {"", 112, Mapper112_Init},\r
597 {"", 113, Mapper113_Init},\r
598 {"", 114, Mapper114_Init},\r
599 {"", 115, Mapper115_Init},\r
600 {"", 116, Mapper116_Init},\r
601// {116, UNLSL1632_Init},\r
602 {"", 117, Mapper117_Init},\r
603 {"TSKROM", 118, TKSROM_Init},\r
604 {"", 119, Mapper119_Init},\r
605 {"", 120, Mapper120_Init},\r
606 {"", 121, Mapper121_Init},\r
607 {"UNLH2288", 123, UNLH2288_Init},\r
608 {"UNL22211", 132, UNL22211_Init},\r
609 {"SA72008", 133, SA72008_Init},\r
610 {"", 134, Mapper134_Init},\r
611 {"TCU02", 136, TCU02_Init},\r
612 {"S8259D", 137, S8259D_Init},\r
613 {"S8259B", 138, S8259B_Init},\r
614 {"S8259C", 139, S8259C_Init},\r
615 {"", 140, Mapper140_Init},\r
616 {"S8259A", 141, S8259A_Init},\r
617 {"UNLKS7032", 142, UNLKS7032_Init},\r
618 {"TCA01", 143, TCA01_Init},\r
619 {"", 144, Mapper144_Init},\r
620 {"SA72007", 145, SA72007_Init},\r
621 {"SA0161M", 146, SA0161M_Init},\r
622 {"TCU01", 147, TCU01_Init},\r
623 {"SA0037", 148, SA0037_Init},\r
624 {"SA0036", 149, SA0036_Init},\r
625 {"S74LS374N", 150, S74LS374N_Init},\r
626 {"", 152, Mapper152_Init},\r
627 {"", 153, Mapper153_Init},\r
628 {"", 154, Mapper154_Init},\r
629 {"", 155, Mapper155_Init},\r
630 {"", 156, Mapper156_Init},\r
631 {"", 159, Mapper159_Init},\r
632 {"SA009", 160, SA009_Init},\r
633 {"", 163, Mapper163_Init},\r
634 {"", 164, Mapper164_Init},\r
635 {"", 165, Mapper165_Init},\r
636// {169, Mapper169_Init},\r
637 {"", 171, Mapper171_Init},\r
638 {"", 172, Mapper172_Init},\r
639 {"", 173, Mapper173_Init},\r
640 {"", 175, Mapper175_Init},\r
641 {"BMCFK23C", 176, BMCFK23C_Init}, //zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance 水浒神兽. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it.\r
642 //{"BMCFK23C", 176, Mapper176_Init}, \r
643 {"", 177, Mapper177_Init},\r
644 {"", 178, Mapper178_Init},\r
645 {"", 180, Mapper180_Init},\r
646 {"", 181, Mapper181_Init},\r
647// {"", 182, Mapper182_Init}, // identical to 114\r
648 {"", 183, Mapper183_Init},\r
649 {"", 184, Mapper184_Init},\r
650 {"", 185, Mapper185_Init},\r
651 {"", 186, Mapper186_Init},\r
652 {"", 187, Mapper187_Init},\r
653 {"", 188, Mapper188_Init},\r
654 {"", 189, Mapper189_Init},\r
655 {"", 191, Mapper191_Init},\r
656 {"", 192, Mapper192_Init},\r
657 {"", 194, Mapper194_Init},\r
658 {"", 195, Mapper195_Init},\r
659 {"", 196, Mapper196_Init},\r
660 {"", 197, Mapper197_Init},\r
661 {"", 198, Mapper198_Init},\r
662 {"", 199, Mapper199_Init},\r
663 {"", 200, Mapper200_Init},\r
664 {"", 205, Mapper205_Init},\r
665 {"DEIROM", 206, DEIROM_Init},\r
666 {"", 208, Mapper208_Init},\r
667 {"", 209, Mapper209_Init},\r
668 {"", 210, Mapper210_Init},\r
669 {"", 211, Mapper211_Init},\r
670 {"", 215, UNL8237_Init},\r
671 {"", 216, Mapper216_Init},\r
672// {"", 217, Mapper217_Init},\r
673 {"UNLA9746", 219, UNLA9746_Init},\r
674 {"OneBus", 220, UNLOneBus_Init},\r
675\r
676// {220, BMCFK23C_Init},\r
677// {220, UNL3DBlock_Init},\r
678// {220, UNLTF1201_Init},\r
679// {220, TCU02_Init},\r
680// {220, UNLCN22M_Init},\r
681// {220, BMCT2271_Init},\r
682// {220, UNLDANCE_Init},\r
683\r
684 {"UNLN625092", 221, UNLN625092_Init},\r
685 {"", 222, Mapper222_Init},\r
686 {"", 226, Mapper226_Init},\r
687 {"", 235, Mapper235_Init},\r
688 {"UNL6035052", 238, UNL6035052_Init},\r
689 {"", 240, Mapper240_Init},\r
690 {"S74LS374NA", 243, S74LS374NA_Init},\r
691 {"", 245, Mapper245_Init},\r
692 {"", 249, Mapper249_Init},\r
693 {"", 250, Mapper250_Init},\r
694 {"", 253, Mapper253_Init},\r
695 {"", 254, Mapper254_Init},\r
696 {"", 0, 0}\r
697};\r
698\r
699void cleanup(struct iNES_HEADER *this)\r
700{\r
701 if(!memcmp((char *)(this)+0x7,"DiskDude",8))\r
702 {\r
703 memset((char *)(this)+0x7,0,0x9);\r
704 }\r
705\r
706 if(!memcmp((char *)(this)+0x7,"demiforce",9))\r
707 {\r
708 memset((char *)(this)+0x7,0,0x9);\r
709 }\r
710\r
711 if(!memcmp((char *)(this)+0xA,"Ni03",4))\r
712 {\r
713 if(!memcmp((char *)(this)+0x7,"Dis",3))\r
714 memset((char *)(this)+0x7,0,0x9);\r
715 else\r
716 memset((char *)(this)+0xA,0,0x6);\r
717 }\r
718}\r
719\r
720int iNESLoad(const char *name, int fp, int OverwriteVidMode)\r
d97315ac 721{\r
386f5371 722 struct md5_context md5;\r
d97315ac 723\r
724 if(FCEU_fread(&head,1,16,fp)!=16)\r
386f5371 725 return 0;\r
d97315ac 726\r
386f5371 727 if(memcmp(&head,"NES\x1a",4))\r
728 return 0;\r
729\r
730 cleanup(&head);\r
d97315ac 731\r
732 memset(&iNESCart,0,sizeof(iNESCart));\r
733\r
386f5371 734 MapperNo = (head.ROM_type>>4);\r
735 MapperNo|=(head.ROM_type2&0xF0);\r
736 Mirroring = (head.ROM_type&1);\r
d97315ac 737\r
d97315ac 738\r
386f5371 739 // int ROM_size=0;\r
740 if(!head.ROM_size)\r
d97315ac 741 {\r
386f5371 742 // FCEU_PrintError("No PRG ROM!");\r
743 // return(0);\r
744 ROM_size=256;\r
745 //head.ROM_size++;\r
d97315ac 746 }\r
386f5371 747 else\r
748 ROM_size=uppow2(head.ROM_size);\r
749\r
750 // ROM_size = head.ROM_size;\r
751 VROM_size = head.VROM_size;\r
d97315ac 752\r
386f5371 753 int round = 1;\r
754 int i;\r
755 for (i = 0; i != sizeof(not_power2)/sizeof(not_power2[0]); ++i)\r
756 {\r
757 //for games not to the power of 2, so we just read enough\r
758 //prg rom from it, but we have to keep ROM_size to the power of 2\r
759 //since PRGCartMapping wants ROM_size to be to the power of 2\r
760 //so instead if not to power of 2, we just use head.ROM_size when\r
761 //we use FCEU_read\r
762 if (not_power2[i] == MapperNo)\r
763 {\r
764 round = 0;\r
765 break;\r
766 }\r
767 }\r
d97315ac 768\r
386f5371 769 if(VROM_size)\r
770 VROM_size=uppow2(VROM_size);\r
d97315ac 771\r
d97315ac 772\r
773 if(head.ROM_type&8) Mirroring=2;\r
774\r
386f5371 775 if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;\r
d97315ac 776\r
386f5371 777 if(VROM_size)\r
778 {\r
779 if((VROM = (uint8 *)FCEU_malloc(VROM_size<<13)) == NULL)\r
780 {\r
781 free(ROM);\r
782 ROM = NULL;\r
783 return 0;\r
784 }\r
785 }\r
786 memset(ROM,0xFF,ROM_size<<14);\r
787 if(VROM_size) memset(VROM,0xFF,VROM_size<<13);\r
788 if(head.ROM_type&4) /* Trainer */\r
d97315ac 789 {\r
386f5371 790 trainerpoo=(uint8 *)FCEU_gmalloc(512);\r
791 FCEU_fread(trainerpoo,512,1,fp);\r
d97315ac 792 }\r
793\r
794 ResetCartMapping();\r
795 ResetExState(0,0);\r
796\r
797 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);\r
386f5371 798 // SetupCartPRGMapping(1,WRAM,8192,1); // ?\r
d97315ac 799\r
386f5371 800 FCEU_fread(ROM,0x4000,(round) ? ROM_size : head.ROM_size,fp);\r
d97315ac 801\r
802 if(VROM_size)\r
386f5371 803 FCEU_fread(VROM,0x2000,head.VROM_size,fp);\r
d97315ac 804\r
386f5371 805 md5_starts(&md5);\r
806 md5_update(&md5,ROM,ROM_size<<14);\r
d97315ac 807\r
808 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);\r
809\r
810 if(VROM_size)\r
811 {\r
386f5371 812 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);\r
813 md5_update(&md5,VROM,VROM_size<<13);\r
d97315ac 814 }\r
815 md5_finish(&md5,iNESCart.MD5);\r
386f5371 816 memcpy(&GameInfo->MD5,&iNESCart.MD5,sizeof(iNESCart.MD5));\r
d97315ac 817\r
818 iNESCart.CRC32=iNESGameCRC32;\r
819\r
386f5371 820 FCEU_printf(" PRG ROM: %3d x 16KiB\n CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08lx\n",\r
821 (round) ? ROM_size : head.ROM_size, head.VROM_size,\r
822 (unsigned long)iNESGameCRC32);\r
d97315ac 823\r
386f5371 824 {\r
825 int x;\r
826 FCEU_printf(" ROM MD5: 0x");\r
827 for(x=0;x<16;x++)\r
828 FCEU_printf("%02x",iNESCart.MD5[x]);\r
829 FCEU_printf("\n");\r
830 }\r
831\r
832 char* mappername = "Not Listed";\r
833 int mappertest;\r
834\r
835 for(mappertest=0;mappertest< (sizeof bmap / sizeof bmap[0]) - 1;mappertest++)\r
836 {\r
837 if (bmap[mappertest].number == MapperNo) {\r
838 mappername = bmap[mappertest].name;\r
839 break;\r
840 }\r
841 }\r
842\r
843 FCEU_printf(" Mapper #: %d\n Mapper name: %s\n Mirroring: %s\n",\r
844 MapperNo, mappername, Mirroring==2?"None (Four-screen)":Mirroring?"Vertical":"Horizontal");\r
845\r
846 FCEU_printf(" Battery-backed: %s\n", (head.ROM_type&2)?"Yes":"No");\r
847 FCEU_printf(" Trained: %s\n", (head.ROM_type&4)?"Yes":"No");\r
848 // (head.ROM_type&8) = Mirroring: None(Four-screen)\r
d97315ac 849\r
850 SetInput();\r
851 CheckHInfo();\r
852 {\r
386f5371 853 int x;\r
854 uint64 partialmd5=0;\r
d97315ac 855\r
386f5371 856 for(x=0;x<8;x++)\r
857 {\r
858 partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);\r
859 }\r
d97315ac 860\r
386f5371 861 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);\r
d97315ac 862 }\r
863 /* Must remain here because above functions might change value of\r
386f5371 864 VROM_size and free(VROM).\r
d97315ac 865 */\r
866 if(VROM_size)\r
386f5371 867 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);\r
d97315ac 868\r
386f5371 869 if(Mirroring==2)\r
870 SetupCartMirroring(4,1,ExtraNTARAM);\r
871 else if(Mirroring>=0x10)\r
872 SetupCartMirroring(2+(Mirroring&1),1,0);\r
d97315ac 873 else\r
386f5371 874 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);\r
d97315ac 875\r
876 iNESCart.battery=(head.ROM_type&2)?1:0;\r
877 iNESCart.mirror=Mirroring;\r
878\r
879 //if(MapperNo != 18) {\r
386f5371 880 // if(ROM) free(ROM);\r
881 // if(VROM) free(VROM);\r
882 // ROM=VROM=0;\r
883 // return(0);\r
d97315ac 884 // }\r
885\r
d97315ac 886\r
386f5371 887 GameInfo->mappernum = MapperNo;\r
888 MapperInit();\r
d97315ac 889 FCEU_LoadGameSave(&iNESCart);\r
890\r
386f5371 891 //strcpy(LoadedRomFName,name); //bbit edited: line added\r
892\r
893 // Extract Filename only. Should account for Windows/Unix this way.\r
894 if (strrchr(name, '/')) {\r
895 name = strrchr(name, '/') + 1;\r
896 } else if(strrchr(name, '\\')) {\r
897 name = strrchr(name, '\\') + 1;\r
898 }\r
899\r
d97315ac 900 GameInterface=iNESGI;\r
901 FCEU_printf("\n");\r
902\r
903 // since apparently the iNES format doesn't store this information,\r
904 // guess if the settings should be PAL or NTSC from the ROM name\r
905 // TODO: MD5 check against a list of all known PAL games instead?\r
386f5371 906 if(OverwriteVidMode)\r
907 {\r
908 if(strstr(name,"(E)") || strstr(name,"(e)")\r
909 || strstr(name,"(F)") || strstr(name,"(f)")\r
910 || strstr(name,"(G)") || strstr(name,"(g)")\r
911 || strstr(name,"(I)") || strstr(name,"(i)"))\r
912 FCEUI_SetVidSystem(1);\r
913 else\r
914 FCEUI_SetVidSystem(0);\r
915 }\r
916 return 1;\r
917}\r
918\r
919\r
920//bbit edited: the whole function below was added\r
921int iNesSave(){\r
922 FILE *fp;\r
923 char name[2048];\r
924\r
925 if(GameInfo->type != GIT_CART)return 0;\r
926 if(GameInterface!=iNESGI)return 0;\r
927\r
928 //strcpy(name,LoadedRomFName);\r
929 if (strcmp(name+strlen(name)-4,".nes") != 0) { //para edit\r
930 strcat(name,".nes");\r
931 }\r
932\r
933 fp = fopen(name,"wb");\r
934\r
935 if(fwrite(&head,1,16,fp)!=16)\r
936 {\r
937 fclose(fp);\r
938 return 0;\r
939 }\r
940\r
941 if(head.ROM_type&4) /* Trainer */\r
942 {\r
943 fwrite(trainerpoo,512,1,fp);\r
944 }\r
945\r
946 fwrite(ROM,0x4000,ROM_size,fp);\r
947\r
948 if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);\r
949 fclose(fp);\r
950\r
951 return 1;\r
952}\r
953\r
954int iNesSaveAs(char* name)\r
955{\r
956 //adelikat: TODO: iNesSave() and this have pretty much the same code, outsource the common code to a single function\r
957 FILE *fp;\r
958\r
959 if(GameInfo->type != GIT_CART)return 0;\r
960 if(GameInterface != iNESGI)return 0;\r
961\r
962 fp = fopen(name,"wb");\r
963\r
964 if(fwrite(&head,1,16,fp)!=16)\r
965 {\r
966 fclose(fp);\r
967 return 0;\r
968 }\r
969\r
970 if(head.ROM_type&4) /* Trainer */\r
971 {\r
972 fwrite(trainerpoo,512,1,fp);\r
973 }\r
974\r
975 fwrite(ROM,0x4000,ROM_size,fp);\r
976\r
977 if(head.VROM_size)fwrite(VROM,0x2000,head.VROM_size,fp);\r
978 fclose(fp);\r
d97315ac 979\r
980 return 1;\r
981}\r
982\r
386f5371 983//para edit: added function below\r
984#if 0\r
985char *iNesShortFName() {\r
986 char *ret;\r
987\r
988 if (!(ret = strrchr(LoadedRomFName,'\\'))) {\r
989 if (!(ret = strrchr(LoadedRomFName,'/'))) return 0;\r
990 }\r
991 return ret+1;\r
992}\r
993#endif\r
994\r
995void VRAM_BANK1(uint32 A, uint8 V)\r
d97315ac 996{\r
386f5371 997 V&=7;\r
998 PPUCHRRAM|=(1<<(A>>10));\r
999 CHRBankList[(A)>>10]=V;\r
1000 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);\r
d97315ac 1001}\r
1002\r
386f5371 1003void VRAM_BANK4(uint32 A, uint32 V)\r
d97315ac 1004{\r
386f5371 1005 V&=1;\r
1006 PPUCHRRAM|=(0xF<<(A>>10));\r
1007 CHRBankList[(A)>>10]=(V<<2);\r
1008 CHRBankList[((A)>>10)+1]=(V<<2)+1;\r
1009 CHRBankList[((A)>>10)+2]=(V<<2)+2;\r
1010 CHRBankList[((A)>>10)+3]=(V<<2)+3;\r
1011 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);\r
d97315ac 1012}\r
386f5371 1013void VROM_BANK1(uint32 A,uint32 V)\r
d97315ac 1014{\r
386f5371 1015 setchr1(A,V);\r
1016 CHRBankList[(A)>>10]=V;\r
d97315ac 1017}\r
1018\r
386f5371 1019void VROM_BANK2(uint32 A,uint32 V)\r
d97315ac 1020{\r
386f5371 1021 setchr2(A,V);\r
1022 CHRBankList[(A)>>10]=(V<<1);\r
1023 CHRBankList[((A)>>10)+1]=(V<<1)+1;\r
d97315ac 1024}\r
1025\r
386f5371 1026void VROM_BANK4(uint32 A, uint32 V)\r
d97315ac 1027{\r
386f5371 1028 setchr4(A,V);\r
1029 CHRBankList[(A)>>10]=(V<<2);\r
1030 CHRBankList[((A)>>10)+1]=(V<<2)+1;\r
1031 CHRBankList[((A)>>10)+2]=(V<<2)+2;\r
1032 CHRBankList[((A)>>10)+3]=(V<<2)+3;\r
d97315ac 1033}\r
1034\r
386f5371 1035void VROM_BANK8(uint32 V)\r
d97315ac 1036{\r
386f5371 1037 setchr8(V);\r
1038 CHRBankList[0]=(V<<3);\r
1039 CHRBankList[1]=(V<<3)+1;\r
1040 CHRBankList[2]=(V<<3)+2;\r
1041 CHRBankList[3]=(V<<3)+3;\r
1042 CHRBankList[4]=(V<<3)+4;\r
1043 CHRBankList[5]=(V<<3)+5;\r
1044 CHRBankList[6]=(V<<3)+6;\r
1045 CHRBankList[7]=(V<<3)+7;\r
d97315ac 1046}\r
1047\r
386f5371 1048void ROM_BANK8(uint32 A, uint32 V)\r
d97315ac 1049{\r
386f5371 1050 setprg8(A,V);\r
1051 if(A>=0x8000)\r
1052 PRGBankList[((A-0x8000)>>13)]=V;\r
d97315ac 1053}\r
1054\r
386f5371 1055void ROM_BANK16(uint32 A, uint32 V)\r
d97315ac 1056{\r
386f5371 1057 setprg16(A,V);\r
1058 if(A>=0x8000)\r
1059 {\r
1060 PRGBankList[((A-0x8000)>>13)]=V<<1;\r
1061 PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1;\r
1062 }\r
d97315ac 1063}\r
1064\r
386f5371 1065void ROM_BANK32(uint32 V)\r
d97315ac 1066{\r
386f5371 1067 setprg32(0x8000,V);\r
1068 PRGBankList[0]=V<<2;\r
1069 PRGBankList[1]=(V<<2)+1;\r
1070 PRGBankList[2]=(V<<2)+2;\r
1071 PRGBankList[3]=(V<<2)+3;\r
d97315ac 1072}\r
1073\r
386f5371 1074void onemir(uint8 V)\r
d97315ac 1075{\r
1076 if(Mirroring==2) return;\r
386f5371 1077 if(V>1)\r
1078 V=1;\r
d97315ac 1079 Mirroring=0x10|V;\r
1080 setmirror(MI_0+V);\r
1081}\r
1082\r
386f5371 1083void MIRROR_SET2(uint8 V)\r
d97315ac 1084{\r
1085 if(Mirroring==2) return;\r
1086 Mirroring=V;\r
1087 setmirror(V);\r
1088}\r
1089\r
386f5371 1090void MIRROR_SET(uint8 V)\r
d97315ac 1091{\r
1092 if(Mirroring==2) return;\r
1093 V^=1;\r
1094 Mirroring=V;\r
1095 setmirror(V);\r
1096}\r
1097\r
1098static void NONE_init(void)\r
1099{\r
386f5371 1100 ROM_BANK16(0x8000,0);\r
1101 ROM_BANK16(0xC000,~0);\r
d97315ac 1102\r
386f5371 1103 if(VROM_size)\r
1104 VROM_BANK8(0);\r
1105 else\r
1106 setvram8(CHRRAM);\r
d97315ac 1107}\r
d97315ac 1108void (*MapInitTab[256])(void)=\r
1109{\r
386f5371 1110 0,\r
1111 0,\r
1112 0, //Mapper2_init,\r
1113 0, //Mapper3_init,\r
1114 0,\r
1115 0,\r
1116 Mapper6_init,\r
1117 0,//Mapper7_init,\r
1118 Mapper8_init,\r
1119 Mapper9_init,\r
1120 Mapper10_init,\r
1121 0, //Mapper11_init,\r
1122 0,\r
1123 0, //Mapper13_init,\r
1124 0,\r
1125 0, //Mapper15_init,\r
1126 0, //Mapper16_init,\r
1127 Mapper17_init,\r
1128 Mapper18_init,\r
1129 0,\r
1130 0,\r
1131 Mapper21_init,\r
1132 Mapper22_init,\r
1133 0, //Mapper23_init,\r
1134 Mapper24_init,\r
1135 Mapper25_init,\r
1136 Mapper26_init,\r
1137 Mapper27_init,\r
1138 0,\r
1139 0,\r
1140 0,\r
1141 0,\r
1142 Mapper32_init,\r
1143 Mapper33_init,\r
1144 Mapper34_init,\r
1145 0,\r
1146 0,\r
1147 0,\r
1148 0,\r
1149 0,\r
1150 Mapper40_init,\r
1151 Mapper41_init,\r
1152 Mapper42_init,\r
1153 0, //Mapper43_init,\r
1154 0,\r
1155 0,\r
1156 Mapper46_init,\r
1157 0,\r
1158 Mapper48_init,\r
1159 0,\r
1160 Mapper50_init,\r
1161 Mapper51_init,\r
1162 0,\r
1163 0,\r
1164 0,\r
1165 0,\r
1166 0,\r
1167 0,// Mapper57_init,\r
1168 0,// Mapper58_init,\r
1169 Mapper59_init,\r
1170 0,// Mapper60_init,\r
1171 Mapper61_init,\r
1172 Mapper62_init,\r
1173 0,\r
1174 Mapper64_init,\r
1175 Mapper65_init,\r
1176 0,//Mapper66_init,\r
1177 Mapper67_init,\r
1178 0,//Mapper68_init,\r
1179 Mapper69_init,\r
1180 0,//Mapper70_init,\r
1181 Mapper71_init,\r
1182 Mapper72_init,\r
1183 Mapper73_init,\r
1184 0,\r
1185 Mapper75_init,\r
1186 Mapper76_init,\r
1187 Mapper77_init,\r
1188 0, //Mapper78_init,\r
1189 Mapper79_init,\r
1190 Mapper80_init,\r
1191 0,\r
1192 Mapper82_init,\r
1193 Mapper83_init,\r
1194 0,\r
1195 Mapper85_init,\r
1196 Mapper86_init,\r
1197 0, //Mapper87_init,\r
1198 0, //Mapper88_init,\r
1199 Mapper89_init,\r
1200 0,\r
1201 Mapper91_init,\r
1202 Mapper92_init,\r
1203 0, //Mapper93_init,\r
1204 0, //Mapper94_init,\r
1205 0,\r
1206 Mapper96_init,\r
1207 Mapper97_init,\r
1208 0,\r
1209 Mapper99_init,\r
1210 0,\r
1211 0,\r
1212 0,\r
1213 0,\r
1214 0,\r
1215 0,\r
1216 0,\r
1217 0, //Mapper107_init,\r
1218 0,\r
1219 0,\r
1220 0,\r
1221 0,\r
1222 0,\r
1223 0, // Mapper113_init,\r
1224 0,\r
1225 0,\r
1226 0, //Mapper116_init,\r
1227 0, //Mapper117_init,\r
1228 0,\r
1229 0,\r
1230 0,\r
1231 0,\r
1232 0,\r
1233 0,\r
1234 0,\r
1235 0,\r
1236 0,\r
1237 0,\r
1238 0,\r
1239 0,\r
1240 0,\r
1241 0,\r
1242 0,\r
1243 0,\r
1244 0,\r
1245 0,\r
1246 0,\r
1247 0,\r
1248 0,\r
1249 0,\r
1250 0, //Mapper140_init,\r
1251 0,\r
1252 0,\r
1253 0,\r
1254 0, //Mapper144_init,\r
1255 0,\r
1256 0,\r
1257 0,\r
1258 0,\r
1259 0,\r
1260 0,\r
1261 Mapper151_init,\r
1262 0, //Mapper152_init,\r
1263 0, //Mapper153_init,\r
1264 0, //Mapper154_init,\r
1265 0,\r
1266 0,\r
1267 Mapper157_init,\r
1268 0, //Mapper158_init, removed\r
1269 0,\r
1270 0,\r
1271 0,\r
1272 0,\r
1273 0,\r
1274 0,\r
1275 0,\r
1276 Mapper166_init,\r
1277 Mapper167_init,\r
1278 0,\r
1279 0,\r
1280 0,\r
1281 0,\r
1282 0,\r
1283 0,\r
1284 0,\r
1285 0,\r
1286 0,\r
1287 0,\r
1288 0,\r
1289 0,\r
1290 0, //Mapper180_init,\r
1291 0,\r
1292 0,\r
1293 0,\r
1294 0, //Mapper184_init,\r
1295 0, //Mapper185_init,\r
1296 0,\r
1297 0,\r
1298 0,\r
1299 0, //Mapper189_init,\r
1300 0,\r
1301 0, //Mapper191_init,\r
1302 0,\r
1303 Mapper193_init,\r
1304 0,\r
1305 0,\r
1306 0,\r
1307 0,\r
1308 0,\r
1309 0,\r
1310 0, //Mapper200_init,\r
1311 Mapper201_init,\r
1312 Mapper202_init,\r
1313 Mapper203_init,\r
1314 Mapper204_init,\r
1315 0,\r
1316 0,\r
1317 Mapper207_init,\r
1318 0,\r
1319 0,\r
1320 0,\r
1321 0, //Mapper211_init,\r
1322 Mapper212_init,\r
1323 Mapper213_init,\r
1324 Mapper214_init,\r
1325 0,\r
1326 0,\r
1327 0,\r
1328 0,\r
1329 0,\r
1330 0,\r
1331 0,\r
1332 0,\r
1333 0,\r
1334 0,\r
1335 Mapper225_init,\r
1336 0, //Mapper226_init,\r
1337 Mapper227_init,\r
1338 Mapper228_init,\r
1339 Mapper229_init,\r
1340 Mapper230_init,\r
1341 Mapper231_init,\r
1342 Mapper232_init,\r
1343 0,\r
1344 Mapper234_init,\r
1345 0, //Mapper235_init,\r
1346 0,\r
1347 0,\r
1348 0,\r
1349 0,\r
1350 0, //Mapper240_init,\r
1351 Mapper241_init,\r
1352 Mapper242_init,\r
1353 0,\r
1354 Mapper244_init,\r
1355 0,\r
1356 Mapper246_init,\r
1357 0,\r
1358 0,\r
1359 0,\r
1360 0,\r
1361 0,\r
1362 0,\r
1363 0,\r
1364 0,\r
1365 Mapper255_init\r
d97315ac 1366};\r
1367\r
1368static DECLFW(BWRAM)\r
1369{\r
386f5371 1370 WRAM[A-0x6000]=V;\r
d97315ac 1371}\r
1372\r
1373static DECLFR(AWRAM)\r
1374{\r
386f5371 1375 return WRAM[A-0x6000];\r
d97315ac 1376}\r
1377\r
d97315ac 1378\r
1379void (*MapStateRestore)(int version);\r
1380void iNESStateRestore(int version)\r
1381{\r
386f5371 1382 int x;\r
1383\r
1384 if(!MapperNo) return;\r
1385\r
1386 for(x=0;x<4;x++)\r
1387 setprg8(0x8000+x*8192,PRGBankList[x]);\r
1388\r
1389 if(VROM_size)\r
1390 for(x=0;x<8;x++)\r
1391 setchr1(0x400*x,CHRBankList[x]);\r
1392\r
1393 if(0) switch(Mirroring)\r
1394 {\r
1395 case 0:setmirror(MI_H);break;\r
1396 case 1:setmirror(MI_V);break;\r
1397 case 0x12:\r
1398 case 0x10:setmirror(MI_0);break;\r
1399 case 0x13:\r
1400 case 0x11:setmirror(MI_1);break;\r
1401 }\r
1402 if(MapStateRestore) MapStateRestore(version);\r
d97315ac 1403}\r
1404\r
1405static void iNESPower(void)\r
1406{\r
386f5371 1407 int x;\r
d97315ac 1408 int type=MapperNo;\r
1409\r
386f5371 1410 SetReadHandler(0x8000,0xFFFF,CartBR);\r
1411 GameStateRestore=iNESStateRestore;\r
1412 MapClose=0;\r
d97315ac 1413 MapperReset=0;\r
386f5371 1414 MapStateRestore=0;\r
d97315ac 1415\r
386f5371 1416 setprg8r(1,0x6000,0);\r
d97315ac 1417\r
386f5371 1418 SetReadHandler(0x6000,0x7FFF,AWRAM);\r
e7f52878 1419#ifdef ASM_6502\r
386f5371 1420 // asm code needs pages to be set again..\r
1421 Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;\r
e7f52878 1422#endif\r
386f5371 1423 SetWriteHandler(0x6000,0x7FFF,BWRAM);\r
1424 FCEU_CheatAddRAM(8,0x6000,WRAM);\r
d97315ac 1425\r
1426 /* This statement represents atrocious code. I need to rewrite\r
386f5371 1427 all of the iNES mapper code... */\r
d97315ac 1428 IRQCount=IRQLatch=IRQa=0;\r
386f5371 1429 if(head.ROM_type&2)\r
1430 memset(GameMemBlock+8192,0,GAME_MEM_BLOCK_SIZE-8192);\r
d97315ac 1431 else\r
386f5371 1432 memset(GameMemBlock,0,GAME_MEM_BLOCK_SIZE);\r
d97315ac 1433\r
386f5371 1434 NONE_init();\r
1435 ResetExState(0,0);\r
d97315ac 1436\r
386f5371 1437 if(GameInfo->type == GIT_VSUNI)\r
1438 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
d97315ac 1439\r
386f5371 1440 AddExState(WRAM, 8192, 0, "WRAM");\r
1441 if(type==19 || type==6 || type==69 || type==85 || type==96)\r
1442 AddExState(MapperExRAM, 32768, 0, "MEXR");\r
1443 if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96))\r
1444 AddExState(CHRRAM, 8192, 0, "CHRR");\r
1445 if(head.ROM_type&8)\r
1446 AddExState(ExtraNTARAM, 2048, 0, "EXNR");\r
d97315ac 1447\r
1448 /* Exclude some mappers whose emulation code handle save state stuff\r
386f5371 1449 themselves. */\r
d97315ac 1450 if(type && type!=13 && type!=96)\r
1451 {\r
386f5371 1452 AddExState(mapbyte1, 32, 0, "MPBY");\r
1453 AddExState(&Mirroring, 1, 0, "MIRR");\r
1454 AddExState(&IRQCount, 4, 1, "IRQC");\r
1455 AddExState(&IRQLatch, 4, 1, "IQL1");\r
1456 AddExState(&IRQa, 1, 0, "IRQA");\r
1457 AddExState(PRGBankList, 4, 0, "PBL");\r
1458 for(x=0;x<8;x++)\r
1459 {\r
1460 char tak[8];\r
1461 sprintf(tak,"CBL%d",x);\r
1462 AddExState(&CHRBankList[x], 2, 1,tak);\r
1463 }\r
d97315ac 1464 }\r
1465\r
386f5371 1466 if(MapInitTab[type]) MapInitTab[type]();\r
1467 else if(type)\r
1468 {\r
1469 FCEU_PrintError("iNES mapper #%d is not supported at all.",type);\r
1470 }\r
d97315ac 1471}\r
1472\r
386f5371 1473static int NewiNES_Init(int num)\r
1474{\r
1475 BMAPPINGLocal *tmp=bmap;\r
d97315ac 1476\r
386f5371 1477 CHRRAMSize = -1;\r
d97315ac 1478\r
386f5371 1479 if(GameInfo->type == GIT_VSUNI)\r
1480 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
e2d0dd92 1481\r
386f5371 1482 while(tmp->init)\r
1483 {\r
1484 if(num==tmp->number)\r
1485 {\r
1486 UNIFchrrama=0; // need here for compatibility with UNIF mapper code\r
1487 if(!VROM_size)\r
1488 {\r
1489 if(num==13)\r
1490 {\r
1491 CHRRAMSize=16384;\r
1492 }\r
1493 else\r
1494 {\r
1495 CHRRAMSize=8192;\r
1496 }\r
1497 if((VROM = (uint8 *)FCEU_malloc(CHRRAMSize)) == NULL) return 0;\r
1498 FCEU_MemoryRand(VROM,CHRRAMSize);\r
1499\r
1500 UNIFchrrama=VROM;\r
1501 SetupCartCHRMapping(0,VROM,CHRRAMSize,1);\r
1502 AddExState(VROM,CHRRAMSize, 0, "CHRR");\r
1503 }\r
1504 if(head.ROM_type&8)\r
1505 AddExState(ExtraNTARAM, 2048, 0, "EXNR");\r
1506 tmp->init(&iNESCart);\r
1507 return 1;\r
1508 }\r
1509 tmp++;\r
1510 }\r
1511 return 0;\r
d97315ac 1512}\r
6587f346 1513\r
386f5371 1514// vim:ts=4\r