merge mapper code from FCEUX
[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         {"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
699 void 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
720 int iNESLoad(const char *name, int fp, int OverwriteVidMode)\r
721 {\r
722         struct md5_context md5;\r
723 \r
724         if(FCEU_fread(&head,1,16,fp)!=16)\r
725                 return 0;\r
726 \r
727         if(memcmp(&head,"NES\x1a",4))\r
728                 return 0;\r
729 \r
730         cleanup(&head);\r
731 \r
732         memset(&iNESCart,0,sizeof(iNESCart));\r
733 \r
734         MapperNo = (head.ROM_type>>4);\r
735         MapperNo|=(head.ROM_type2&0xF0);\r
736         Mirroring = (head.ROM_type&1);\r
737 \r
738 \r
739         //  int ROM_size=0;\r
740         if(!head.ROM_size)\r
741         {\r
742                 //   FCEU_PrintError("No PRG ROM!");\r
743                 //   return(0);\r
744                 ROM_size=256;\r
745                 //head.ROM_size++;\r
746         }\r
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
752 \r
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
768 \r
769     if(VROM_size)\r
770                 VROM_size=uppow2(VROM_size);\r
771 \r
772 \r
773         if(head.ROM_type&8) Mirroring=2;\r
774 \r
775         if((ROM = (uint8 *)FCEU_malloc(ROM_size<<14)) == NULL) return 0;\r
776 \r
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
789         {\r
790                 trainerpoo=(uint8 *)FCEU_gmalloc(512);\r
791                 FCEU_fread(trainerpoo,512,1,fp);\r
792         }\r
793 \r
794         ResetCartMapping();\r
795         ResetExState(0,0);\r
796 \r
797         SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);\r
798    // SetupCartPRGMapping(1,WRAM,8192,1); // ?\r
799 \r
800     FCEU_fread(ROM,0x4000,(round) ? ROM_size : head.ROM_size,fp);\r
801 \r
802         if(VROM_size)\r
803                 FCEU_fread(VROM,0x2000,head.VROM_size,fp);\r
804 \r
805         md5_starts(&md5);\r
806         md5_update(&md5,ROM,ROM_size<<14);\r
807 \r
808         iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);\r
809 \r
810         if(VROM_size)\r
811         {\r
812                 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);\r
813                 md5_update(&md5,VROM,VROM_size<<13);\r
814         }\r
815         md5_finish(&md5,iNESCart.MD5);\r
816         memcpy(&GameInfo->MD5,&iNESCart.MD5,sizeof(iNESCart.MD5));\r
817 \r
818         iNESCart.CRC32=iNESGameCRC32;\r
819 \r
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
823 \r
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
849 \r
850         SetInput();\r
851         CheckHInfo();\r
852         {\r
853                 int x;\r
854                 uint64 partialmd5=0;\r
855 \r
856                 for(x=0;x<8;x++)\r
857                 {\r
858                         partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);\r
859                 }\r
860 \r
861                 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);\r
862         }\r
863         /* Must remain here because above functions might change value of\r
864         VROM_size and free(VROM).\r
865         */\r
866         if(VROM_size)\r
867                 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);\r
868 \r
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
873         else\r
874                 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);\r
875 \r
876         iNESCart.battery=(head.ROM_type&2)?1:0;\r
877         iNESCart.mirror=Mirroring;\r
878 \r
879         //if(MapperNo != 18) {\r
880         //  if(ROM) free(ROM);\r
881         //  if(VROM) free(VROM);\r
882         //  ROM=VROM=0;\r
883         //  return(0);\r
884         // }\r
885 \r
886 \r
887         GameInfo->mappernum = MapperNo;\r
888         MapperInit();\r
889         FCEU_LoadGameSave(&iNESCart);\r
890 \r
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
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
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
921 int 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
954 int 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
979 \r
980         return 1;\r
981 }\r
982 \r
983 //para edit: added function below\r
984 #if 0\r
985 char *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
995 void VRAM_BANK1(uint32 A, uint8 V)\r
996 {\r
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
1001 }\r
1002 \r
1003 void VRAM_BANK4(uint32 A, uint32 V)\r
1004 {\r
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
1012 }\r
1013 void VROM_BANK1(uint32 A,uint32 V)\r
1014 {\r
1015         setchr1(A,V);\r
1016         CHRBankList[(A)>>10]=V;\r
1017 }\r
1018 \r
1019 void VROM_BANK2(uint32 A,uint32 V)\r
1020 {\r
1021         setchr2(A,V);\r
1022         CHRBankList[(A)>>10]=(V<<1);\r
1023         CHRBankList[((A)>>10)+1]=(V<<1)+1;\r
1024 }\r
1025 \r
1026 void VROM_BANK4(uint32 A, uint32 V)\r
1027 {\r
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
1033 }\r
1034 \r
1035 void VROM_BANK8(uint32 V)\r
1036 {\r
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
1046 }\r
1047 \r
1048 void ROM_BANK8(uint32 A, uint32 V)\r
1049 {\r
1050         setprg8(A,V);\r
1051         if(A>=0x8000)\r
1052                 PRGBankList[((A-0x8000)>>13)]=V;\r
1053 }\r
1054 \r
1055 void ROM_BANK16(uint32 A, uint32 V)\r
1056 {\r
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
1063 }\r
1064 \r
1065 void ROM_BANK32(uint32 V)\r
1066 {\r
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
1072 }\r
1073 \r
1074 void onemir(uint8 V)\r
1075 {\r
1076         if(Mirroring==2) return;\r
1077         if(V>1)\r
1078                 V=1;\r
1079         Mirroring=0x10|V;\r
1080         setmirror(MI_0+V);\r
1081 }\r
1082 \r
1083 void MIRROR_SET2(uint8 V)\r
1084 {\r
1085         if(Mirroring==2) return;\r
1086         Mirroring=V;\r
1087         setmirror(V);\r
1088 }\r
1089 \r
1090 void MIRROR_SET(uint8 V)\r
1091 {\r
1092         if(Mirroring==2) return;\r
1093         V^=1;\r
1094         Mirroring=V;\r
1095         setmirror(V);\r
1096 }\r
1097 \r
1098 static void NONE_init(void)\r
1099 {\r
1100         ROM_BANK16(0x8000,0);\r
1101         ROM_BANK16(0xC000,~0);\r
1102 \r
1103         if(VROM_size)\r
1104                 VROM_BANK8(0);\r
1105         else\r
1106                 setvram8(CHRRAM);\r
1107 }\r
1108 void (*MapInitTab[256])(void)=\r
1109 {\r
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
1366 };\r
1367 \r
1368 static DECLFW(BWRAM)\r
1369 {\r
1370         WRAM[A-0x6000]=V;\r
1371 }\r
1372 \r
1373 static DECLFR(AWRAM)\r
1374 {\r
1375         return WRAM[A-0x6000];\r
1376 }\r
1377 \r
1378 \r
1379 void (*MapStateRestore)(int version);\r
1380 void iNESStateRestore(int version)\r
1381 {\r
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
1403 }\r
1404 \r
1405 static void iNESPower(void)\r
1406 {\r
1407         int x;\r
1408         int type=MapperNo;\r
1409 \r
1410         SetReadHandler(0x8000,0xFFFF,CartBR);\r
1411         GameStateRestore=iNESStateRestore;\r
1412         MapClose=0;\r
1413         MapperReset=0;\r
1414         MapStateRestore=0;\r
1415 \r
1416         setprg8r(1,0x6000,0);\r
1417 \r
1418         SetReadHandler(0x6000,0x7FFF,AWRAM);\r
1419 #ifdef ASM_6502\r
1420         // asm code needs pages to be set again..\r
1421         Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;\r
1422 #endif\r
1423         SetWriteHandler(0x6000,0x7FFF,BWRAM);\r
1424         FCEU_CheatAddRAM(8,0x6000,WRAM);\r
1425 \r
1426         /* This statement represents atrocious code.  I need to rewrite\r
1427         all of the iNES mapper code... */\r
1428         IRQCount=IRQLatch=IRQa=0;\r
1429         if(head.ROM_type&2)\r
1430                 memset(GameMemBlock+8192,0,GAME_MEM_BLOCK_SIZE-8192);\r
1431         else\r
1432                 memset(GameMemBlock,0,GAME_MEM_BLOCK_SIZE);\r
1433 \r
1434         NONE_init();\r
1435         ResetExState(0,0);\r
1436 \r
1437         if(GameInfo->type == GIT_VSUNI)\r
1438                 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
1439 \r
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
1447 \r
1448         /* Exclude some mappers whose emulation code handle save state stuff\r
1449         themselves. */\r
1450         if(type && type!=13 && type!=96)\r
1451         {\r
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
1464         }\r
1465 \r
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
1471 }\r
1472 \r
1473 static int NewiNES_Init(int num)\r
1474 {\r
1475         BMAPPINGLocal *tmp=bmap;\r
1476 \r
1477         CHRRAMSize = -1;\r
1478 \r
1479         if(GameInfo->type == GIT_VSUNI)\r
1480                 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);\r
1481 \r
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
1512 }\r
1513 \r
1514 // vim:ts=4\r