1 /* FCE Ultra - NES/Famicom Emulator
\r
3 * Copyright notice for this file:
\r
4 * Copyright (C) 2002 Xodnizel
\r
6 * This program is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either version 2 of the License, or
\r
9 * (at your option) any later version.
\r
11 * This program is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with this program; if not, write to the Free Software
\r
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\r
21 /* TODO: Battery backup file saving, mirror force */
\r
22 /* **INCOMPLETE** */
\r
23 /* Override stuff: CHR RAM instead of CHR ROM, mirroring. */
\r
51 void (*init)(CartInfo *);
\r
57 int (*init)(int fp);
\r
60 static CartInfo UNIFCart;
\r
63 static int mirrortodo;
\r
64 static uint8 *boardname;
\r
65 static uint8 *sboardname;
\r
67 static uint32 CHRRAMSize;
\r
68 uint8 *UNIFchrrama=0;
\r
70 static UNIF_HEADER unhead;
\r
71 static UNIF_HEADER uchead;
\r
74 static uint8 *malloced[32];
\r
75 static uint32 mallocedsizes[32];
\r
77 static int FixRomSize(uint32 size, uint32 minimum)
\r
79 uint32 x=1; //mbg merge 7/17/06 made uint
\r
88 static void FreeUNIF(void)
\r
92 {free(UNIFchrrama);UNIFchrrama=0;}
\r
94 {free(boardname);boardname=0;}
\r
98 {free(malloced[x]);malloced[x]=0;}
\r
102 static void ResetUNIF(void)
\r
110 memset(&UNIFCart,0,sizeof(UNIFCart));
\r
114 static uint8 exntar[2048];
\r
116 static void MooMirroring(void)
\r
119 SetupCartMirroring(mirrortodo,1,0);
\r
120 else if(mirrortodo==0x4)
\r
122 SetupCartMirroring(4,1,exntar);
\r
123 AddExState(exntar, 2048, 0,"EXNR");
\r
126 SetupCartMirroring(0,0,0);
\r
129 static int DoMirroring(int fp)
\r
136 static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};
\r
138 FCEU_printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);
\r
143 static int NAME(int fp)
\r
149 FCEU_printf(" Name: ");
\r
152 while((t=FCEU_fgetc(fp))>0)
\r
154 namebuf[index++]=t;
\r
157 FCEU_printf("%s\n",namebuf);
\r
159 if(!GameInfo->name)
\r
161 GameInfo->name=(uint8*)malloc(strlen(namebuf)+1); //mbg merge 7/17/06 added cast
\r
162 strcpy((char*)GameInfo->name,namebuf); //mbg merge 7/17/06 added cast
\r
166 static int DINF(int fp)
\r
168 char name[100], method[100];
\r
173 if(FCEU_fread(name,1,100,fp)!=100)
\r
175 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
177 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
179 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
181 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
183 if(FCEU_fread(method,1,100,fp)!=100)
\r
185 name[99]=method[99]=0;
\r
186 FCEU_printf(" Dumped by: %s\n",name);
\r
187 FCEU_printf(" Dumped with: %s\n",method);
\r
189 char *months[12]={"January","February","March","April","May","June","July",
\r
190 "August","September","October","November","December"};
\r
191 FCEU_printf(" Dumped on: %s %d, %d\n",months[(m-1)%12],d,y);
\r
196 static int CTRL(int fp)
\r
200 if((t=FCEU_fgetc(fp))==EOF)
\r
202 /* The information stored in this byte isn't very helpful, but it's
\r
203 better than nothing...maybe.
\r
206 if(t&1) GameInfo->input[0]=GameInfo->input[1]=SI_GAMEPAD;
\r
207 else GameInfo->input[0]=GameInfo->input[1]=SI_NONE;
\r
209 if(t&2) GameInfo->input[1]=SI_ZAPPER;
\r
210 //else if(t&0x10) GameInfo->input[1]=SI_POWERPAD;
\r
215 static int TVCI(int fp)
\r
218 if( (t=FCEU_fgetc(fp)) ==EOF)
\r
222 char *stuffo[3]={"NTSC","PAL","NTSC and PAL"};
\r
225 GameInfo->vidsys=GIV_NTSC;
\r
226 FCEUI_SetVidSystem(0);
\r
230 GameInfo->vidsys=GIV_PAL;
\r
231 FCEUI_SetVidSystem(1);
\r
233 FCEU_printf(" TV Standard Compatibility: %s\n",stuffo[t]);
\r
238 static int EnableBattery(int fp)
\r
240 FCEU_printf(" Battery-backed.\n");
\r
241 if(FCEU_fgetc(fp)==EOF)
\r
243 UNIFCart.battery=1;
\r
247 static int LoadPRG(int fp)
\r
250 z=uchead.ID[3]-'0';
\r
254 FCEU_printf(" PRG ROM %d size: %d",z,(int) uchead.info);
\r
257 t=FixRomSize(uchead.info,2048);
\r
258 if(!(malloced[z]=(uint8 *)FCEU_malloc(t)))
\r
260 mallocedsizes[z]=t;
\r
261 memset(malloced[z]+uchead.info,0xFF,t-uchead.info);
\r
262 if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info)
\r
264 FCEU_printf("Read Error!\n");
\r
270 SetupCartPRGMapping(z,malloced[z],t,0);
\r
274 static int SetBoardName(int fp)
\r
276 if(!(boardname=(uint8 *)FCEU_malloc(uchead.info+1)))
\r
278 FCEU_fread(boardname,1,uchead.info,fp);
\r
279 boardname[uchead.info]=0;
\r
280 FCEU_printf(" Board name: %s\n",boardname);
\r
281 sboardname=boardname;
\r
282 if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4))
\r
287 static int LoadCHR(int fp)
\r
290 z=uchead.ID[3]-'0';
\r
293 FCEU_printf(" CHR ROM %d size: %d",z,(int) uchead.info);
\r
295 free(malloced[16+z]);
\r
296 t=FixRomSize(uchead.info,8192);
\r
297 if(!(malloced[16+z]=(uint8 *)FCEU_malloc(t)))
\r
299 mallocedsizes[16+z]=t;
\r
300 memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info);
\r
301 if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info)
\r
303 FCEU_printf("Read Error!\n");
\r
309 SetupCartCHRMapping(z,malloced[16+z],t,0);
\r
314 #define BMCFLAG_FORCE4 1
\r
315 #define BMCFLAG_16KCHRR 2
\r
316 #define BMCFLAG_32KCHRR 4
\r
317 #define BMCFLAG_EXPCHRR 8
\r
319 static BMAPPING bmap[] = {
\r
322 { "TC-U01-1.5M", TCU01_Init,0},
\r
323 { "Sachen-8259A", S8259A_Init,0},
\r
324 { "Sachen-8259B", S8259B_Init,0},
\r
325 { "Sachen-8259C", S8259C_Init,0},
\r
326 { "Sachen-8259D", S8259D_Init,0},
\r
327 { "Sachen-74LS374N", S74LS374N_Init,0},
\r
328 { "Sachen-74LS374NA", S74LS374NA_Init,0}, //seems to be custom mapper
\r
329 { "SA-002", TCU02_Init, 0},
\r
330 { "SA-016-1M", SA0161M_Init,0},
\r
331 { "SA-72007", SA72007_Init,0},
\r
332 { "SA-72008", SA72008_Init,0},
\r
333 { "SA-009", SA009_Init,0},
\r
334 { "SA-0036", SA0036_Init,0},
\r
335 { "SA-0037", SA0037_Init,0},
\r
336 { "SA-NROM", TCA01_Init,0},
\r
337 { "SA-9602B", SA9602B_Init, BMCFLAG_32KCHRR},
\r
339 // /* AVE carts. */
\r
340 // { "MB-91", MB91_Init,0}, // DeathBots
\r
341 // { "NINA-06", NINA06_Init,0}, // F-15 City War
\r
342 // { "NINA-03", NINA03_Init,0}, // Tiles of Fate
\r
343 // { "NINA-001", NINA001_Init,0}, // Impossible Mission 2
\r
345 { "ANROM", ANROM_Init,0},
\r
347 { "HKROM", HKROM_Init,0},
\r
349 { "EWROM", EWROM_Init,0},
\r
350 { "EKROM", EKROM_Init,0},
\r
351 { "ELROM", ELROM_Init,0},
\r
352 { "ETROM", ETROM_Init,0},
\r
354 { "SAROM", SAROM_Init,0},
\r
355 { "SBROM", SBROM_Init,0},
\r
356 { "SCROM", SCROM_Init,0},
\r
357 { "SEROM", SEROM_Init,0},
\r
358 { "SGROM", SGROM_Init,0},
\r
359 { "SKROM", SKROM_Init,0},
\r
360 { "SLROM", SLROM_Init,0},
\r
361 { "SL1ROM", SL1ROM_Init,0},
\r
362 { "SNROM", SNROM_Init,0},
\r
363 { "SOROM", SOROM_Init,0},
\r
365 { "TGROM", TGROM_Init,0},
\r
366 { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4},
\r
368 { "TBROM", TBROM_Init,0},
\r
369 { "TEROM", TEROM_Init,0},
\r
370 { "TFROM", TFROM_Init,0},
\r
371 { "TLROM", TLROM_Init,0},
\r
372 { "TKROM", TKROM_Init,0},
\r
373 { "TSROM", TSROM_Init,0},
\r
375 { "TLSROM", TLSROM_Init,0},
\r
376 { "TKSROM", TKSROM_Init,0},
\r
377 { "TQROM", TQROM_Init,0},
\r
378 { "TVROM", TLROM_Init,BMCFLAG_FORCE4},
\r
380 { "NTBROM", Mapper68_Init,0},
\r
382 { "CPROM", CPROM_Init,BMCFLAG_16KCHRR},
\r
383 { "CNROM", CNROM_Init,0},
\r
384 { "NROM", NROM_Init,0 }, //NROM256_Init,0 },
\r
385 { "NROM-128", NROM_Init,0 }, //NROM128_Init,0 },
\r
386 { "NROM-256", NROM_Init,0 }, //NROM256_Init,0 },
\r
387 { "SSS-NROM-256", SSSNROM_Init,0 },
\r
388 { "RROM", NROM_Init,0 }, //NROM128_Init,0 },
\r
389 { "RROM-128", NROM_Init,0 }, //NROM128_Init,0 },
\r
390 { "MHROM", MHROM_Init,0},
\r
391 { "UNROM", UNROM_Init,0},
\r
392 { "UOROM", UNROM_Init,0},
\r
393 { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init,0},
\r
394 { "MARIO1-MALEE2", MALEE_Init,0},
\r
395 { "3D-BLOCK", UNL3DBlock_Init, 0},
\r
396 { "SMB2J", UNLSMB2J_Init, 0},
\r
397 { "AX5705", UNLAX5705_Init, 0},
\r
398 { "CC-21", UNLCC21_Init,0},
\r
399 { "LE05", LE05_Init,0},
\r
400 { "AC08", AC08_Init,0},
\r
401 { "LH10", LH10_Init,0},
\r
402 { "LH32", LH32_Init,0},
\r
403 { "LH53", LH53_Init,0},
\r
404 { "BB", UNLBB_Init,0},
\r
406 { "H2288", UNLH2288_Init,0},
\r
407 { "KOF97", UNLKOF97_Init,0},
\r
408 { "SL1632", UNLSL1632_Init,0},
\r
409 { "SL12", UNLSL12_Init,0},
\r
410 { "SHERO", UNLSHeroes_Init,0},
\r
411 { "8237", UNL8237_Init,0},
\r
412 { "8237A", UNL8237A_Init,0},
\r
413 { "8157", UNL8157_Init,0},
\r
414 { "T-262", BMCT262_Init,0},
\r
415 { "FK23C", BMCFK23C_Init,BMCFLAG_EXPCHRR},
\r
416 { "FK23CA", BMCFK23CA_Init,BMCFLAG_EXPCHRR},
\r
417 { "A65AS", BMCA65AS_Init,0},
\r
418 { "YOKO", UNLYOKO_Init,0},
\r
419 { "FS304", UNLFS304_Init,0},
\r
420 { "43272", UNL43272_Init,0},
\r
421 { "EDU2000", UNLEDU2000_Init,0},
\r
422 { "603-5052", UNL6035052_Init,0},
\r
423 { "N625092", UNLN625092_Init,0},
\r
424 { "Supervision16in1", Supervision16_Init,0},
\r
425 { "NovelDiamond9999999in1", Novel_Init,0},
\r
426 { "Super24in1SC03", Super24_Init,0},
\r
427 { "64in1NoRepeat", BMC64in1nr_Init, 0},
\r
428 { "42in1ResetSwitch", Mapper226_Init, 0},
\r
429 { "13in1JY110", BMC13in1JY110_Init, 0},
\r
430 { "70in1", BMC70in1_Init, 0},
\r
431 { "70in1B", BMC70in1B_Init, 0},
\r
432 { "D1038", BMCD1038_Init, 0},
\r
433 { "GK-192", BMCGK192_Init, 0},
\r
434 { "SuperHIK8in1", Mapper45_Init,0},
\r
435 { "22211", UNL22211_Init,0},
\r
436 { "TF1201", UNLTF1201_Init, 0},
\r
437 { "GS-2004", BMCGS2004_Init, 0},
\r
438 { "GS-2013", BMCGS2013_Init, 0},
\r
439 { "KS7057", UNLKS7057_Init, 0},
\r
440 { "KS7037", UNLKS7037_Init, 0},
\r
441 { "KS7030", UNLKS7030_Init, 0},
\r
442 { "KS7031", UNLKS7031_Init, 0},
\r
443 { "KS7032", UNLKS7032_Init, 0},
\r
444 { "KS7017", UNLKS7017_Init, 0},
\r
445 { "KS7012", UNLKS7012_Init, 0},
\r
446 { "KS7013B", UNLKS7013B_Init, 0},
\r
447 { "T-230", UNLT230_Init, 0},
\r
448 { "CITYFIGHT", UNLCITYFIGHT_Init, 0},
\r
449 { "190in1", BMC190in1_Init, 0},
\r
450 { "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0},
\r
451 { "BS-5",BMCBS5_Init, 0},
\r
452 { "411120-C",BMC411120C_Init, 0},
\r
453 { "830118C",BMC830118C_Init, 0},
\r
454 { "T-227-1",BMCT2271_Init,0},
\r
455 { "PEC-586",UNLPEC586Init,0},
\r
456 { "12-IN-1",BMC12IN1_Init,0},
\r
457 { "VRC7", UNLVRC7_Init,0},
\r
458 { "810544-C-A1", BMC810544CA1_Init,0},
\r
459 { "NTD-03", BMCNTD03_Init,0},
\r
461 { "DREAMTECH01", DreamTech01_Init,0},
\r
462 { "KONAMI-QTAI", Mapper190_Init,0},
\r
464 { "DANCE", UNLOneBus_Init,0}, // redundant
\r
465 { "OneBus", UNLOneBus_Init,0},
\r
466 { "SC-127", UNLSC127_Init,0},
\r
467 { "DANCE2000", UNLD2000_Init,0},
\r
468 { "Transformer", Transformer_Init, 0},
\r
470 { "TEK90", Mapper90_Init,0},
\r
473 { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init,0},
\r
474 { "COPYFAMI", MapperCopyFami_Init,0},
\r
480 static BFMAPPING bfunc[] = {
\r
483 { "BATR", EnableBattery },
\r
484 { "MIRR", DoMirroring },
\r
485 { "PRG", LoadPRG },
\r
486 { "CHR", LoadCHR },
\r
488 { "MAPR", SetBoardName },
\r
493 int LoadUNIFChunks(int fp)
\r
499 t=FCEU_fread(&uchead,1,4,fp);
\r
506 if(!(FCEU_read32le(&uchead.info,fp)))
\r
510 //printf("Funky: %s\n",((uint8 *)&uchead));
\r
511 while(bfunc[x].name)
\r
513 if(!memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name)))
\r
515 if(!bfunc[x].init(fp))
\r
523 if(FCEU_fseek(fp,uchead.info,SEEK_CUR)<0)
\r
528 static int InitializeBoard(void)
\r
532 if(!sboardname) return(0);
\r
534 while(bmap[x].name)
\r
536 if(!strcmp((char *)sboardname,(char *)bmap[x].name))
\r
540 if(bmap[x].flags & BMCFLAG_16KCHRR)
\r
541 CHRRAMSize = 16384;
\r
542 else if(bmap[x].flags & BMCFLAG_32KCHRR)
\r
543 CHRRAMSize = 32768;
\r
544 else if(bmap[x].flags & BMCFLAG_EXPCHRR)
\r
545 CHRRAMSize = 128 * 1024;
\r
548 if((UNIFchrrama=(uint8 *)FCEU_malloc(CHRRAMSize)))
\r
550 SetupCartCHRMapping(0,UNIFchrrama,CHRRAMSize,1);
\r
551 AddExState(UNIFchrrama, CHRRAMSize, 0,"CHRR");
\r
556 if(bmap[x].flags&BMCFLAG_FORCE4)
\r
559 bmap[x].init(&UNIFCart);
\r
564 FCEU_PrintError("Board type not supported.");
\r
568 static void UNIFGI(int h, void *param)
\r
573 //FCEU_ClearGameSave(&UNIFCart);
\r
583 if(UNIFchrrama) memset(UNIFchrrama,0,8192);
\r
586 FCEU_SaveGameSave(&UNIFCart);
\r
591 case GI_INFOSTRING:
\r
594 strncpy(board, (char *)sboardname, 20);
\r
596 sprintf(param, "UNIF, %s, %s%s", board, PAL?"PAL":"NTSC", UNIFCart.battery?", BB":"");
\r
602 int UNIFLoad(const char *name, int fp)
\r
604 FCEU_fseek(fp,0,SEEK_SET);
\r
605 FCEU_fread(&unhead,1,4,fp);
\r
606 if(memcmp(&unhead,"UNIF",4))
\r
609 ResetCartMapping();
\r
613 if(!FCEU_read32le(&unhead.info,fp))
\r
615 if(FCEU_fseek(fp,0x20,SEEK_SET)<0)
\r
617 if(!LoadUNIFChunks(fp))
\r
621 struct md5_context md5;
\r
628 md5_update(&md5,malloced[x],mallocedsizes[x]);
\r
630 md5_finish(&md5,UNIFCart.MD5);
\r
631 FCEU_printf(" ROM MD5: 0x");
\r
633 FCEU_printf("%02x",UNIFCart.MD5[x]);
\r
635 memcpy(&GameInfo->MD5,&UNIFCart.MD5,sizeof(UNIFCart.MD5));
\r
638 if(!InitializeBoard())
\r
641 FCEU_LoadGameSave(&UNIFCart);
\r
643 //strcpy(LoadedRomFName,name); //For the debugger list
\r
644 GameInterface=UNIFGI;
\r