asm cpu works, added sync()s
[fceu.git] / ines.c
CommitLineData
c62d2810 1/* FCE Ultra - NES/Famicom Emulator
2 *
3 * Copyright notice for this file:
92e249b1 4 * Copyright (C) 1998 BERO
c62d2810 5 * Copyright (C) 2002 Ben Parnell
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
92e249b1 25#ifdef GP2X
26#include <unistd.h>
27#endif
c62d2810 28
29#include "types.h"
30#include "x6502.h"
31#include "fce.h"
32#define INESPRIV
33#include "ines.h"
34#include "version.h"
35#include "svga.h"
36#include "general.h"
37#include "state.h"
38#include "file.h"
39#include "memory.h"
40#include "cart.h"
41#include "crc32.h"
42#include "cheat.h"
43
44static DECLFR(VSRead);
45
46static uint8 *trainerpoo=0;
47static uint8 *ROM=NULL;
48uint8 *VROM=NULL;
49
50
51static uint32 ROM_size;
52uint32 VROM_size;
53
54static void CheckVSUni(void);
55static int MMC_init(int type);
56void (*MapClose)(void);
57void (*MapperReset)(void);
58
59static int MapperNo;
60static int SaveGame=0;
61
62static iNES_HEADER head;
63
92e249b1 64/* MapperReset() is called when the NES is reset(with the reset button).
c62d2810 65 Mapperxxx_init is called when the NES has been powered on.
66*/
67
68static void iNESGI(int h)
69{
70 switch(h)
71 {
72 case GI_RESETM2:
73 if(MapperReset)
74 MapperReset();
75 break;
76 case GI_POWER:
77 SetReadHandler(0x8000,0xFFFF,CartBR);
78 MMC_init(MapperNo);
79 break;
80 case GI_CLOSE:
81 {
82 FILE *sp;
92e249b1 83
c62d2810 84 if(ROM) {free(ROM);ROM=0;}
85 if(VROM) {free(VROM);VROM=0;}
86
87 if(SaveGame)
88 {
89 char *soot;
90 SaveGame=0;
91 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
92 sp=fopen(soot,"wb");
93 if (sp==NULL)
94 FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
95 else
96 {
97 void *ptr;
98 uint32 amount;
99 ptr=WRAM;
100 amount=8192;
101
102 if(MapperNo==1)
103 {
104 extern uint8 MMC1WRAMsize;
105 if(MMC1WRAMsize==2) ptr=WRAM+8192;
106 }
107 else if(MapperNo==5)
108 {
109 extern uint8 MMC5WRAMsize;
110 if(MMC5WRAMsize==4)
111 amount=32768;
112 }
113
114 fwrite(ptr,1,amount,sp);
115 fclose(sp);
92e249b1 116#ifdef GP2X
117 sync();
118#endif
c62d2810 119 }
120 }
121 if(MapClose) MapClose();
122 if(trainerpoo) {free(trainerpoo);trainerpoo=0;}
123 }
124 break;
125 }
126}
127
128uint32 iNESGameCRC32;
129
130struct CRCMATCH {
131 uint32 crc;
132 char *name;
133};
134
135static void CheckBad(void)
136{
137 int x;
138 #define CRCNT 7
139 struct CRCMATCH tab[CRCNT]={
140 {0x28d183ac,"Antarctic Adventure"},
141 {0x7095ac65,"Akumajo Densetsu"},
142 {0x1bd7ed5a,"Gradius 2"},
143 {0x81c3aa66,"Crisis Force"},
144 {0xfe3088df,"Fire Emblem Gaiden"},
145 {0xfa8339a5,"Bucky O'Hare"},
146 {0x3c539d78,"Ganbare Goemon 2"},
147 };
148 for(x=0;x<CRCNT;x++)
149 if(tab[x].crc == iNESGameCRC32)
150 {
151 FCEU_PrintError("The copy of the game you have loaded, %s, is a bad dump, has been hacked, or both. It will not work correctly on FCE Ultra. Use a good copy of the ROM image instead.",tab[x].name);
152 break;
153 }
154}
155
156struct INPSEL {
157 uint32 crc32;
158 int input1;
159 int input2;
160 int inputfc;
161};
162
163/* This is mostly for my personal use. So HA. */
164static void SetInput(void)
165{
166 static struct INPSEL moo[]=
167 {
168 {0xad9c63e2,SI_GAMEPAD,-1,SIFC_SHADOW}, /* Space Shadow */
169 {0x24598791,-1,SI_ZAPPER,0}, /* Duck Hunt */
170 {0xff24d794,-1,SI_ZAPPER,0}, /* Hogan's Alley */
171 {0xbeb8ab01,-1,SI_ZAPPER,0}, /* Gumshoe */
172 {0xde8fd935,-1,SI_ZAPPER,0}, /* To the Earth */
173 {0xedc3662b,-1,SI_ZAPPER,0}, /* Operation Wolf */
174 {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,0}, /* The Lone Ranger */
175 {0xb8b9aca3,-1,SI_ZAPPER,0}, /* Wild Gunman */
176 {0x5112dc21,-1,SI_ZAPPER,0}, /* Wild Gunman */
177 {0x4318a2f8,-1,SI_ZAPPER,0}, /* Barker Bill's Trick Shooting */
178 {0x5ee6008e,-1,SI_ZAPPER,0}, /* Mechanized Attack */
179 {0x3e58a87e,-1,SI_ZAPPER,0}, /* Freedom Force */
180 {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,0}, /* Shooting Range */
181 {0x74bea652,SI_GAMEPAD,SI_ZAPPER,0}, /* Supergun 3-in-1 */
182 {0x32fb0583,-1,SI_ARKANOID,0}, /* Arkanoid(NES) */
183 {0xd89e5a67,-1,-1,SIFC_ARKANOID}, /* Arkanoid (J) */
184 {0x0f141525,-1,-1,SIFC_ARKANOID}, /* Arkanoid 2(J) */
185
186 {0xf7606810,-1,-1,SIFC_FKB}, /* Family BASIC 2.0A */
187 {0x895037bc,-1,-1,SIFC_FKB}, /* Family BASIC 2.1a */
188 {0xb2530afc,-1,-1,SIFC_FKB}, /* Family BASIC 3.0 */
189 {0,-1,-1,-1}
190 };
191 int x=0;
192
193 while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0)
194 {
195 if(moo[x].crc32==iNESGameCRC32)
196 {
197 FCEUGameInfo.input[0]=moo[x].input1;
198 FCEUGameInfo.input[1]=moo[x].input2;
199 FCEUGameInfo.inputfc=moo[x].inputfc;
200 break;
201 }
202 x++;
203 }
204}
205
206struct CHINF {
207 uint32 crc32;
208 int32 mapper;
209 int32 mirror;
210};
211
212#define SAVCNT 14
213static void CheckHInfo(void)
214{
215 /* ROM images that have the battery-backed bit set in the header that really
216 don't have battery-backed RAM is not that big of a problem, so I'll
217 treat this differently.
218 */
219
220 static uint32 savie[SAVCNT]=
221 {
222 0x7cab2e9b,0x3ee43cda,0xe1383deb, /* Mouryou Senki Madara */
223 0x3b3f88f0,0x2545214c, /* Dragon Warrior PRG 0 and 1 */
224 0x8c5a784e, /* DW 2 */
225 0xa86a5318, /* DW 3 */
226 0x506e259d, /* DW 4 */
227 0xcebd2a31,0xb8b88130, /* Final Fantasy */
228 0x466efdc2, /* FF(J) */
229 0xc9556b36, /* FF1+2*/
230 0xd29db3c7, /* FF2 */
231 0x57e220d0, /* FF3 */
232 };
233
234 static struct CHINF moo[]=
235 {
236 {0xc68363f6,180,0}, /* Crazy Climber */
237 {0xbe939fce,9,1}, /* Punchout*/
238 {0x5e66eaea,13,1}, /* Videomation */
239 {0xaf5d7aa2,-1,0}, /* Clu Clu Land */
240
241 {0xc2730c30,34,0}, /* Deadly Towers */
242 {0x932ff06e,34,1}, /* Classic Concentration */
243 {0x4c7c1af3,34,1}, /* Caesar's Palace */
244 {0x9ea1dc76,2,0}, /* Rainbow Islands */
92e249b1 245
c62d2810 246 {0x9eefb4b4,4,8}, /* Pachi Slot Adventure 2 */
247 {0x5337f73c,4,8}, /* Niji no Silk Road */
248 {0x7474ac92,4,8}, /* Kabuki: Quantum Fighter */
249
250 {0x970bd9c2,1,8}, /* Hanjuku Hero */
251
252 {0xbb7c5f7a,89,8}, /* Mito Koumon or something similar */
253 /* Probably a Namco MMC3-workalike */
254 {0xa5e6baf9,4,1|4}, /* Dragon Slayer 4 */
255 {0xe40b4973,4,1|4}, /* Metro Cross */
256 {0xd97c31b0,4,1|4}, /* Rasaaru Ishii no Childs Quest */
257
258 {0x84382231,9,0}, /* Punch Out (J) */
259
260 {0xfcdaca80,0,0}, /* Elevator Action */
261 {0xe492d45a,0,0}, /* Zippy Race */
262 {0x32fa246f,0,0}, /* Tag Team Pro Wrestling */
263 {0x6d65cac6,2,0}, /* Terra Cresta */
264 {0x28c11d24,2,1}, /* Sukeban Deka */
265 {0x02863604,2,1}, /* Sukeban Deka */
266 {0x2bb6a0f8,2,1}, /* Sherlock Holmes */
267 {0x55773880,2,1}, /* Gilligan's Island */
268 {0x419461d0,2,1}, /* Super Cars */
269 {0x6e0eb43e,2,1}, /* Puss n Boots */
270 {0xfc3e5c86,2,1}, /* Trojan */
271
272 {0x291bcd7d,1,8}, /* Pachio Kun 2 */
273 {0xf74dfc91,1,-1}, /* Win, Lose, or Draw */
274
275 {0x59280bec,4,8}, /* Jackie Chan */
276
277 {0xfe364be5,1,8}, /* Deep Dungeon 4 */
278 {0xd8ee7669,1,8}, /* Adventures of Rad Gravity */
279 {0xa5e8d2cd,1,8}, /* Breakthru */
280 {0xf6fa4453,1,8}, /* Bigfoot */
281 {0x37ba3261,1,8}, /* Back to the Future 2 and 3 */
282 {0x934db14a,1,-1}, /* All-Pro Basketball */
283 {0xe94d5181,1,8}, /* Mirai Senshi - Lios */
284 {0x7156cb4d,1,8}, /* Muppet Adventure Carnival thingy */
285 {0x5b6ca654,1,8}, /* Barbie rev X*/
286 {0x57c12280,1,8}, /* Demon Sword */
287
288 {0xcf322bb3,3,1}, /* John Elway's Quarterback */
289 {0x9bde3267,3,1}, /* Adventures of Dino Riki */
290 {0x02cc3973,3,8}, /* Ninja Kid */
291 {0xb5d28ea2,3,1}, /* Mystery Quest - mapper 3?*/
292 {0xbc065fc3,3,1}, /* Pipe Dream */
293
294 {0x5b837e8d,1,8}, /* Alien Syndrome */
295 {0x283ad224,32,8}, /* Ai Sensei no Oshiete */
296 {0x5555fca3,32,8}, /* "" "" */
297 {0x243a8735,32,0x10|4}, /* Major League */
298
299 {0x6bc65d7e,66,1}, /* Youkai Club*/
300 {0xc2df0a00,66,1}, /* Bio Senshi Dan(hacked) */
301 {0xbde3ae9b,66,1}, /* Doraemon */
302 {0xd26efd78,66,1}, /* SMB Duck Hunt */
303 {0x811f06d9,66,1}, /* Dragon Power */
304
305 {0x3293afea,66,1}, /* Mississippi Satsujin Jiken */
306 {0xe84274c5,66,1}, /* "" "" */
307
308
309 {0x6e68e31a,16,8}, /* Dragon Ball 3*/
310
311 {0xba51ac6f,78,2},
312 {0x3d1c3137,78,8},
313
314 {0xbda8f8e4,152,8}, /* Gegege no Kitarou 2 */
315 {0x026c5fca,152,8}, /* Saint Seiya Ougon Densetsu */
316 {0x0f141525,152,8}, /* Arkanoid 2 (Japanese) */
317 {0xb1a94b82,152,8}, /* Pocket Zaurus */
318
319 {0x3f15d20d,153,8}, /* Famicom Jump 2 */
320
321 {0xbba58be5,70,-1}, /* Family Trainer - Manhattan Police */
322 {0x370ceb65,70,-1}, /* Family Trainer - Meiro Dai Sakusen */
323 {0xdd8ed0f7,70,1}, /* Kamen Rider Club */
324
325 {0x90c773c1,118,-1}, /* Goal! 2 */
326 {0xb9b4d9e0,118,-1}, /* NES Play Action Football */
327 {0x78b657ac,118,-1}, /* Armadillo */
328 {0x37b62d04,118,-1}, /* Ys 3 */
329 {0x07d92c31,118,-1}, /* RPG Jinsei Game */
330 {0x2705eaeb,234,-1}, /* Maxi 15 */
331 {0x404b2e8b,4,2}, /* Rad Racer 2 */
332
333 {0x1356f6a6,4,8}, /* "Cattou Ninden Teyandee" English tranlation.
334 Should I have even bothered to do this? */
335 {0x50fd4fd6,4,8}, /* "" "" */
336
337 {0xa912b064,51|0x800,8}, /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */
338 {0,-1,-1}
339 };
340 int tofix=0;
341 int x=0;
342
343 do
344 {
345 if(moo[x].crc32==iNESGameCRC32)
346 {
347 if(moo[x].mapper>=0)
348 {
349 if(moo[x].mapper&0x800 && VROM_size)
350 {
351 VROM_size=0;
352 free(VROM);
353 tofix|=8;
354 }
355 if(MapperNo!=(moo[x].mapper&0xFF))
356 {
357 tofix|=1;
358 MapperNo=moo[x].mapper&0xFF;
359 }
360 }
361 if(moo[x].mirror>=0)
362 {
363 if(moo[x].mirror==8)
364 {
365 if(Mirroring==2) /* Anything but hard-wired(four screen). */
366 {
367 tofix|=2;
368 Mirroring=0;
369 }
370 }
371 else if(Mirroring!=moo[x].mirror)
372 {
373 if(Mirroring!=(moo[x].mirror&~4))
374 if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring
375 needs to be set(the iNES header can't
376 hold this information).
377 */
378 tofix|=2;
379 Mirroring=moo[x].mirror;
380 }
381 }
382 break;
383 }
384 x++;
385 } while(moo[x].mirror>=0 || moo[x].mapper>=0);
386
387 for(x=0;x<SAVCNT;x++)
388 {
389 if(savie[x]==iNESGameCRC32)
390 {
391 if(!(head.ROM_type&2))
392 {
393 tofix|=4;
394 head.ROM_type|=2;
395 }
396 }
397 }
398
399 /* Games that use these iNES mappers tend to have the four-screen bit set
400 when it should not be.
401 */
402 if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2))
403 {
404 Mirroring=0;
405 tofix|=2;
406 }
407
408 if(tofix)
409 {
410 char gigastr[768];
411 strcpy(gigastr,"The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
412 if(tofix&1)
413 sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d. ",MapperNo);
414 if(tofix&2)
415 {
416 char *mstr[3]={"Horizontal","Vertical","Four-screen"};
417 sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]);
418 }
419 if(tofix&4)
92e249b1 420 strcat(gigastr,"The battery-backed bit should be set. ");
c62d2810 421 if(tofix&8)
422 strcat(gigastr,"This game should not have any CHR ROM. ");
423 strcat(gigastr,"\n");
424 FCEUD_PrintError(gigastr);
425 }
426}
427
428int iNESLoad(char *name, int fp)
429{
430 FILE *sp;
431
432 if(FCEU_fread(&head,1,16,fp)!=16)
433 return 0;
434
435 if(memcmp(&head,"NES\x1a",4))
436 return 0;
437
438 if(!memcmp((char *)(&head)+0x7,"DiskDude",8))
439 {
440 memset((char *)(&head)+0x7,0,0x9);
441 }
442
443 if(!memcmp((char *)(&head)+0x7,"demiforce",9))
444 {
445 memset((char *)(&head)+0x7,0,0x9);
446 }
447
448 if(!memcmp((char *)(&head)+0xA,"Ni03",4))
449 {
450 if(!memcmp((char *)(&head)+0x7,"Dis",3))
451 memset((char *)(&head)+0x7,0,0x9);
452 else
453 memset((char *)(&head)+0xA,0,0x6);
454 }
455
456 if(!head.ROM_size)
457 head.ROM_size++;
458
459 ROM_size = head.ROM_size;
460 VROM_size = head.VROM_size;
461 ROM_size=uppow2(ROM_size);
462
463 if(VROM_size)
464 VROM_size=uppow2(VROM_size);
465
466 MapperNo = (head.ROM_type>>4);
467 MapperNo|=(head.ROM_type2&0xF0);
468
469 Mirroring = (head.ROM_type&1);
470 if(head.ROM_type&8) Mirroring=2;
471
472 if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
473 return 0;
92e249b1 474
475 if (VROM_size)
c62d2810 476 if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
477 {
478 free(ROM);
479 return 0;
480 }
481
482 memset(ROM,0xFF,ROM_size<<14);
483 if(VROM_size) memset(VROM,0xFF,VROM_size<<13);
484 if(head.ROM_type&4) /* Trainer */
485 {
486 if(!(trainerpoo=FCEU_malloc(512)))
487 return(0);
488 FCEU_fread(trainerpoo,512,1,fp);
489 }
490 ResetCartMapping();
491 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);
492 SetupCartPRGMapping(1,WRAM,8192,1);
493
494 FCEU_fread(ROM,0x4000,head.ROM_size,fp);
495
496 if(VROM_size)
497 FCEU_fread(VROM,0x2000,head.VROM_size,fp);
498
499 printf("File %s loaded.\n",name);
500
501 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);
502 if(VROM_size)
503 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);
504 printf("\n PRG ROM: %3d x 16k\n CHR ROM: %3d x 8k\n ROM CRC32: %08lx\n Mapper: %d\n Mirroring: %s\n",head.ROM_size,head.VROM_size,iNESGameCRC32,MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal");
505 if(head.ROM_type&2) puts(" Battery-backed.");
506 if(head.ROM_type&4) puts(" Trained.");
507 puts("");
508
509 CheckBad();
510 SetInput();
511 CheckHInfo();
512 CheckVSUni();
513 //if(MapperNo!=4 && MapperNo!=118 && MapperNo!=119) exit(1); // Testing
514
515 /* Must remain here because above functions might change value of
516 VROM_size and free(VROM).
517 */
518 if(VROM_size)
519 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);
520
521 if(Mirroring==2)
522 SetupCartMirroring(4,1,ExtraNTARAM);
523 else if(Mirroring>=0x10)
524 SetupCartMirroring(2+(Mirroring&1),1,0);
525 else
526 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);
527
528 if(MapperNo==5) DetectMMC5WRAMSize();
529 else if(MapperNo==1) DetectMMC1WRAMSize();
530
531 if(head.ROM_type&2)
92e249b1 532 {
c62d2810 533 char *soot;
534
535 SaveGame=1;
536 soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
537 sp=fopen(soot,"rb");
538 if(sp!=NULL)
539 {
540 void *ptr;
541 uint32 amount;
542
543 ptr=WRAM;
544 amount=8192;
545 if(MapperNo==1)
546 {
547 extern uint8 MMC1WRAMsize;
548 if(MMC1WRAMsize==2) ptr=WRAM+8192;
549 }
550 else if(MapperNo==5)
551 {
552 extern uint8 MMC5WRAMsize;
553 if(MMC5WRAMsize==4)
554 amount=32768;
555 }
556 if(fread(ptr,1,amount,sp)==amount)
557 printf(" WRAM Save File \"%s\" loaded...\n",soot);
558 fclose(sp);
559 }
560
561 }
562 GameInterface=iNESGI;
563 return 1;
564}
565
566#include "banksw.h"
567
568
569void FASTAPASS(1) onemir(uint8 V)
570{
571 if(Mirroring==2) return;
572 if(V>1)
573 V=1;
574 Mirroring=0x10|V;
575 setmirror(MI_0+V);
576}
577
578void FASTAPASS(1) MIRROR_SET2(uint8 V)
579{
580 if(Mirroring==2) return;
581 Mirroring=V;
582 setmirror(V);
583}
584
585void FASTAPASS(1) MIRROR_SET(uint8 V)
586{
587 if(Mirroring==2) return;
588 V^=1;
589 Mirroring=V;
590 setmirror(V);
591}
592
593static void NONE_init(void)
594{
595 ROM_BANK16(0x8000,0);
596 ROM_BANK16(0xC000,~0);
597
92e249b1 598 if(VROM_size)
c62d2810 599 VROM_BANK8(0);
600 else
601 setvram8(CHRRAM);
602}
603
604static uint8 secdata[2][32]=
605{
606 {
607 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
608 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
609 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
610 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
611 },
612 {
613 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00,
614 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00,
615 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
617 }
618};
619
620static uint8 *secptr;
621
622static void CheckVSUni(void)
623{
624 FCEUGameInfo.type=GIT_VSUNI;
92e249b1 625
c62d2810 626 /* FCE Ultra doesn't complain when headers for these games are bad. */
627 secptr=0;
628 switch(iNESGameCRC32)
629 {
630 default:FCEUGameInfo.type=0;break;
631
632 case 0xffbef374: pale=1;break; /* Castlevania */
633
92e249b1 634 case 0x98e3c75a:
c62d2810 635 case 0x7cff0f84: pale=2;break; /* SMB */
92e249b1 636
c62d2810 637 case 0xef7af338: pale=2;break; /* Ice Climber */
638 case 0xabe1a0c2: FCEUGameInfo.input[0]=SI_ZAPPER;break; /*Duck hunt */
639 case 0x16aa4e2d: pale=7;FCEUGameInfo.input[0]=SI_ZAPPER;break; /* hoganal ^_^ */
640 case 0x2b85420e: pale=3;break; /* Dr Mario */
641
642 case 0xfb0ddde7: pale=2;break;
643 case 0xc95321a8: pale=6;break; /* Excitebike */
644 case 0xb1c4c508: pale=1;break; /* Golf */
645
646 case 0x66471efe: break;
647 case 0xca3e9b1a: pale=7;break; /* Pinball*/
648
649 case 0xf735d926: pale=7; break; /* Gradius */
650
651 case 0x2019fe65:
652 case 0x31678411:MapperNo=68;pale=7;break; /* Platoon */
653
654 case 0x74f713b4:pale=4;break; /* Goonies */
655 case 0x9ae2baa0:pale=5;break; /* Slalom */
656 case 0xe45485a5:secptr=secdata[1];vsdip=0x20;MapperNo=4;break; /* RBI Baseball */
657 case 0x21a653c7:vsdip=0x20;MapperNo=4;break; /* Super Sky Kid */
658 case 0xe9a6f17d:vsdip=0x20;break; /* Tetris */
659
660 case 0x159ef3c1:break; /* Star Luster */
661 case 0x9768e5e0:break; /* Stroke and Match Golf */
92e249b1 662
c62d2810 663 /* FCE Ultra doesn't have correct palettes for the following games. */
664 case 0x0fa322c2:pale=2;break; /* Clu Clu Land */
665
666 case 0x766c2cac: /* Soccer */
667 case 0x01357944: /* Battle City */
668 case 0xb2816bf9:break; /* Battle City (Bootleg) */
669
670 case 0x832cf592:FCEUGameInfo.input[0]=SI_ZAPPER;break; /* Freedom Force */
671 case 0x63abf889:break; /* Ladies Golf */
672 case 0x8c0c2df5:pale=2;MapperNo=1;Mirroring=1;break; /* Top Gun */
92e249b1 673 case 0x52c501d0:vsdip=0x80;MapperNo=4;secptr=secdata[0];break;
c62d2810 674 /* TKO Boxing */
675 }
676
677 if(MapperNo==99)
678 Mirroring=2;
679}
680
681
682static int VSindex;
683
684static DECLFR(VSRead)
685{
686 //printf("$%04x, $%04x\n",A,X.PC);
687 switch(A)
688 {
689 default:
690 case 0x5e00: VSindex=0;return 0xFF;
691 case 0x5e01: return(secptr[(VSindex++)&0x1F]);
692 }
693}
694
695static void DoVSHooks(void)
696{
697 if(secptr)
698 SetReadHandler(0x5e00,0x5e01,VSRead);
699}
700
701void (*MapInitTab[256])(void)=
702{
703 0,
704 Mapper1_init,Mapper2_init,Mapper3_init,Mapper4_init,
705 Mapper5_init,Mapper6_init,Mapper7_init,Mapper8_init,
706 Mapper9_init,Mapper10_init,Mapper11_init,0,
707 Mapper13_init,0,Mapper15_init,Mapper16_init,
708 Mapper17_init,Mapper18_init,Mapper19_init,0,
709 Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init,
710 Mapper25_init,Mapper26_init,0,0,
711 0,0,0,Mapper32_init,
712 Mapper33_init,Mapper34_init,0,0,
713 0,0,0,Mapper40_init,
714 Mapper41_init,Mapper42_init,Mapper43_init,Mapper44_init,
715 Mapper45_init,Mapper46_init,Mapper47_init,Mapper33_init,Mapper49_init,0,Mapper51_init,Mapper52_init,
716 0,0,0,0,0,0,0,0,
717 0,0,0,Mapper64_init,
718 Mapper65_init,Mapper66_init,Mapper67_init,Mapper68_init,
719 Mapper69_init,Mapper70_init,Mapper71_init,Mapper72_init,
720 Mapper73_init,0,Mapper75_init,Mapper76_init,
721 Mapper77_init,Mapper78_init,Mapper79_init,Mapper80_init,
722 0,Mapper82_init,Mapper83_init,0,
723 Mapper85_init,Mapper86_init,Mapper87_init,Mapper88_init,
724 Mapper89_init,Mapper90_init,0,Mapper92_init,
725 Mapper93_init,Mapper94_init,Mapper95_init,Mapper96_init,
726 Mapper97_init,0,Mapper99_init,0,
727 0,0,0,0,Mapper105_init,0,0,0,
728 0,0,0,Mapper112_init,Mapper113_init,0,0,0,
729 Mapper117_init,Mapper118_init,Mapper119_init,0,0,0,0,0,
730 0,0,0,0,0,0,0,0,
731 0,0,0,0,0,0,0,Mapper140_init,
732 0,0,0,0,0,0,0,0,
733 0,0,Mapper151_init,Mapper152_init,Mapper153_init,0,0,0,
734 0,0,0,0,0,0,0,0,
735 0,0,0,0,0,0,0,0,
736 0,0,0,0,0,0,0,Mapper180_init,
737 0,Mapper182_init,0,Mapper184_init,Mapper185_init,0,0,0,
738 Mapper189_init,0,0,0,0,0,0,0,
739 0,0,0,0,0,0,0,0,
740 0,0,0,0,0,0,0,0,
741 0,0,0,0,0,0,0,0,
742 0,0,0,0,Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init,
743 Mapper229_init,0,0,Mapper232_init,0,Mapper234_init,Mapper43_init,0,
744 0,0,0,Mapper240_init,0,Mapper242_init,0,0,
745 Mapper245_init,Mapper246_init,0,Mapper248_init,Mapper249_init,Mapper250_init,0,0,0,0,0
746};
747
748static DECLFW(BWRAM)
749{
750 WRAM[A-0x6000]=V;
751}
752
753static DECLFR(AWRAM)
754{
755 return WRAM[A-0x6000];
756}
757
758void (*MapStateRestore)(int version);
759void iNESStateRestore(int version)
760{
761 int x;
92e249b1 762
c62d2810 763 if(!MapperNo) return;
764
765 for(x=0;x<4;x++)
766 setprg8(0x8000+x*8192,PRGBankList[x]);
767
768 if(VROM_size)
92e249b1 769 for(x=0;x<8;x++)
c62d2810 770 setchr1(0x400*x,CHRBankList[x]);
771
772 switch(Mirroring)
773 {
774 case 0:setmirror(MI_H);break;
775 case 1:setmirror(MI_V);break;
776 case 0x12:
777 case 0x10:setmirror(MI_0);break;
778 case 0x13:
779 case 0x11:setmirror(MI_1);break;
780 }
781 if(MapStateRestore) MapStateRestore(version);
782}
783
784static int MMC_init(int type)
785{
786 int x;
787
788 GameStateRestore=iNESStateRestore;
789 MapClose=0;
790 MapperReset=0;
791 MapStateRestore=0;
792
793 setprg8r(1,0x6000,0);
794
795 SetReadHandler(0x6000,0x7FFF,AWRAM);
796 SetWriteHandler(0x6000,0x7FFF,BWRAM);
797 FCEU_CheatAddRAM(8,0x6000,WRAM);
798
799 /* This statement represents atrocious code. I need to rewrite
800 all of the iNES mapper code... */
801 IRQCount=IRQLatch=IRQa=0;
802 if(head.ROM_type&2)
803 {
804 extern uint8 MMC5WRAMsize,MMC1WRAMsize;
805 if(type==5 && MMC5WRAMsize==4)
806 memset(GameMemBlock+32768,0,sizeof(GameMemBlock)-32768);
807 else if(type==1 && MMC1WRAMsize==2)
808 {
809 memset(GameMemBlock,0,8192);
810 memset(GameMemBlock+16384,0,sizeof(GameMemBlock)-16384);
811 }
812 else
813 memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192);
814 }
815 else
816 memset(GameMemBlock,0,sizeof(GameMemBlock));
817 if(head.ROM_type&4)
818 memcpy(WRAM+4096,trainerpoo,512);
819
820 NONE_init();
821
822 if(FCEUGameInfo.type==GIT_VSUNI)
823 DoVSHooks();
824 if(type==5)
825 {
826 MMC5HackVROMMask=CHRmask4[0];
827 MMC5HackExNTARAMPtr=MapperExRAM+0x6000;
828 MMC5Hack=1;
829 MMC5HackVROMPTR=VROM;
830 MMC5HackCHRMode=0;
831 }
832 ResetExState();
833 AddExState(WRAM, 8192, 0, "WRAM");
834 if(type==19 || type==5 || type==6 || type==69 || type==85)
835 AddExState(MapperExRAM, 32768, 0, "MEXR");
836 if((!VROM_size || type==6 || type==19 || type==119) &&
837 (type!=13 && type!=96))
838 AddExState(CHRRAM, 8192, 0, "CHRR");
839 if(head.ROM_type&8)
840 AddExState(ExtraNTARAM, 2048, 0, "EXNR");
841
92e249b1 842 /* Exclude some mappers whose emulation code handle save state stuff
c62d2810 843 themselves. */
844 if(type && type!=13 && type!=96)
845 {
846 AddExState(mapbyte1, 32, 0, "MPBY");
847 AddExState(&Mirroring, 1, 0, "MIRR");
848 AddExState(&IRQCount, 4, 1, "IRQC");
849 AddExState(&IRQLatch, 4, 1, "IQL1");
850 AddExState(&IRQa, 1, 0, "IRQA");
851 AddExState(PRGBankList, 4, 0, "PBL");
852 for(x=0;x<8;x++)
853 {
854 char tak[8];
92e249b1 855 sprintf(tak,"CBL%d",x);
c62d2810 856 AddExState(&CHRBankList[x], 2, 1,tak);
857 }
858 }
859
860 if(MapInitTab[type]) MapInitTab[type]();
861 else if(type)
862 {
863 FCEU_PrintError("iNES mapper #%d is not supported at all.",type);
864 }
865 return 1;
866}