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, void *param)
\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
124 case GI_INFOSTRING:
\r
127 MapperNo = (head.ROM_type>>4);
\r
128 MapperNo|=(head.ROM_type2&0xF0);
\r
129 sprintf(param, "iNES, %s, Mapper: %d%s%s", PAL?"PAL":"NTSC",
\r
130 MapperNo, (head.ROM_type&2)?", BB":"", (head.ROM_type&4)?", T":"");
\r
136 uint32 iNESGameCRC32=0;
\r
150 /* This is mostly for my personal use. So HA. */
\r
151 static void SetInput(void)
\r
153 static struct INPSEL moo[]=
\r
155 {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, /* Nekketsu Kakutou Densetsu */
\r
158 {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* The two "Oeka Kids" games */
\r
159 {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* */
\r
161 {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,-1}, /* World Class Track Meet */
\r
162 {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,-1}, /* Super Team Games */
\r
163 {0x61d86167,SI_GAMEPAD,SI_POWERPADB,-1}, /* Street Cop */
\r
164 {0x6435c095,SI_GAMEPAD,SI_POWERPADB,-1}, /* Short Order/Eggsplode */
\r
167 {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, /* Top Rider */
\r
169 {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, /* Barcode World */
\r
170 {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Super Mogura Tataki!! - Pokkun Moguraa */
\r
171 {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Rairai Kyonshizu */
\r
172 {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Jogging Race */
\r
173 {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Athletic World */
\r
175 {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Totsugeki Fuuun Takeshi Jou */
\r
176 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Running Stadium */
\r
177 {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Meiro Dai Sakusen */
\r
178 // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Fuun Takeshi Jou 2 */
\r
179 {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Dai Undoukai */
\r
180 {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Aerobics Studio */
\r
181 {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Manhattan Police */
\r
182 {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Running Stadium */
\r
184 {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... */
\r
185 {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... 2 */
\r
187 {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong 2 */
\r
188 {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong */
\r
190 {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic */
\r
191 {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic (Gentei Ban) */
\r
192 {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Sports */
\r
194 {0xad9c63e2,SI_GAMEPAD,-1,SIFC_SHADOW}, /* Space Shadow */
\r
196 {0x24598791,-1,SI_ZAPPER,0}, /* Duck Hunt */
\r
197 {0xff24d794,-1,SI_ZAPPER,0}, /* Hogan's Alley */
\r
198 {0xbeb8ab01,-1,SI_ZAPPER,0}, /* Gumshoe */
\r
199 {0xde8fd935,-1,SI_ZAPPER,0}, /* To the Earth */
\r
200 {0xedc3662b,-1,SI_ZAPPER,0}, /* Operation Wolf */
\r
201 {0x2a6559a1,-1,SI_ZAPPER,0}, /* Operation Wolf (J) */
\r
203 {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,0}, /* The Lone Ranger */
\r
204 {0xb8b9aca3,-1,SI_ZAPPER,0}, /* Wild Gunman */
\r
205 {0x5112dc21,-1,SI_ZAPPER,0}, /* Wild Gunman */
\r
206 {0x4318a2f8,-1,SI_ZAPPER,0}, /* Barker Bill's Trick Shooting */
\r
207 {0x5ee6008e,-1,SI_ZAPPER,0}, /* Mechanized Attack */
\r
208 {0x3e58a87e,-1,SI_ZAPPER,0}, /* Freedom Force */
\r
209 {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,0}, /* Shooting Range */
\r
210 {0x74bea652,SI_GAMEPAD,SI_ZAPPER,0}, /* Supergun 3-in-1 */
\r
211 {0x32fb0583,-1,SI_ARKANOID,0}, /* Arkanoid(NES) */
\r
212 {0xd89e5a67,-1,-1,SIFC_ARKANOID}, /* Arkanoid (J) */
\r
213 {0x0f141525,-1,-1,SIFC_ARKANOID}, /* Arkanoid 2(J) */
\r
215 {0x912989dc,-1,-1,SIFC_FKB}, /* Playbox BASIC */
\r
216 {0xf7606810,-1,-1,SIFC_FKB}, /* Family BASIC 2.0A */
\r
217 {0x895037bc,-1,-1,SIFC_FKB}, /* Family BASIC 2.1a */
\r
218 {0xb2530afc,-1,-1,SIFC_FKB}, /* Family BASIC 3.0 */
\r
220 {0x82f1fb96,-1,-1,SIFC_SUBORKB}, /* Subor 1.0 Russian */
\r
221 {0xabb2f974,-1,-1,SIFC_SUBORKB}, /* Study and Game 32-in-1 */
\r
222 {0xd5d6eac4,-1,-1,SIFC_SUBORKB}, /* Edu (As) */
\r
223 {0x589b6b0d,-1,-1,SIFC_SUBORKB}, /* SuporV20 */
\r
224 {0x5e073a1b,-1,-1,SIFC_SUBORKB}, /* Supor English (Chinese) */
\r
225 {0x8b265862,-1,-1,SIFC_SUBORKB},
\r
226 {0x41401c6d,-1,-1,SIFC_SUBORKB}, /* SuporV40 */
\r
227 {0x41ef9ac4,-1,-1,SIFC_SUBORKB},
\r
228 {0x368c19a8,-1,-1,SIFC_SUBORKB}, /* LIKO Study Cartridge */
\r
229 {0x543ab532,-1,-1,SIFC_SUBORKB}, /* LIKO Color Lines */
\r
235 while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0)
\r
237 if(moo[x].crc32==iNESGameCRC32)
\r
239 FCEUGameInfo.input[0]=moo[x].input1;
\r
240 FCEUGameInfo.input[1]=moo[x].input2;
\r
241 FCEUGameInfo.inputfc=moo[x].inputfc;
\r
248 #define INESB_INCOMPLETE 1
\r
249 #define INESB_CORRUPT 2
\r
250 #define INESB_HACKED 4
\r
259 static struct BADINF BadROMImages[]=
\r
261 #include "ines-bad.h"
\r
264 void CheckBad(uint64 md5partial)
\r
269 //printf("0x%llx\n",md5partial);
\r
270 while(BadROMImages[x].name)
\r
272 if(BadROMImages[x].md5partial == md5partial)
\r
274 FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly on FCE Ultra.", BadROMImages[x].name);
\r
289 static void CheckHInfo(void)
\r
291 /* ROM images that have the battery-backed bit set in the header that really
\r
292 don't have battery-backed RAM is not that big of a problem, so I'll
\r
293 treat this differently by only listing games that should have battery-backed RAM.
\r
295 Lower 64 bits of the MD5 hash.
\r
298 static uint64 savie[]=
\r
300 0x498c10dc463cfe95LL, /* Battle Fleet */
\r
301 0x6917ffcaca2d8466LL, /* Famista '90 */
\r
303 0xd63dcc68c2b20adcLL, /* Final Fantasy J */
\r
304 0x012df596e2b31174LL, /* Final Fantasy 1+2 */
\r
305 0xf6b359a720549ecdLL, /* Final Fantasy 2 */
\r
306 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */
\r
308 0x2ee3417ba8b69706LL, /* Hydlide 3*/
\r
310 0xebbce5a54cf3ecc0LL, /* Justbreed */
\r
312 0x6a858da551ba239eLL, /* Kaijuu Monogatari */
\r
313 0xa40666740b7d22feLL, /* Mindseeker */
\r
315 0x77b811b2760104b9LL, /* Mouryou Senki Madara */
\r
317 0x11b69122efe86e8cLL, /* RPG Jinsei Game */
\r
319 0xa70b495314f4d075LL, /* Ys 3 */
\r
322 0xc04361e499748382LL, /* AD&D Heroes of the Lance */
\r
323 0xb72ee2337ced5792LL, /* AD&D Hillsfar */
\r
324 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */
\r
326 0x854d7947a3177f57LL, /* Crystalis */
\r
328 0xb0bcc02c843c1b79LL, /* DW */
\r
329 0x4a1f5336b86851b6LL, /* DW */
\r
331 0x2dcf3a98c7937c22LL, /* DW 2 */
\r
332 0x733026b6b72f2470LL, /* Dw 3 */
\r
333 0x98e55e09dfcc7533LL, /* DW 4*/
\r
334 0x8da46db592a1fcf4LL, /* Faria */
\r
335 0x91a6846d3202e3d6LL, /* Final Fantasy */
\r
336 0xedba17a2c4608d20LL, /* "" */
\r
338 0x94b9484862a26cbaLL, /* Legend of Zelda */
\r
339 0x04a31647de80fdabLL, /* "" */
\r
341 0x9aa1dc16c05e7de5LL, /* Startropics */
\r
342 0x1b084107d0878bd0LL, /* Startropics 2*/
\r
344 0x836c0ff4f3e06e45LL, /* Zelda 2 */
\r
346 0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */
\r
349 static struct CHINF moo[]=
\r
351 #include "ines-correct.h"
\r
355 uint64 partialmd5=0;
\r
359 partialmd5 |= (uint64)iNESCart.MD5[15-x] << (x*8);
\r
360 //printf("%16llx\n",partialmd5);
\r
362 CheckBad(partialmd5);
\r
368 if(moo[x].crc32==iNESGameCRC32)
\r
370 if(moo[x].mapper>=0)
\r
372 if(moo[x].mapper&0x800 && VROM_size)
\r
379 if(MapperNo!=(moo[x].mapper&0xFF))
\r
382 MapperNo=moo[x].mapper&0xFF;
\r
385 if(moo[x].mirror>=0)
\r
387 if(moo[x].mirror==8)
\r
389 if(Mirroring==2) /* Anything but hard-wired(four screen). */
\r
395 else if(Mirroring!=moo[x].mirror)
\r
397 if(Mirroring!=(moo[x].mirror&~4))
\r
398 if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring
\r
399 needs to be set(the iNES header can't
\r
400 hold this information).
\r
403 Mirroring=moo[x].mirror;
\r
409 } while(moo[x].mirror>=0 || moo[x].mapper>=0);
\r
412 while(savie[x] != 0)
\r
414 if(savie[x] == partialmd5)
\r
416 if(!(head.ROM_type&2))
\r
425 /* Games that use these iNES mappers tend to have the four-screen bit set
\r
426 when it should not be.
\r
428 if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2))
\r
434 /* Four-screen mirroring implicitly set. */
\r
441 strcpy(gigastr,"The iNES header contains incorrect information. For now, the information will be corrected in RAM. ");
\r
443 sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d. ",MapperNo);
\r
446 char *mstr[3]={"Horizontal","Vertical","Four-screen"};
\r
447 sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]);
\r
450 strcat(gigastr,"The battery-backed bit should be set. ");
\r
452 strcat(gigastr,"This game should not have any CHR ROM. ");
\r
453 strcat(gigastr,"\n");
\r
454 FCEU_printf("%s",gigastr);
\r
460 void (*init)(CartInfo *);
\r
463 int iNESLoad(const char *name, int fp)
\r
465 struct md5_context md5;
\r
467 if(FCEU_fread(&head,1,16,fp)!=16)
\r
470 if(memcmp(&head,"NES\x1a",4))
\r
473 memset(&iNESCart,0,sizeof(iNESCart));
\r
475 if(!memcmp((char *)(&head)+0x7,"DiskDude",8))
\r
477 memset((char *)(&head)+0x7,0,0x9);
\r
480 if(!memcmp((char *)(&head)+0x7,"demiforce",9))
\r
482 memset((char *)(&head)+0x7,0,0x9);
\r
485 if(!memcmp((char *)(&head)+0xA,"Ni03",4))
\r
487 if(!memcmp((char *)(&head)+0x7,"Dis",3))
\r
488 memset((char *)(&head)+0x7,0,0x9);
\r
490 memset((char *)(&head)+0xA,0,0x6);
\r
496 // FCEU_PrintError("No PRG ROM!");
\r
502 ROM_size=head.ROM_size;
\r
504 // ROM_size = head.ROM_size;
\r
505 VROM_size = head.VROM_size;
\r
506 ROM_size=uppow2(ROM_size);
\r
509 VROM_size=uppow2(VROM_size);
\r
511 MapperNo = (head.ROM_type>>4);
\r
512 MapperNo|=(head.ROM_type2&0xF0);
\r
513 Mirroring = (head.ROM_type&1);
\r
515 if(head.ROM_type&8) Mirroring=2;
\r
517 if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
\r
521 if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
\r
527 memset(ROM,0xFF,ROM_size<<14);
\r
528 if(VROM_size) memset(VROM,0xFF,VROM_size<<13);
\r
529 if(head.ROM_type&4) /* Trainer */
\r
531 trainerpoo=(uint8 *)FCEU_gmalloc(512);
\r
532 FCEU_fread(trainerpoo,512,1,fp);
\r
535 ResetCartMapping();
\r
538 SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0);
\r
539 SetupCartPRGMapping(1,WRAM,8192,1);
\r
541 FCEU_fread(ROM,0x4000,head.ROM_size,fp);
\r
544 FCEU_fread(VROM,0x2000,head.VROM_size,fp);
\r
547 md5_update(&md5,ROM,ROM_size<<14);
\r
549 iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14);
\r
553 iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13);
\r
554 md5_update(&md5,VROM,VROM_size<<13);
\r
556 md5_finish(&md5,iNESCart.MD5);
\r
557 memcpy(FCEUGameInfo.MD5,iNESCart.MD5,sizeof(iNESCart.MD5));
\r
559 iNESCart.CRC32=iNESGameCRC32;
\r
561 FCEU_printf(" PRG ROM: %3d x 16KiB\n CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08x\n",
\r
562 head.ROM_size,head.VROM_size,iNESGameCRC32);
\r
566 FCEU_printf(" ROM MD5: 0x");
\r
568 FCEU_printf("%02x",iNESCart.MD5[x]);
\r
571 FCEU_printf(" Mapper: %d\n Mirroring: %s\n", MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal");
\r
572 if(head.ROM_type&2) FCEU_printf(" Battery-backed.\n");
\r
573 if(head.ROM_type&4) FCEU_printf(" Trained.\n");
\r
579 uint64 partialmd5=0;
\r
583 partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8);
\r
586 FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring);
\r
588 /* Must remain here because above functions might change value of
\r
589 VROM_size and free(VROM).
\r
592 SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0);
\r
595 SetupCartMirroring(4,1,ExtraNTARAM);
\r
596 else if(Mirroring>=0x10)
\r
597 SetupCartMirroring(2+(Mirroring&1),1,0);
\r
599 SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0);
\r
601 iNESCart.battery=(head.ROM_type&2)?1:0;
\r
602 iNESCart.mirror=Mirroring;
\r
604 //if(MapperNo != 18) {
\r
605 // if(ROM) free(ROM);
\r
606 // if(VROM) free(VROM);
\r
611 if(NewiNES_Init(MapperNo))
\r
617 iNESCart.Power=iNESPower;
\r
618 if(head.ROM_type&2)
\r
620 iNESCart.SaveGame[0]=WRAM;
\r
621 iNESCart.SaveGameLen[0]=8192;
\r
624 FCEU_LoadGameSave(&iNESCart);
\r
626 GameInterface=iNESGI;
\r
629 // since apparently the iNES format doesn't store this information,
\r
630 // guess if the settings should be PAL or NTSC from the ROM name
\r
631 // TODO: MD5 check against a list of all known PAL games instead?
\r
632 if(strstr(name,"(E)") || strstr(name,"(e)")
\r
633 || strstr(name,"(F)") || strstr(name,"(f)")
\r
634 || strstr(name,"(G)") || strstr(name,"(g)")
\r
635 || strstr(name,"(I)") || strstr(name,"(i)"))
\r
636 FCEUI_SetVidSystem(1);
\r
638 FCEUI_SetVidSystem(0);
\r
643 void FASTAPASS(2) VRAM_BANK1(uint32 A, uint8 V)
\r
646 PPUCHRRAM|=(1<<(A>>10));
\r
647 CHRBankList[(A)>>10]=V;
\r
648 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
\r
651 void FASTAPASS(2) VRAM_BANK4(uint32 A, uint32 V)
\r
654 PPUCHRRAM|=(0xF<<(A>>10));
\r
655 CHRBankList[(A)>>10]=(V<<2);
\r
656 CHRBankList[((A)>>10)+1]=(V<<2)+1;
\r
657 CHRBankList[((A)>>10)+2]=(V<<2)+2;
\r
658 CHRBankList[((A)>>10)+3]=(V<<2)+3;
\r
659 VPage[(A)>>10]=&CHRRAM[V<<10]-(A);
\r
661 void FASTAPASS(2) VROM_BANK1(uint32 A,uint32 V)
\r
664 CHRBankList[(A)>>10]=V;
\r
667 void FASTAPASS(2) VROM_BANK2(uint32 A,uint32 V)
\r
670 CHRBankList[(A)>>10]=(V<<1);
\r
671 CHRBankList[((A)>>10)+1]=(V<<1)+1;
\r
674 void FASTAPASS(2) VROM_BANK4(uint32 A, uint32 V)
\r
677 CHRBankList[(A)>>10]=(V<<2);
\r
678 CHRBankList[((A)>>10)+1]=(V<<2)+1;
\r
679 CHRBankList[((A)>>10)+2]=(V<<2)+2;
\r
680 CHRBankList[((A)>>10)+3]=(V<<2)+3;
\r
683 void FASTAPASS(1) VROM_BANK8(uint32 V)
\r
686 CHRBankList[0]=(V<<3);
\r
687 CHRBankList[1]=(V<<3)+1;
\r
688 CHRBankList[2]=(V<<3)+2;
\r
689 CHRBankList[3]=(V<<3)+3;
\r
690 CHRBankList[4]=(V<<3)+4;
\r
691 CHRBankList[5]=(V<<3)+5;
\r
692 CHRBankList[6]=(V<<3)+6;
\r
693 CHRBankList[7]=(V<<3)+7;
\r
696 void FASTAPASS(2) ROM_BANK8(uint32 A, uint32 V)
\r
700 PRGBankList[((A-0x8000)>>13)]=V;
\r
703 void FASTAPASS(2) ROM_BANK16(uint32 A, uint32 V)
\r
708 PRGBankList[((A-0x8000)>>13)]=V<<1;
\r
709 PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1;
\r
713 void FASTAPASS(1) ROM_BANK32(uint32 V)
\r
715 setprg32(0x8000,V);
\r
716 PRGBankList[0]=V<<2;
\r
717 PRGBankList[1]=(V<<2)+1;
\r
718 PRGBankList[2]=(V<<2)+2;
\r
719 PRGBankList[3]=(V<<2)+3;
\r
722 void FASTAPASS(1) onemir(uint8 V)
\r
724 if(Mirroring==2) return;
\r
731 void FASTAPASS(1) MIRROR_SET2(uint8 V)
\r
733 if(Mirroring==2) return;
\r
738 void FASTAPASS(1) MIRROR_SET(uint8 V)
\r
740 if(Mirroring==2) return;
\r
746 static void NONE_init(void)
\r
748 ROM_BANK16(0x8000,0);
\r
749 ROM_BANK16(0xC000,~0);
\r
757 void (*MapInitTab[256])(void)=
\r
759 0,0, //Mapper2_init,Mapper3_init,
\r
764 Mapper8_init,Mapper9_init,
\r
766 0, //Mapper11_init,
\r
767 0, //Mapper13_init,
\r
770 Mapper15_init,Mapper16_init,Mapper17_init,Mapper18_init,
\r
772 Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init,
\r
773 Mapper25_init,Mapper26_init,Mapper27_init,
\r
775 Mapper32_init,Mapper33_init,Mapper34_init,
\r
777 Mapper40_init,Mapper41_init,Mapper42_init,Mapper43_init,
\r
783 Mapper50_init,Mapper51_init,
\r
785 0,// Mapper57_init,
\r
786 0,// Mapper58_init,
\r
787 Mapper59_init,Mapper60_init,
\r
788 Mapper61_init,Mapper62_init,
\r
790 Mapper64_init,Mapper65_init,
\r
793 Mapper68_init,Mapper69_init,
\r
796 Mapper72_init,Mapper73_init,
\r
798 Mapper75_init,Mapper76_init,Mapper77_init,
\r
799 0, //Mapper78_init,
\r
800 Mapper79_init,Mapper80_init,
\r
802 Mapper82_init,Mapper83_init,
\r
804 Mapper85_init,Mapper86_init,
\r
805 0, //Mapper87_init,
\r
806 0, //Mapper88_init,
\r
809 Mapper91_init,Mapper92_init,
\r
810 0, //Mapper93_init,
\r
811 0, //Mapper94_init,
\r
813 Mapper96_init,Mapper97_init,
\r
817 0, //Mapper107_init,
\r
821 0, //Mapper117_init,
\r
822 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
\r
823 0, //Mapper140_init,
\r
825 0, //Mapper144_init,
\r
828 0, //Mapper152_init,
\r
830 0, //Mapper154_init,
\r
832 Mapper156_init,Mapper157_init,Mapper158_init,0,
\r
834 Mapper166_init,Mapper167_init,
\r
835 0,0,0,0,0,0,0,0,0,0,0,0,
\r
839 0, //Mapper185_init,
\r
841 0, //Mapper189_init,
\r
843 0, //Mapper191_init,
\r
847 Mapper200_init,Mapper201_init,Mapper202_init,Mapper203_init,
\r
852 0, //Mapper211_init,
\r
853 Mapper212_init,Mapper213_init,Mapper214_init,
\r
854 0,0,0,0,0,0,0,0,0,0,
\r
855 Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init,
\r
856 Mapper229_init,Mapper230_init,Mapper231_init,Mapper232_init,
\r
859 0, //Mapper235_init,
\r
861 Mapper240_init,Mapper241_init,Mapper242_init,0,
\r
871 static DECLFW(BWRAM)
\r
876 static DECLFR(AWRAM)
\r
878 return WRAM[A-0x6000];
\r
881 #ifdef DEBUG_MAPPER
\r
882 static DECLFW(WriteHandler)
\r
884 FCEU_printf("$%04x:$%02x\n",A,V);
\r
888 void (*MapStateRestore)(int version);
\r
889 void iNESStateRestore(int version)
\r
893 if(!MapperNo) return;
\r
896 setprg8(0x8000+x*8192,PRGBankList[x]);
\r
900 setchr1(0x400*x,CHRBankList[x]);
\r
902 if(0) switch(Mirroring)
\r
904 case 0:setmirror(MI_H);break;
\r
905 case 1:setmirror(MI_V);break;
\r
907 case 0x10:setmirror(MI_0);break;
\r
909 case 0x11:setmirror(MI_1);break;
\r
911 if(MapStateRestore) MapStateRestore(version);
\r
914 static void iNESPower(void)
\r
919 SetReadHandler(0x8000,0xFFFF,CartBR);
\r
920 GameStateRestore=iNESStateRestore;
\r
925 setprg8r(1,0x6000,0);
\r
927 SetReadHandler(0x6000,0x7FFF,AWRAM);
\r
929 // asm code needs pages to be set again..
\r
930 Page[12]=Page[13]=Page[14]=Page[15]=WRAM-0x6000;
\r
932 SetWriteHandler(0x6000,0x7FFF,BWRAM);
\r
933 FCEU_CheatAddRAM(8,0x6000,WRAM);
\r
935 #ifdef DEBUG_MAPPER
\r
936 if(type==0) SetWriteHandler(0x4020,0xFFFF,WriteHandler);
\r
939 /* This statement represents atrocious code. I need to rewrite
\r
940 all of the iNES mapper code... */
\r
941 IRQCount=IRQLatch=IRQa=0;
\r
942 if(head.ROM_type&2)
\r
943 memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192);
\r
945 memset(GameMemBlock,0,sizeof(GameMemBlock));
\r
950 if(FCEUGameInfo.type == GIT_VSUNI)
\r
951 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
\r
953 AddExState(WRAM, 8192, 0, "WRAM");
\r
954 if(type==19 || type==6 || type==69 || type==85 || type==96)
\r
955 AddExState(MapperExRAM, 32768, 0, "MEXR");
\r
956 if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96))
\r
957 AddExState(CHRRAM, 8192, 0, "CHRR");
\r
958 if(head.ROM_type&8)
\r
959 AddExState(ExtraNTARAM, 2048, 0, "EXNR");
\r
961 /* Exclude some mappers whose emulation code handle save state stuff
\r
963 if(type && type!=13 && type!=96)
\r
965 AddExState(mapbyte1, 32, 0, "MPBY");
\r
966 AddExState(&Mirroring, 1, 0, "MIRR");
\r
967 AddExState(&IRQCount, 4, 1, "IRQC");
\r
968 AddExState(&IRQLatch, 4, 1, "IQL1");
\r
969 AddExState(&IRQa, 1, 0, "IRQA");
\r
970 AddExState(PRGBankList, 4, 0, "PBL");
\r
974 sprintf(tak,"CBL%d",x);
\r
975 AddExState(&CHRBankList[x], 2, 1,tak);
\r
979 if(MapInitTab[type]) MapInitTab[type]();
\r
982 FCEU_PrintError("iNES mapper #%d is not supported at all.",type);
\r
989 void (*init)(CartInfo *);
\r
992 static BMAPPING bmap[] = {
\r
1000 {11, Mapper11_Init},
\r
1001 {12, Mapper12_Init},
\r
1003 {19, Mapper19_Init},
\r
1004 {37, Mapper37_Init},
\r
1005 {44, Mapper44_Init},
\r
1006 {45, Mapper45_Init},
\r
1007 {47, Mapper47_Init},
\r
1008 {49, Mapper49_Init},
\r
1009 {52, Mapper52_Init},
\r
1010 {57, Mapper57_Init},
\r
1011 {58, Mapper58_Init},
\r
1013 {70, Mapper70_Init},
\r
1014 {74, Mapper74_Init},
\r
1015 {78, Mapper78_Init},
\r
1016 {87, Mapper87_Init},
\r
1017 {88, Mapper88_Init},
\r
1018 {90, Mapper90_Init},
\r
1019 {93, SUNSOFT_UNROM_Init},
\r
1020 {94, Mapper94_Init},
\r
1021 {95, Mapper95_Init},
\r
1022 {105, Mapper105_Init},
\r
1023 {107, Mapper107_Init},
\r
1024 {112, Mapper112_Init},
\r
1025 {114, Mapper114_Init},
\r
1026 {115, Mapper115_Init},
\r
1027 {116, Mapper116_Init},
\r
1028 {117, Mapper117_Init},
\r
1029 {118, Mapper118_Init},
\r
1030 {119, Mapper119_Init},
\r
1031 {133, SA72008_Init},
\r
1032 {137, S8259D_Init},
\r
1033 {138, S8259B_Init},
\r
1034 {139, S8259C_Init},
\r
1035 {140, Mapper140_Init},
\r
1036 {141, S8259A_Init},
\r
1037 {143, TCA01_Init},
\r
1038 {144, Mapper144_Init},
\r
1039 {145, SA72007_Init},
\r
1040 {146, SA0161M_Init},
\r
1041 {147, TCU01_Init},
\r
1042 {148, SA0037_Init},
\r
1043 {149, SA0036_Init},
\r
1044 {150, S74LS374N_Init},
\r
1045 {152, Mapper152_Init},
\r
1046 {154, Mapper154_Init},
\r
1047 {155, Mapper155_Init},
\r
1048 {160, Mapper90_Init},
\r
1049 {163, Mapper163_Init},
\r
1050 {164, Mapper164_Init},
\r
1051 {165, Mapper165_Init},
\r
1052 {181, Mapper181_Init},
\r
1053 {182, Mapper182_Init},
\r
1054 {183, Mapper183_Init},
\r
1055 {185, Mapper185_Init},
\r
1056 {186, Mapper186_Init},
\r
1057 {187, Mapper187_Init},
\r
1058 {188, Mapper188_Init},
\r
1059 {189, Mapper189_Init},
\r
1060 {191, Mapper191_Init},
\r
1061 {192, Mapper192_Init},
\r
1062 {194, Mapper194_Init},
\r
1063 {198, Mapper198_Init},
\r
1064 {199, Mapper199_Init},
\r
1065 {205, Mapper205_Init},
\r
1066 {206, DEIROM_Init},
\r
1067 {208, Mapper208_Init},
\r
1068 {209, Mapper209_Init},
\r
1069 {210, Mapper210_Init},
\r
1070 {211, Mapper211_Init},
\r
1071 {215, Mapper215_Init},
\r
1072 {216, Mapper216_Init},
\r
1073 {217, Mapper217_Init},
\r
1074 {218, UNLSonic_Init},
\r
1075 {219, UNLSL1632_Init},
\r
1076 // {220, Mapper220_Init},
\r
1077 {222, Mapper222_Init},
\r
1078 {235, Mapper235_Init},
\r
1079 {243, S74LS374NA_Init},
\r
1080 {245, Mapper245_Init},
\r
1081 {249, Mapper249_Init},
\r
1082 {250, Mapper250_Init},
\r
1083 {254, Mapper254_Init},
\r
1088 static int NewiNES_Init(int num)
\r
1090 BMAPPING *tmp=bmap;
\r
1092 if(FCEUGameInfo.type == GIT_VSUNI)
\r
1093 AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0);
\r
1097 if(num==tmp->number)
\r
1099 UNIFchrrama=0; // need here for compatibility with UNIF mapper code
\r
1107 VROM=(uint8 *)malloc(CHRRAMSize);
\r
1109 SetupCartCHRMapping(0,VROM,CHRRAMSize,1);
\r
1110 AddExState(VROM,CHRRAMSize, 0, "CHRR");
\r
1112 if(head.ROM_type&8)
\r
1113 AddExState(ExtraNTARAM, 2048, 0, "EXNR");
\r
1114 tmp->init(&iNESCart);
\r