1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 1998 BERO
\r
5 * Copyright (C) 2002 Xodnizel
\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
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
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
35 #include "general.h"
\r
47 extern SFORMAT FCEUVSUNI_STATEINFO[];
\r
49 static uint8 *trainerpoo=0;
\r
50 static uint8 *ROM=NULL;
\r
54 static CartInfo iNESCart;
\r
56 uint8 iNESMirroring=0;
\r
57 uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0};
\r
58 int32 iNESIRQLatch=0,iNESIRQCount=0;
\r
64 static void iNESPower(void);
\r
65 static int NewiNES_Init(int num);
\r
67 void (*MapClose)(void);
\r
68 void (*MapperReset)(void);
\r
70 static int MapperNo=0;
\r
72 static iNES_HEADER head;
\r
74 /* MapperReset() is called when the NES is reset(with the reset button).
\r
75 Mapperxxx_init is called when the NES has been powered on.
\r
78 static DECLFR(TrainerRead)
\r
80 return(trainerpoo[A&0x1FF]);
\r
83 static void iNESGI(int h)
\r
101 //X6502_DMW(0x7000+x,trainerpoo[x]);
\r
102 //if(X6502_DMR(0x7000+x)!=trainerpoo[x])
\r
103 unsigned int A=0x7000+x;
\r
104 BWrite[A](A,trainerpoo[x]);
\r
105 if(ARead[A](A)!=trainerpoo[x])
\r
107 SetReadHandler(0x7000,0x71FF,TrainerRead);
\r
115 FCEU_SaveGameSave(&iNESCart);
\r
117 if(iNESCart.Close) iNESCart.Close();
\r
118 if(ROM) {free(ROM);ROM=0;}
\r
119 if(VROM) {free(VROM);VROM=0;}
\r
120 if(MapClose) MapClose();
\r
121 if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;}
\r
127 uint32 iNESGameCRC32=0;
\r
141 /* This is mostly for my personal use. So HA. */
\r
142 static void SetInput(void)
\r
144 static struct INPSEL moo[]=
\r
146 {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, /* Nekketsu Kakutou Densetsu */
\r
149 {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* The two "Oeka Kids" games */
\r
150 {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* */
\r
152 {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,-1}, /* World Class Track Meet */
\r
153 {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,-1}, /* Super Team Games */
\r
154 {0x61d86167,SI_GAMEPAD,SI_POWERPADB,-1}, /* Street Cop */
\r
155 {0x6435c095,SI_GAMEPAD,SI_POWERPADB,-1}, /* Short Order/Eggsplode */
\r
158 {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, /* Top Rider */
\r
160 {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, /* Barcode World */
\r
161 {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Super Mogura Tataki!! - Pokkun Moguraa */
\r
162 {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Rairai Kyonshizu */
\r
163 {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Jogging Race */
\r
164 {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Athletic World */
\r
166 {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Totsugeki Fuuun Takeshi Jou */
\r
167 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Running Stadium */
\r
168 {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Meiro Dai Sakusen */
\r
169 // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Fuun Takeshi Jou 2 */
\r
170 {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Dai Undoukai */
\r
171 {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Aerobics Studio */
\r
172 {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Manhattan Police */
\r
173 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Running Stadium */
\r
175 {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... */
\r
176 {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... 2 */
\r
178 {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong 2 */
\r
179 {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong */
\r
181 {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic */
\r
182 {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic (Gentei Ban) */
\r
183 {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Sports */
\r
185 {0xad9c63e2,SI_GAMEPAD,-1,SIFC_SHADOW}, /* Space Shadow */
\r
187 {0x24598791,-1,SI_ZAPPER,0}, /* Duck Hunt */
\r
188 {0xff24d794,-1,SI_ZAPPER,0}, /* Hogan's Alley */
\r
189 {0xbeb8ab01,-1,SI_ZAPPER,0}, /* Gumshoe */
\r
190 {0xde8fd935,-1,SI_ZAPPER,0}, /* To the Earth */
\r
191 {0xedc3662b,-1,SI_ZAPPER,0}, /* Operation Wolf */
\r
192 {0x2a6559a1,-1,SI_ZAPPER,0}, /* Operation Wolf (J) */
\r
194 {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,0}, /* The Lone Ranger */
\r
195 {0xb8b9aca3,-1,SI_ZAPPER,0}, /* Wild Gunman */
\r
196 {0x5112dc21,-1,SI_ZAPPER,0}, /* Wild Gunman */
\r
197 {0x4318a2f8,-1,SI_ZAPPER,0}, /* Barker Bill's Trick Shooting */
\r
198 {0x5ee6008e,-1,SI_ZAPPER,0}, /* Mechanized Attack */
\r
199 {0x3e58a87e,-1,SI_ZAPPER,0}, /* Freedom Force */
\r
200 {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,0}, /* Shooting Range */
\r
201 {0x74bea652,SI_GAMEPAD,SI_ZAPPER,0}, /* Supergun 3-in-1 */
\r
202 {0x32fb0583,-1,SI_ARKANOID,0}, /* Arkanoid(NES) */
\r
203 {0xd89e5a67,-1,-1,SIFC_ARKANOID}, /* Arkanoid (J) */
\r
204 {0x0f141525,-1,-1,SIFC_ARKANOID}, /* Arkanoid 2(J) */
\r
206 {0x912989dc,-1,-1,SIFC_FKB}, /* Playbox BASIC */
\r
207 {0xf7606810,-1,-1,SIFC_FKB}, /* Family BASIC 2.0A */
\r
208 {0x895037bc,-1,-1,SIFC_FKB}, /* Family BASIC 2.1a */
\r
209 {0xb2530afc,-1,-1,SIFC_FKB}, /* Family BASIC 3.0 */
\r
211 {0x82f1fb96,-1,-1,SIFC_SUBORKB}, /* Subor 1.0 Russian */
\r
212 {0xabb2f974,-1,-1,SIFC_SUBORKB}, /* Study and Game 32-in-1 */
\r
213 {0xd5d6eac4,-1,-1,SIFC_SUBORKB}, /* Edu (As) */
\r
214 {0x589b6b0d,-1,-1,SIFC_SUBORKB}, /* SuporV20 */
\r
215 {0x5e073a1b,-1,-1,SIFC_SUBORKB}, /* Supor English (Chinese) */
\r
216 {0x8b265862,-1,-1,SIFC_SUBORKB},
\r
217 {0x41401c6d,-1,-1,SIFC_SUBORKB}, /* SuporV40 */
\r
218 {0x41ef9ac4,-1,-1,SIFC_SUBORKB},
\r
219 {0x368c19a8,-1,-1,SIFC_SUBORKB}, /* LIKO Study Cartridge */
\r
220 {0x543ab532,-1,-1,SIFC_SUBORKB}, /* LIKO Color Lines */
\r
226 while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0)
\r
228 if(moo[x].crc32==iNESGameCRC32)
\r
230 FCEUGameInfo.input[0]=moo[x].input1;
\r
231 FCEUGameInfo.input[1]=moo[x].input2;
\r
232 FCEUGameInfo.inputfc=moo[x].inputfc;
\r
239 #define INESB_INCOMPLETE 1
\r
240 #define INESB_CORRUPT 2
\r
241 #define INESB_HACKED 4
\r
250 static struct BADINF BadROMImages[]=
\r
252 #include "ines-bad.h"
\r
255 void CheckBad(uint64 md5partial)
\r
260 //printf("0x%llx\n",md5partial);
\r
261 while(BadROMImages[x].name)
\r
263 if(BadROMImages[x].md5partial == md5partial)
\r
265 FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly on FCE Ultra.", BadROMImages[x].name);
\r
280 static void CheckHInfo(void)
\r
282 /* ROM images that have the battery-backed bit set in the header that really
\r
283 don't have battery-backed RAM is not that big of a problem, so I'll
\r
284 treat this differently by only listing games that should have battery-backed RAM.
\r
286 Lower 64 bits of the MD5 hash.
\r
289 static uint64 savie[]=
\r
291 0x498c10dc463cfe95LL, /* Battle Fleet */
\r
292 0x6917ffcaca2d8466LL, /* Famista '90 */
\r
294 0xd63dcc68c2b20adcLL, /* Final Fantasy J */
\r
295 0x012df596e2b31174LL, /* Final Fantasy 1+2 */
\r
296 0xf6b359a720549ecdLL, /* Final Fantasy 2 */
\r
297 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */
\r
299 0x2ee3417ba8b69706LL, /* Hydlide 3*/
\r
301 0xebbce5a54cf3ecc0LL, /* Justbreed */
\r
303 0x6a858da551ba239eLL, /* Kaijuu Monogatari */
\r
304 0xa40666740b7d22feLL, /* Mindseeker */
\r
306 0x77b811b2760104b9LL, /* Mouryou Senki Madara */
\r
308 0x11b69122efe86e8cLL, /* RPG Jinsei Game */
\r
310 0xa70b495314f4d075LL, /* Ys 3 */
\r
313 0xc04361e499748382LL, /* AD&D Heroes of the Lance */
\r
314 0xb72ee2337ced5792LL, /* AD&D Hillsfar */
\r
315 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */
\r
317 0x854d7947a3177f57LL, /* Crystalis */
\r
319 0xb0bcc02c843c1b79LL, /* DW */
\r
320 0x4a1f5336b86851b6LL, /* DW */
\r
322 0x2dcf3a98c7937c22LL, /* DW 2 */
\r
323 0x733026b6b72f2470LL, /* Dw 3 */
\r
324 0x98e55e09dfcc7533LL, /* DW 4*/
\r
325 0x8da46db592a1fcf4LL, /* Faria */
\r
326 0x91a6846d3202e3d6LL, /* Final Fantasy */
\r
327 0xedba17a2c4608d20LL, /* "" */
\r
329 0x94b9484862a26cbaLL, /* Legend of Zelda */
\r
330 0x04a31647de80fdabLL, /* "" */
\r
332 0x9aa1dc16c05e7de5LL, /* Startropics */
\r
333 0x1b084107d0878bd0LL, /* Startropics 2*/
\r
335 0x836c0ff4f3e06e45LL, /* Zelda 2 */
\r
337 0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */
\r
340 static struct CHINF moo[]=
\r
342 #include "ines-correct.h"
\r
346 uint64 partialmd5=0;
\r
350 partialmd5 |= (uint64)iNESCart.MD5[15-x] << (x*8);
\r
351 //printf("%16llx\n",partialmd5);
\r
353 CheckBad(partialmd5);
\r
359 if(moo[x].crc32==iNESGameCRC32)
\r
361 if(moo[x].mapper>=0)
\r
363 if(moo[x].mapper&0x800 && VROM_size)
\r
370 if(MapperNo!=(moo[x].mapper&0xFF))
\r
373 MapperNo=moo[x].mapper&0xFF;
\r
376 if(moo[x].mirror>=0)
\r
378 if(moo[x].mirror==8)
\r
380 if(Mirroring==2) /* Anything but hard-wired(four screen). */
\r
386 else if(Mirroring!=moo[x].mirror)
\r
388 if(Mirroring!=(moo[x].mirror&~4))
\r
389 if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring
\r
390 needs to be set(the iNES header can't
\r
391 hold this information).
\r
394 Mirroring=moo[x].mirror;
\r
400 } while(moo[x].mirror>=0 || moo[x].mapper>=0);
\r
403 while(savie[x] != 0)
\r
405 if(savie[x] == partialmd5)
\r
407 if(!(head.ROM_type&2))
\r
416 /* Games that use these iNES mappers tend to have the four-screen bit set
\r
417 when it should not be.
\r
419 if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2))
\r
425 /* Four-screen mirroring implicitly set. */
\r
432 strcpy(gigastr,"The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
\r
434 sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d. ",MapperNo);
\r
437 char *mstr[3]={"Horizontal","Vertical","Four-screen"};
\r
438 sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]);
\r
441 strcat(gigastr,"The battery-backed bit should be set. ");
\r
443 strcat(gigastr,"This game should not have any CHR ROM. ");
\r
444 strcat(gigastr,"\n");
\r
445 FCEU_printf("%s",gigastr);
\r
451 void (*init)(CartInfo *);
\r
454 int iNESLoad(const char *name, int fp)
\r
456 struct md5_context md5;
\r
458 if(FCEU_fread(&head,1,16,fp)!=16)
\r
461 if(memcmp(&head,"NES\x1a",4))
\r
464 memset(&iNESCart,0,sizeof(iNESCart));
\r
466 if(!memcmp((char *)(&head)+0x7,"DiskDude",8))
\r
468 memset((char *)(&head)+0x7,0,0x9);
\r
471 if(!memcmp((char *)(&head)+0x7,"demiforce",9))
\r
473 memset((char *)(&head)+0x7,0,0x9);
\r
476 if(!memcmp((char *)(&head)+0xA,"Ni03",4))
\r
478 if(!memcmp((char *)(&head)+0x7,"Dis",3))
\r
479 memset((char *)(&head)+0x7,0,0x9);
\r
481 memset((char *)(&head)+0xA,0,0x6);
\r
487 // FCEU_PrintError("No PRG ROM!");
\r
493 ROM_size=head.ROM_size;
\r
495 // ROM_size = head.ROM_size;
\r
496 VROM_size = head.VROM_size;
\r
497 ROM_size=uppow2(ROM_size);
\r
500 VROM_size=uppow2(VROM_size);
\r
502 MapperNo = (head.ROM_type>>4);
\r
503 MapperNo|=(head.ROM_type2&0xF0);
\r
504 Mirroring = (head.ROM_type&1);
\r
506 if(head.ROM_type&8) Mirroring=2;
\r
508 if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
\r
512 if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
\r
518 memset(ROM,0xFF,ROM_size<<14);
\r
519 if(VROM_size) memset(VROM,0xFF,VROM_size<<13);
\r
520 if(head.ROM_type&4) /* Trainer */
\r
522 trainerpoo=(uint8 *)FCEU_gmalloc(512);
\r
523 FCEU_fread(trainerpoo,512,1,fp);
\r
526 ResetCartMapping();
\r
529 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);
\r
530 SetupCartPRGMapping(1,WRAM,8192,1);
\r
532 FCEU_fread(ROM,0x4000,head.ROM_size,fp);
\r
535 FCEU_fread(VROM,0x2000,head.VROM_size,fp);
\r
538 md5_update(&md5,ROM,ROM_size<<14);
\r
540 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);
\r
544 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);
\r
545 md5_update(&md5,VROM,VROM_size<<13);
\r
547 md5_finish(&md5,iNESCart.MD5);
\r
548 memcpy(FCEUGameInfo.MD5,iNESCart.MD5,sizeof(iNESCart.MD5));
\r
550 iNESCart.CRC32=iNESGameCRC32;
\r
552 FCEU_printf(" PRG ROM: %3d x 16KiB\n CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08lx\n",
\r
553 head.ROM_size,head.VROM_size,iNESGameCRC32);
\r
557 FCEU_printf(" ROM MD5: 0x");
\r
559 FCEU_printf("%02x",iNESCart.MD5[x]);
\r
562 FCEU_printf(" Mapper: %d\n Mirroring: %s\n", MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal");
\r
563 if(head.ROM_type&2) FCEU_printf(" Battery-backed.\n");
\r
564 if(head.ROM_type&4) FCEU_printf(" Trained.\n");
\r
570 uint64 partialmd5=0;
\r
574 partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);
\r
577 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
\r
579 /* Must remain here because above functions might change value of
\r
580 VROM_size and free(VROM).
\r
583 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);
\r
586 SetupCartMirroring(4,1,ExtraNTARAM);
\r
587 else if(Mirroring>=0x10)
\r
588 SetupCartMirroring(2+(Mirroring&1),1,0);
\r
590 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);
\r
592 iNESCart.battery=(head.ROM_type&2)?1:0;
\r
593 iNESCart.mirror=Mirroring;
\r
595 //if(MapperNo != 18) {
\r
596 // if(ROM) free(ROM);
\r
597 // if(VROM) free(VROM);
\r
602 if(NewiNES_Init(MapperNo))
\r
608 iNESCart.Power=iNESPower;
\r
609 if(head.ROM_type&2)
\r
611 iNESCart.SaveGame[0]=WRAM;
\r
612 iNESCart.SaveGameLen[0]=8192;
\r
615 FCEU_LoadGameSave(&iNESCart);
\r
617 GameInterface=iNESGI;
\r
620 // since apparently the iNES format doesn't store this information,
\r
621 // guess if the settings should be PAL or NTSC from the ROM name
\r
622 // TODO: MD5 check against a list of all known PAL games instead?
\r
623 if(strstr(name,"(E)") || strstr(name,"(e)")
\r
624 || strstr(name,"(F)") || strstr(name,"(f)")
\r
625 || strstr(name,"(G)") || strstr(name,"(g)")
\r
626 || strstr(name,"(I)") || strstr(name,"(i)"))
\r
627 FCEUI_SetVidSystem(1);
\r
629 FCEUI_SetVidSystem(0);
\r
634 void FASTAPASS(2) VRAM_BANK1(uint32 A, uint8 V)
\r
637 PPUCHRRAM|=(1<<(A>>10));
\r
638 CHRBankList[(A)>>10]=V;
\r
639 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
\r
642 void FASTAPASS(2) VRAM_BANK4(uint32 A, uint32 V)
\r
645 PPUCHRRAM|=(0xF<<(A>>10));
\r
646 CHRBankList[(A)>>10]=(V<<2);
\r
647 CHRBankList[((A)>>10)+1]=(V<<2)+1;
\r
648 CHRBankList[((A)>>10)+2]=(V<<2)+2;
\r
649 CHRBankList[((A)>>10)+3]=(V<<2)+3;
\r
650 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
\r
652 void FASTAPASS(2) VROM_BANK1(uint32 A,uint32 V)
\r
655 CHRBankList[(A)>>10]=V;
\r
658 void FASTAPASS(2) VROM_BANK2(uint32 A,uint32 V)
\r
661 CHRBankList[(A)>>10]=(V<<1);
\r
662 CHRBankList[((A)>>10)+1]=(V<<1)+1;
\r
665 void FASTAPASS(2) VROM_BANK4(uint32 A, uint32 V)
\r
668 CHRBankList[(A)>>10]=(V<<2);
\r
669 CHRBankList[((A)>>10)+1]=(V<<2)+1;
\r
670 CHRBankList[((A)>>10)+2]=(V<<2)+2;
\r
671 CHRBankList[((A)>>10)+3]=(V<<2)+3;
\r
674 void FASTAPASS(1) VROM_BANK8(uint32 V)
\r
677 CHRBankList[0]=(V<<3);
\r
678 CHRBankList[1]=(V<<3)+1;
\r
679 CHRBankList[2]=(V<<3)+2;
\r
680 CHRBankList[3]=(V<<3)+3;
\r
681 CHRBankList[4]=(V<<3)+4;
\r
682 CHRBankList[5]=(V<<3)+5;
\r
683 CHRBankList[6]=(V<<3)+6;
\r
684 CHRBankList[7]=(V<<3)+7;
\r
687 void FASTAPASS(2) ROM_BANK8(uint32 A, uint32 V)
\r
691 PRGBankList[((A-0x8000)>>13)]=V;
\r
694 void FASTAPASS(2) ROM_BANK16(uint32 A, uint32 V)
\r
699 PRGBankList[((A-0x8000)>>13)]=V<<1;
\r
700 PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1;
\r
704 void FASTAPASS(1) ROM_BANK32(uint32 V)
\r
706 setprg32(0x8000,V);
\r
707 PRGBankList[0]=V<<2;
\r
708 PRGBankList[1]=(V<<2)+1;
\r
709 PRGBankList[2]=(V<<2)+2;
\r
710 PRGBankList[3]=(V<<2)+3;
\r
713 void FASTAPASS(1) onemir(uint8 V)
\r
715 if(Mirroring==2) return;
\r
722 void FASTAPASS(1) MIRROR_SET2(uint8 V)
\r
724 if(Mirroring==2) return;
\r
729 void FASTAPASS(1) MIRROR_SET(uint8 V)
\r
731 if(Mirroring==2) return;
\r
737 static void NONE_init(void)
\r
739 ROM_BANK16(0x8000,0);
\r
740 ROM_BANK16(0xC000,~0);
\r
748 void (*MapInitTab[256])(void)=
\r
751 // Mapper2_init,Mapper3_init,
\r
754 Mapper6_init,Mapper7_init,Mapper8_init,Mapper9_init,
\r
755 Mapper10_init,Mapper11_init,
\r
760 Mapper15_init,Mapper16_init,Mapper17_init,Mapper18_init,
\r
762 Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init,
\r
763 Mapper25_init,Mapper26_init,Mapper27_init,
\r
765 Mapper32_init,Mapper33_init,Mapper34_init,
\r
767 Mapper40_init,Mapper41_init,Mapper42_init,Mapper43_init,
\r
773 Mapper50_init,Mapper51_init,
\r
775 Mapper57_init,Mapper58_init,Mapper59_init,Mapper60_init,
\r
776 Mapper61_init,Mapper62_init,
\r
778 Mapper64_init,Mapper65_init,Mapper66_init,Mapper67_init,
\r
779 Mapper68_init,Mapper69_init,Mapper70_init,Mapper71_init,
\r
780 Mapper72_init,Mapper73_init,
\r
782 Mapper75_init,Mapper76_init,Mapper77_init,Mapper78_init,
\r
783 Mapper79_init,Mapper80_init,
\r
785 Mapper82_init,Mapper83_init,
\r
787 Mapper85_init,Mapper86_init,Mapper87_init,Mapper88_init,
\r
790 Mapper91_init,Mapper92_init,Mapper93_init,Mapper94_init,
\r
792 Mapper96_init,Mapper97_init,
\r
801 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
806 Mapper151_init,Mapper152_init,Mapper153_init,Mapper154_init,
\r
808 Mapper156_init,Mapper157_init,Mapper158_init,0,
\r
810 Mapper166_init,Mapper167_init,
\r
811 0,0,0,0,0,0,0,0,0,0,0,0,
\r
814 Mapper184_init,Mapper185_init,
\r
823 Mapper200_init,Mapper201_init,Mapper202_init,Mapper203_init,
\r
828 Mapper211_init,Mapper212_init,Mapper213_init,Mapper214_init,
\r
829 0,0,0,0,0,0,0,0,0,0,
\r
830 Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init,
\r
831 Mapper229_init,Mapper230_init,Mapper231_init,Mapper232_init,
\r
833 Mapper234_init,Mapper235_init,
\r
835 Mapper240_init,Mapper241_init,Mapper242_init,0,
\r
843 static DECLFW(BWRAM)
\r
848 static DECLFR(AWRAM)
\r
850 return WRAM[A-0x6000];
\r
853 #ifdef DEBUG_MAPPER
\r
854 static DECLFW(WriteHandler)
\r
856 FCEU_printf("$%04x:$%02x\n",A,V);
\r
860 void (*MapStateRestore)(int version);
\r
861 void iNESStateRestore(int version)
\r
865 if(!MapperNo) return;
\r
868 setprg8(0x8000+x*8192,PRGBankList[x]);
\r
872 setchr1(0x400*x,CHRBankList[x]);
\r
874 if(0) switch(Mirroring)
\r
876 case 0:setmirror(MI_H);break;
\r
877 case 1:setmirror(MI_V);break;
\r
879 case 0x10:setmirror(MI_0);break;
\r
881 case 0x11:setmirror(MI_1);break;
\r
883 if(MapStateRestore) MapStateRestore(version);
\r
886 static void iNESPower(void)
\r
891 SetReadHandler(0x8000,0xFFFF,CartBR);
\r
892 GameStateRestore=iNESStateRestore;
\r
897 setprg8r(1,0x6000,0);
\r
899 SetReadHandler(0x6000,0x7FFF,AWRAM);
\r
900 SetWriteHandler(0x6000,0x7FFF,BWRAM);
\r
901 FCEU_CheatAddRAM(8,0x6000,WRAM);
\r
903 #ifdef DEBUG_MAPPER
\r
904 if(type==0) SetWriteHandler(0x4020,0xFFFF,WriteHandler);
\r
907 /* This statement represents atrocious code. I need to rewrite
\r
908 all of the iNES mapper code... */
\r
909 IRQCount=IRQLatch=IRQa=0;
\r
910 if(head.ROM_type&2)
\r
911 memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192);
\r
913 memset(GameMemBlock,0,sizeof(GameMemBlock));
\r
918 if(FCEUGameInfo.type == GIT_VSUNI)
\r
919 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
\r
921 AddExState(WRAM, 8192, 0, "WRAM");
\r
922 if(type==19 || type==6 || type==69 || type==85 || type==96)
\r
923 AddExState(MapperExRAM, 32768, 0, "MEXR");
\r
924 if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96))
\r
925 AddExState(CHRRAM, 8192, 0, "CHRR");
\r
926 if(head.ROM_type&8)
\r
927 AddExState(ExtraNTARAM, 2048, 0, "EXNR");
\r
929 /* Exclude some mappers whose emulation code handle save state stuff
\r
931 if(type && type!=13 && type!=96)
\r
933 AddExState(mapbyte1, 32, 0, "MPBY");
\r
934 AddExState(&Mirroring, 1, 0, "MIRR");
\r
935 AddExState(&IRQCount, 4, 1, "IRQC");
\r
936 AddExState(&IRQLatch, 4, 1, "IQL1");
\r
937 AddExState(&IRQa, 1, 0, "IRQA");
\r
938 AddExState(PRGBankList, 4, 0, "PBL");
\r
942 sprintf(tak,"CBL%d",x);
\r
943 AddExState(&CHRBankList[x], 2, 1,tak);
\r
947 if(MapInitTab[type]) MapInitTab[type]();
\r
950 FCEU_PrintError("iNES mapper #%d is not supported at all.",type);
\r
957 void (*init)(CartInfo *);
\r
960 static BMAPPING bmap[] = {
\r
966 {12, Mapper12_Init},
\r
968 {19, Mapper19_Init},
\r
969 {44, Mapper44_Init},
\r
970 {45, Mapper45_Init},
\r
971 {47, Mapper47_Init},
\r
972 {49, Mapper49_Init},
\r
973 {52, Mapper52_Init},
\r
974 {74, Mapper74_Init},
\r
975 {90, Mapper90_Init},
\r
976 {95, Mapper95_Init},
\r
977 {105, Mapper105_Init},
\r
978 {112, Mapper112_Init},
\r
979 {114, Mapper114_Init},
\r
980 {115, Mapper115_Init},
\r
981 {116, Mapper116_Init},
\r
982 {118, Mapper118_Init},
\r
983 {119, Mapper119_Init},
\r
984 {133, SA72008_Init},
\r
985 {137, S8259D_Init},
\r
986 {138, S8259B_Init},
\r
987 {139, S8259C_Init},
\r
988 {141, S8259A_Init},
\r
990 {145, SA72007_Init},
\r
991 {146, SA0161M_Init},
\r
993 {148, SA0037_Init},
\r
994 {149, SA0036_Init},
\r
995 {150, S74LS374N_Init},
\r
996 {155, Mapper155_Init},
\r
997 {160, Mapper90_Init},
\r
998 {163, Mapper163_Init},
\r
999 {164, Mapper164_Init},
\r
1000 {165, Mapper165_Init},
\r
1001 {182, Mapper182_Init},
\r
1002 {183, Mapper183_Init},
\r
1003 {186, Mapper186_Init},
\r
1004 {187, Mapper187_Init},
\r
1005 {188, Mapper188_Init},
\r
1006 {191, Mapper191_Init},
\r
1007 {205, Mapper205_Init},
\r
1008 {206, DEIROM_Init},
\r
1009 {208, Mapper208_Init},
\r
1010 {209, Mapper209_Init},
\r
1011 {210, Mapper210_Init},
\r
1012 {215, Mapper215_Init},
\r
1013 {216, Mapper216_Init},
\r
1014 {217, Mapper217_Init},
\r
1015 {243, S74LS374NA_Init},
\r
1016 {245, Mapper245_Init},
\r
1017 {249, Mapper249_Init},
\r
1018 {250, Mapper250_Init},
\r
1019 {254, Mapper254_Init},
\r
1023 static int NewiNES_Init(int num)
\r
1025 BMAPPING *tmp=bmap;
\r
1027 if(FCEUGameInfo.type == GIT_VSUNI)
\r
1028 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
\r
1032 if(num==tmp->number)
\r
1034 UNIFchrrama=0; // need here for compatibility with UNIF mapper code
\r
1042 VROM=(uint8 *)malloc(CHRRAMSize);
\r
1044 SetupCartCHRMapping(0,VROM,CHRRAMSize,1);
\r
1045 AddExState(VROM,CHRRAMSize, 0, "CHRR");
\r
1047 if(head.ROM_type&8)
\r
1048 AddExState(ExtraNTARAM, 2048, 0, "EXNR");
\r
1049 tmp->init(&iNESCart);
\r