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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
35 #include "general.h"
\r
52 void (*init)(CartInfo *);
\r
58 int (*init)(int fp);
\r
61 static CartInfo UNIFCart;
\r
64 static int mirrortodo;
\r
65 static char *boardname;
\r
66 static char *sboardname;
\r
68 static uint32 CHRRAMSize;
\r
69 uint8 *UNIFchrrama=0;
\r
71 static UNIF_HEADER unhead;
\r
72 static UNIF_HEADER uchead;
\r
75 static uint8 *malloced[32];
\r
76 static uint32 mallocedsizes[32];
\r
78 static int FixRomSize(uint32 size, uint32 minimum)
\r
89 static void FreeUNIF(void)
\r
93 {free(UNIFchrrama);UNIFchrrama=0;}
\r
95 {free(boardname);boardname=0;}
\r
99 {free(malloced[x]);malloced[x]=0;}
\r
103 static void ResetUNIF(void)
\r
111 memset(&UNIFCart,0,sizeof(UNIFCart));
\r
115 static uint8 exntar[2048];
\r
117 static void MooMirroring(void)
\r
120 SetupCartMirroring(mirrortodo,1,0);
\r
121 else if(mirrortodo==0x4)
\r
123 SetupCartMirroring(4,1,exntar);
\r
124 AddExState(exntar, 2048, 0,"EXNR");
\r
127 SetupCartMirroring(0,0,0);
\r
130 static int DoMirroring(int fp)
\r
137 static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};
\r
139 FCEU_printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);
\r
144 static int NAME(int fp)
\r
150 FCEU_printf(" Name: ");
\r
153 while((t=FCEU_fgetc(fp))>0)
\r
155 namebuf[index++]=t;
\r
158 FCEU_printf("%s\n",namebuf);
\r
160 if(!FCEUGameInfo.name)
\r
162 FCEUGameInfo.name=malloc(strlen(namebuf)+1);
\r
163 strcpy((char *)FCEUGameInfo.name,namebuf);
\r
167 static int DINF(int fp)
\r
169 char name[100], method[100];
\r
174 if(FCEU_fread(name,1,100,fp)!=100)
\r
176 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
178 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
180 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
182 if((t=FCEU_fgetc(fp))==EOF) return(0);
\r
184 if(FCEU_fread(method,1,100,fp)!=100)
\r
186 name[99]=method[99]=0;
\r
187 FCEU_printf(" Dumped by: %s\n",name);
\r
188 FCEU_printf(" Dumped with: %s\n",method);
\r
190 char *months[12]={"January","February","March","April","May","June","July",
\r
191 "August","September","October","November","December"};
\r
192 FCEU_printf(" Dumped on: %s %d, %d\n",months[(m-1)%12],d,y);
\r
197 static int CTRL(int fp)
\r
201 if((t=FCEU_fgetc(fp))==EOF)
\r
203 /* The information stored in this byte isn't very helpful, but it's
\r
204 better than nothing...maybe.
\r
207 if(t&1) FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_GAMEPAD;
\r
208 else FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_NONE;
\r
210 if(t&2) FCEUGameInfo.input[1]=SI_ZAPPER;
\r
211 //else if(t&0x10) FCEUGameInfo->input[1]=SI_POWERPAD;
\r
216 static int TVCI(int fp)
\r
219 if( (t=FCEU_fgetc(fp)) ==EOF)
\r
223 char *stuffo[3]={"NTSC","PAL","NTSC and PAL"};
\r
226 FCEUGameInfo.vidsys=GIV_NTSC;
\r
227 FCEUI_SetVidSystem(0);
\r
231 FCEUGameInfo.vidsys=GIV_PAL;
\r
232 FCEUI_SetVidSystem(1);
\r
234 FCEU_printf(" TV Standard Compatibility: %s\n",stuffo[t]);
\r
239 static int EnableBattery(int fp)
\r
241 FCEU_printf(" Battery-backed.\n");
\r
242 if(FCEU_fgetc(fp)==EOF)
\r
244 UNIFCart.battery=1;
\r
248 static int LoadPRG(int fp)
\r
251 z=uchead.ID[3]-'0';
\r
255 FCEU_printf(" PRG ROM %d size: %d",z,(int) uchead.info);
\r
258 t=FixRomSize(uchead.info,2048);
\r
259 if(!(malloced[z]=(uint8 *)FCEU_malloc(t)))
\r
261 mallocedsizes[z]=t;
\r
262 memset(malloced[z]+uchead.info,0xFF,t-uchead.info);
\r
263 if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info)
\r
265 FCEU_printf("Read Error!\n");
\r
271 SetupCartPRGMapping(z,malloced[z],t,0);
\r
275 static int SetBoardName(int fp)
\r
277 if(!(boardname=FCEU_malloc(uchead.info+1)))
\r
279 FCEU_fread(boardname,1,uchead.info,fp);
\r
280 boardname[uchead.info]=0;
\r
281 FCEU_printf(" Board name: %s\n",boardname);
\r
282 sboardname=boardname;
\r
283 if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4))
\r
288 static int LoadCHR(int fp)
\r
291 z=uchead.ID[3]-'0';
\r
294 FCEU_printf(" CHR ROM %d size: %d",z,(int) uchead.info);
\r
296 free(malloced[16+z]);
\r
297 t=FixRomSize(uchead.info,8192);
\r
298 if(!(malloced[16+z]=(uint8 *)FCEU_malloc(t)))
\r
300 mallocedsizes[16+z]=t;
\r
301 memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info);
\r
302 if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info)
\r
304 FCEU_printf("Read Error!\n");
\r
310 SetupCartCHRMapping(z,malloced[16+z],t,0);
\r
315 #define BMCFLAG_FORCE4 1
\r
316 #define BMCFLAG_16KCHRR 2
\r
317 #define BMCFLAG_32KCHRR 4
\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-016-1M", SA0161M_Init,0},
\r
330 { "SA-72007", SA72007_Init,0},
\r
331 { "SA-72008", SA72008_Init,0},
\r
332 { "SA-0036", SA0036_Init,0},
\r
333 { "SA-0037", SA0037_Init,0},
\r
334 { "SA-NROM", TCA01_Init,0},
\r
336 // /* AVE carts. */
\r
337 // { "MB-91", MB91_Init,0}, // DeathBots
\r
338 // { "NINA-06", NINA06_Init,0}, // F-15 City War
\r
339 // { "NINA-03", NINA03_Init,0}, // Tiles of Fate
\r
340 // { "NINA-001", NINA001_Init,0}, // Impossible Mission 2
\r
342 { "ANROM", ANROM_Init,0},
\r
344 { "HKROM", HKROM_Init,0},
\r
346 { "EWROM", EWROM_Init,0},
\r
347 { "EKROM", EKROM_Init,0},
\r
348 { "ELROM", ELROM_Init,0},
\r
349 { "ETROM", ETROM_Init,0},
\r
351 { "SAROM", SAROM_Init,0},
\r
352 { "SBROM", SBROM_Init,0},
\r
353 { "SCROM", SCROM_Init,0},
\r
354 { "SEROM", SEROM_Init,0},
\r
355 { "SGROM", SGROM_Init,0},
\r
356 { "SKROM", SKROM_Init,0},
\r
357 { "SLROM", SLROM_Init,0},
\r
358 { "SL1ROM", SL1ROM_Init,0},
\r
359 { "SNROM", SNROM_Init,0},
\r
360 { "SOROM", SOROM_Init,0},
\r
362 { "TGROM", TGROM_Init,0},
\r
363 { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4},
\r
365 { "TEROM", TEROM_Init,0},
\r
366 { "TFROM", TFROM_Init,0},
\r
367 { "TLROM", TLROM_Init,0},
\r
368 { "TKROM", TKROM_Init,0},
\r
369 { "TSROM", TSROM_Init,0},
\r
371 { "TLSROM", TLSROM_Init,0},
\r
372 { "TKSROM", TKSROM_Init,0},
\r
373 { "TQROM", TQROM_Init,0},
\r
374 { "TVROM", TLROM_Init,BMCFLAG_FORCE4},
\r
376 { "CPROM", CPROM_Init,BMCFLAG_16KCHRR},
\r
377 { "CNROM", CNROM_Init,0},
\r
378 { "NROM", NROM_Init,0 }, //NROM256_Init,0 },
\r
379 { "NROM-128", NROM_Init,0 }, //NROM128_Init,0 },
\r
380 { "NROM-256", NROM_Init,0 }, //NROM256_Init,0 },
\r
381 { "RROM", NROM_Init,0 }, //NROM128_Init,0 },
\r
382 { "RROM-128", NROM_Init,0 }, //NROM128_Init,0 },
\r
383 { "MHROM", MHROM_Init,0},
\r
384 { "UNROM", UNROM_Init,0},
\r
385 { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init,0},
\r
386 { "MARIO1-MALEE2", MALEE_Init,0},
\r
388 { "CC-21", UNLCC21_Init,0},
\r
390 { "H2288", UNLH2288_Init,0},
\r
391 { "KOF97", UNLKOF97_Init,0},
\r
392 { "SL1632", UNLSL1632_Init,0},
\r
393 { "SHERO", UNLSHeroes_Init,0},
\r
394 { "8237", UNL8237_Init,0},
\r
395 { "8157", UNL8157_Init,0},
\r
396 { "T-262", BMCT262_Init,0},
\r
397 { "FK23C", BMCFK23C_Init,0},
\r
398 { "Supervision16in1", Supervision16_Init,0},
\r
399 { "NovelDiamond9999999in1", Novel_Init,0},
\r
400 { "Super24in1SC03", Super24_Init,0},
\r
401 { "42in1ResetSwitch", BMC42in1r_Init, 0},
\r
402 { "64in1NoRepeat", BMC64in1nr_Init, 0},
\r
403 { "13in1JY110", BMC13in1JY110_Init, 0},
\r
404 { "70in1", BMC70in1_Init, 0},
\r
405 { "70in1B", BMC70in1B_Init, 0},
\r
406 { "GK-192", Mapper58_Init, 0},
\r
407 { "SuperHIK8in1", Mapper45_Init,0},
\r
409 { "DREAMTECH01", DreamTech01_Init,0},
\r
410 { "KONAMI-QTAI", Mapper190_Init,0},
\r
412 { "TEK90", Mapper90_Init,0},
\r
417 static BFMAPPING bfunc[] = {
\r
420 { "BATR", EnableBattery },
\r
421 { "MIRR", DoMirroring },
\r
422 { "PRG", LoadPRG },
\r
423 { "CHR", LoadCHR },
\r
425 { "MAPR", SetBoardName },
\r
430 int LoadUNIFChunks(int fp)
\r
436 t=FCEU_fread(&uchead,1,4,fp);
\r
443 if(!(FCEU_read32(&uchead.info,fp)))
\r
447 //printf("Funky: %s\n",((uint8 *)&uchead));
\r
448 while(bfunc[x].name)
\r
450 if(!memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name)))
\r
452 if(!bfunc[x].init(fp))
\r
460 if(FCEU_fseek(fp,uchead.info,SEEK_CUR))
\r
465 static int InitializeBoard(void)
\r
469 if(!sboardname) return(0);
\r
471 while(bmap[x].name)
\r
473 if(!strcmp(sboardname,(char *)bmap[x].name))
\r
477 if(bmap[x].flags & BMCFLAG_16KCHRR)
\r
478 CHRRAMSize = 16384;
\r
481 if((UNIFchrrama=(uint8 *)FCEU_malloc(CHRRAMSize)))
\r
483 SetupCartCHRMapping(0,UNIFchrrama,CHRRAMSize,1);
\r
484 AddExState(UNIFchrrama, CHRRAMSize, 0,"CHRR");
\r
489 if(bmap[x].flags&BMCFLAG_FORCE4)
\r
492 bmap[x].init(&UNIFCart);
\r
497 FCEU_PrintError("Board type not supported.");
\r
501 static void UNIFGI(int h, void *param)
\r
512 if(UNIFchrrama) memset(UNIFchrrama,0,8192);
\r
515 FCEU_SaveGameSave(&UNIFCart);
\r
521 case GI_INFOSTRING:
\r
524 strncpy(board, sboardname, 20);
\r
526 sprintf(param, "UNIF, %s, %s%s", board, PAL?"PAL":"NTSC", UNIFCart.battery?", BB":"");
\r
532 int UNIFLoad(const char *name, int fp)
\r
534 FCEU_fseek(fp,0,SEEK_SET);
\r
535 FCEU_fread(&unhead,1,4,fp);
\r
536 if(memcmp(&unhead,"UNIF",4))
\r
539 ResetCartMapping();
\r
543 if(!FCEU_read32(&unhead.info,fp))
\r
545 if(FCEU_fseek(fp,0x20,SEEK_SET)<0)
\r
547 if(!LoadUNIFChunks(fp))
\r
551 struct md5_context md5;
\r
558 md5_update(&md5,malloced[x],mallocedsizes[x]);
\r
560 md5_finish(&md5,UNIFCart.MD5);
\r
561 FCEU_printf(" ROM MD5: 0x");
\r
563 FCEU_printf("%02x",UNIFCart.MD5[x]);
\r
565 memcpy(FCEUGameInfo.MD5,UNIFCart.MD5,sizeof(UNIFCart.MD5));
\r
568 if(!InitializeBoard())
\r
571 FCEU_LoadGameSave(&UNIFCart);
\r
572 GameInterface=UNIFGI;
\r