merge mappers from FCEU-mm
[fceu.git] / ines.c
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
46 extern SFORMAT FCEUVSUNI_STATEINFO[];\r
47 \r
48 //mbg merge 6/29/06 - these need to be global\r
49 uint8 *trainerpoo=0;\r
50 uint8 *ROM = NULL;\r
51 uint8 *VROM = NULL;\r
52 struct iNES_HEADER head;\r
53 \r
54 \r
55 \r
56 static CartInfo iNESCart;\r
57 \r
58 uint8 iNESMirroring=0;\r
59 uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0};\r
60 int32 iNESIRQLatch=0,iNESIRQCount=0;\r
61 uint8 iNESIRQa=0;\r
62 \r
63 uint32 ROM_size=0;\r
64 uint32 VROM_size=0;\r
65 //char LoadedRomFName[2048]; //mbg merge 7/17/06 added\r
66 \r
67 static int CHRRAMSize = -1;\r
68 static void iNESPower(void);\r
69 static int NewiNES_Init(int num);\r
70 \r
71 void (*MapClose)(void);\r
72 void (*MapperReset)(void);\r
73 \r
74 static int MapperNo=0;\r
75 \r
76 /*  MapperReset() is called when the NES is reset(with the reset button).\r
77 Mapperxxx_init is called when the NES has been powered on.\r
78 */\r
79 \r
80 \r
81 static DECLFR(TrainerRead)\r
82 {\r
83         return(trainerpoo[A&0x1FF]);\r
84 }\r
85 \r
86 static 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
112 static 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
153 uint32 iNESGameCRC32=0;\r
154 \r
155 struct CRCMATCH  {\r
156         uint32 crc;\r
157         char *name;\r
158 };\r
159 \r
160 struct INPSEL {\r
161         uint32 crc32;\r
162         int input1;\r
163         int input2;\r
164         int inputfc;\r
165 };\r
166 \r
167 static 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
266 struct BADINF {\r
267         uint64 md5partial;\r
268         char *name;\r
269         uint32 type;\r
270 };\r
271 \r
272 \r
273 static struct BADINF BadROMImages[]=\r
274 {\r
275 #include "ines-bad.h"\r
276 };\r
277 \r
278 void 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
297 struct CHINF {\r
298         uint32 crc32;\r
299         int32 mapper;\r
300         int32 mirror;\r
301         const char* params;\r
302 };\r
303 \r
304 void 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
322 static 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
333 const TMasterRomInfo* MasterRomInfo;\r
334 TMasterRomInfoParams MasterRomInfoParams;\r
335 #endif\r
336 \r
337 static 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
530 typedef 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
541 static int not_power2[] =\r
542 {\r
543     228\r
544 };\r
545 typedef struct {\r
546         char* name;\r
547         int number;\r
548         void (*init)(CartInfo *);\r
549 } BMAPPINGLocal;\r
550 \r
551 static 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
811 void 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
832 int 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
1033 int 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
1066 int 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
1097 char *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
1107 void 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
1115 void 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
1125 void VROM_BANK1(uint32 A,uint32 V)\r
1126 {\r
1127         setchr1(A,V);\r
1128         CHRBankList[(A)>>10]=V;\r
1129 }\r
1130 \r
1131 void 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
1138 void 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
1147 void 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
1160 void 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
1167 void 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
1177 void 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
1186 void 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
1195 void 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
1202 void 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
1210 static 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
1221 void (*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
1481 static DECLFW(BWRAM)\r
1482 {\r
1483         WRAM[A-0x6000]=V;\r
1484 }\r
1485 \r
1486 static DECLFR(AWRAM)\r
1487 {\r
1488         return WRAM[A-0x6000];\r
1489 }\r
1490 \r
1491 \r
1492 void (*MapStateRestore)(int version);\r
1493 void 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
1518 static 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
1586 static 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