| 1 | /* FCE Ultra - NES/Famicom Emulator\r |
| 2 | *\r |
| 3 | * Copyright notice for this file:\r |
| 4 | * Copyright (C) 2002 Xodnizel\r |
| 5 | *\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 |
| 10 | *\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 |
| 15 | *\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 |
| 19 | */\r |
| 20 | \r |
| 21 | /* TODO: Battery backup file saving, mirror force */\r |
| 22 | /* **INCOMPLETE** */\r |
| 23 | /* Override stuff: CHR RAM instead of CHR ROM, mirroring. */\r |
| 24 | \r |
| 25 | #include <stdio.h>\r |
| 26 | #include <stdlib.h>\r |
| 27 | #include <string.h>\r |
| 28 | \r |
| 29 | \r |
| 30 | #include "types.h"\r |
| 31 | #include "fce.h"\r |
| 32 | #include "cart.h"\r |
| 33 | #include "unif.h"\r |
| 34 | #include "ines.h"\r |
| 35 | #include "endian.h"\r |
| 36 | #include "memory.h"\r |
| 37 | #include "md5.h"\r |
| 38 | #include "state.h"\r |
| 39 | #include "file.h"\r |
| 40 | #include "input.h"\r |
| 41 | #include "driver.h"\r |
| 42 | #include "svga.h"\r |
| 43 | \r |
| 44 | typedef struct {\r |
| 45 | char ID[4];\r |
| 46 | uint32 info;\r |
| 47 | } UNIF_HEADER;\r |
| 48 | \r |
| 49 | typedef struct {\r |
| 50 | char *name;\r |
| 51 | void (*init)(CartInfo *);\r |
| 52 | int flags;\r |
| 53 | } BMAPPING;\r |
| 54 | \r |
| 55 | typedef struct {\r |
| 56 | char *name;\r |
| 57 | int (*init)(int fp);\r |
| 58 | } BFMAPPING;\r |
| 59 | \r |
| 60 | static CartInfo UNIFCart;\r |
| 61 | \r |
| 62 | static int vramo;\r |
| 63 | static int mirrortodo;\r |
| 64 | static uint8 *boardname;\r |
| 65 | static uint8 *sboardname;\r |
| 66 | \r |
| 67 | static uint32 CHRRAMSize;\r |
| 68 | uint8 *UNIFchrrama=0;\r |
| 69 | \r |
| 70 | static UNIF_HEADER unhead;\r |
| 71 | static UNIF_HEADER uchead;\r |
| 72 | \r |
| 73 | \r |
| 74 | static uint8 *malloced[32];\r |
| 75 | static uint32 mallocedsizes[32];\r |
| 76 | \r |
| 77 | static int FixRomSize(uint32 size, uint32 minimum)\r |
| 78 | {\r |
| 79 | uint32 x=1; //mbg merge 7/17/06 made uint\r |
| 80 | \r |
| 81 | if(size<minimum)\r |
| 82 | return minimum;\r |
| 83 | while(x<size)\r |
| 84 | x<<=1;\r |
| 85 | return x;\r |
| 86 | }\r |
| 87 | \r |
| 88 | static void FreeUNIF(void)\r |
| 89 | {\r |
| 90 | int x;\r |
| 91 | if(UNIFchrrama)\r |
| 92 | {free(UNIFchrrama);UNIFchrrama=0;}\r |
| 93 | if(boardname)\r |
| 94 | {free(boardname);boardname=0;}\r |
| 95 | for(x=0;x<32;x++)\r |
| 96 | {\r |
| 97 | if(malloced[x])\r |
| 98 | {free(malloced[x]);malloced[x]=0;}\r |
| 99 | }\r |
| 100 | }\r |
| 101 | \r |
| 102 | static void ResetUNIF(void)\r |
| 103 | {\r |
| 104 | int x;\r |
| 105 | for(x=0;x<32;x++)\r |
| 106 | malloced[x]=0;\r |
| 107 | vramo=0;\r |
| 108 | boardname=0;\r |
| 109 | mirrortodo=0;\r |
| 110 | memset(&UNIFCart,0,sizeof(UNIFCart));\r |
| 111 | UNIFchrrama=0;\r |
| 112 | }\r |
| 113 | \r |
| 114 | static uint8 exntar[2048];\r |
| 115 | \r |
| 116 | static void MooMirroring(void)\r |
| 117 | {\r |
| 118 | if(mirrortodo<0x4)\r |
| 119 | SetupCartMirroring(mirrortodo,1,0);\r |
| 120 | else if(mirrortodo==0x4)\r |
| 121 | {\r |
| 122 | SetupCartMirroring(4,1,exntar);\r |
| 123 | AddExState(exntar, 2048, 0,"EXNR");\r |
| 124 | }\r |
| 125 | else\r |
| 126 | SetupCartMirroring(0,0,0);\r |
| 127 | }\r |
| 128 | \r |
| 129 | static int DoMirroring(int fp)\r |
| 130 | {\r |
| 131 | uint8 t;\r |
| 132 | t=FCEU_fgetc(fp);\r |
| 133 | mirrortodo=t;\r |
| 134 | \r |
| 135 | {\r |
| 136 | static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};\r |
| 137 | if(t<6)\r |
| 138 | FCEU_printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);\r |
| 139 | }\r |
| 140 | return(1);\r |
| 141 | }\r |
| 142 | \r |
| 143 | static int NAME(int fp)\r |
| 144 | {\r |
| 145 | char namebuf[100];\r |
| 146 | int index;\r |
| 147 | int t;\r |
| 148 | \r |
| 149 | FCEU_printf(" Name: ");\r |
| 150 | index=0;\r |
| 151 | \r |
| 152 | while((t=FCEU_fgetc(fp))>0)\r |
| 153 | if(index<99)\r |
| 154 | namebuf[index++]=t;\r |
| 155 | \r |
| 156 | namebuf[index]=0;\r |
| 157 | FCEU_printf("%s\n",namebuf);\r |
| 158 | \r |
| 159 | if(!GameInfo->name)\r |
| 160 | {\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 |
| 163 | }\r |
| 164 | return(1);\r |
| 165 | }\r |
| 166 | static int DINF(int fp)\r |
| 167 | {\r |
| 168 | char name[100], method[100];\r |
| 169 | uint8 d, m;\r |
| 170 | uint16 y;\r |
| 171 | int t;\r |
| 172 | \r |
| 173 | if(FCEU_fread(name,1,100,fp)!=100)\r |
| 174 | return(0);\r |
| 175 | if((t=FCEU_fgetc(fp))==EOF) return(0);\r |
| 176 | d=t;\r |
| 177 | if((t=FCEU_fgetc(fp))==EOF) return(0);\r |
| 178 | m=t;\r |
| 179 | if((t=FCEU_fgetc(fp))==EOF) return(0);\r |
| 180 | y=t;\r |
| 181 | if((t=FCEU_fgetc(fp))==EOF) return(0);\r |
| 182 | y|=t<<8;\r |
| 183 | if(FCEU_fread(method,1,100,fp)!=100)\r |
| 184 | return(0);\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 |
| 188 | {\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 |
| 192 | }\r |
| 193 | return(1);\r |
| 194 | }\r |
| 195 | \r |
| 196 | static int CTRL(int fp)\r |
| 197 | {\r |
| 198 | int t;\r |
| 199 | \r |
| 200 | if((t=FCEU_fgetc(fp))==EOF)\r |
| 201 | return(0);\r |
| 202 | /* The information stored in this byte isn't very helpful, but it's\r |
| 203 | better than nothing...maybe.\r |
| 204 | */\r |
| 205 | \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 |
| 208 | \r |
| 209 | if(t&2) GameInfo->input[1]=SI_ZAPPER;\r |
| 210 | //else if(t&0x10) GameInfo->input[1]=SI_POWERPAD;\r |
| 211 | \r |
| 212 | return(1);\r |
| 213 | }\r |
| 214 | \r |
| 215 | static int TVCI(int fp)\r |
| 216 | {\r |
| 217 | int t;\r |
| 218 | if( (t=FCEU_fgetc(fp)) ==EOF)\r |
| 219 | return(0);\r |
| 220 | if(t<=2)\r |
| 221 | {\r |
| 222 | char *stuffo[3]={"NTSC","PAL","NTSC and PAL"};\r |
| 223 | if(t==0)\r |
| 224 | {\r |
| 225 | GameInfo->vidsys=GIV_NTSC;\r |
| 226 | FCEUI_SetVidSystem(0);\r |
| 227 | }\r |
| 228 | else if(t==1)\r |
| 229 | {\r |
| 230 | GameInfo->vidsys=GIV_PAL;\r |
| 231 | FCEUI_SetVidSystem(1);\r |
| 232 | }\r |
| 233 | FCEU_printf(" TV Standard Compatibility: %s\n",stuffo[t]);\r |
| 234 | }\r |
| 235 | return(1);\r |
| 236 | }\r |
| 237 | \r |
| 238 | static int EnableBattery(int fp)\r |
| 239 | {\r |
| 240 | FCEU_printf(" Battery-backed.\n");\r |
| 241 | if(FCEU_fgetc(fp)==EOF)\r |
| 242 | return(0);\r |
| 243 | UNIFCart.battery=1;\r |
| 244 | return(1);\r |
| 245 | }\r |
| 246 | \r |
| 247 | static int LoadPRG(int fp)\r |
| 248 | {\r |
| 249 | int z,t;\r |
| 250 | z=uchead.ID[3]-'0';\r |
| 251 | \r |
| 252 | if(z<0 || z>15)\r |
| 253 | return(0);\r |
| 254 | FCEU_printf(" PRG ROM %d size: %d",z,(int) uchead.info);\r |
| 255 | if(malloced[z])\r |
| 256 | free(malloced[z]);\r |
| 257 | t=FixRomSize(uchead.info,2048);\r |
| 258 | if(!(malloced[z]=(uint8 *)FCEU_malloc(t)))\r |
| 259 | return(0);\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 |
| 263 | {\r |
| 264 | FCEU_printf("Read Error!\n");\r |
| 265 | return(0);\r |
| 266 | }\r |
| 267 | else\r |
| 268 | FCEU_printf("\n");\r |
| 269 | \r |
| 270 | SetupCartPRGMapping(z,malloced[z],t,0);\r |
| 271 | return(1);\r |
| 272 | }\r |
| 273 | \r |
| 274 | static int SetBoardName(int fp)\r |
| 275 | {\r |
| 276 | if(!(boardname=(uint8 *)FCEU_malloc(uchead.info+1)))\r |
| 277 | return(0);\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 |
| 283 | sboardname+=4;\r |
| 284 | return(1);\r |
| 285 | }\r |
| 286 | \r |
| 287 | static int LoadCHR(int fp)\r |
| 288 | {\r |
| 289 | int z,t;\r |
| 290 | z=uchead.ID[3]-'0';\r |
| 291 | if(z<0 || z>15)\r |
| 292 | return(0);\r |
| 293 | FCEU_printf(" CHR ROM %d size: %d",z,(int) uchead.info);\r |
| 294 | if(malloced[16+z])\r |
| 295 | free(malloced[16+z]);\r |
| 296 | t=FixRomSize(uchead.info,8192);\r |
| 297 | if(!(malloced[16+z]=(uint8 *)FCEU_malloc(t)))\r |
| 298 | return(0);\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 |
| 302 | {\r |
| 303 | FCEU_printf("Read Error!\n");\r |
| 304 | return(0);\r |
| 305 | }\r |
| 306 | else\r |
| 307 | FCEU_printf("\n");\r |
| 308 | \r |
| 309 | SetupCartCHRMapping(z,malloced[16+z],t,0);\r |
| 310 | return(1);\r |
| 311 | }\r |
| 312 | \r |
| 313 | \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 |
| 318 | \r |
| 319 | static BMAPPING bmap[] = {\r |
| 320 | \r |
| 321 | /* Sachen Carts */\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 | \r |
| 338 | // /* AVE carts. */\r |
| 339 | // { "MB-91", MB91_Init,0}, // DeathBots\r |
| 340 | // { "NINA-06", NINA06_Init,0}, // F-15 City War\r |
| 341 | // { "NINA-03", NINA03_Init,0}, // Tiles of Fate\r |
| 342 | // { "NINA-001", NINA001_Init,0}, // Impossible Mission 2\r |
| 343 | \r |
| 344 | { "ANROM", ANROM_Init,0},\r |
| 345 | \r |
| 346 | { "HKROM", HKROM_Init,0},\r |
| 347 | \r |
| 348 | { "EWROM", EWROM_Init,0},\r |
| 349 | { "EKROM", EKROM_Init,0},\r |
| 350 | { "ELROM", ELROM_Init,0},\r |
| 351 | { "ETROM", ETROM_Init,0},\r |
| 352 | \r |
| 353 | { "SAROM", SAROM_Init,0},\r |
| 354 | { "SBROM", SBROM_Init,0},\r |
| 355 | { "SCROM", SCROM_Init,0},\r |
| 356 | { "SEROM", SEROM_Init,0},\r |
| 357 | { "SGROM", SGROM_Init,0},\r |
| 358 | { "SKROM", SKROM_Init,0},\r |
| 359 | { "SLROM", SLROM_Init,0},\r |
| 360 | { "SL1ROM", SL1ROM_Init,0},\r |
| 361 | { "SNROM", SNROM_Init,0},\r |
| 362 | { "SOROM", SOROM_Init,0},\r |
| 363 | \r |
| 364 | { "TGROM", TGROM_Init,0},\r |
| 365 | { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4},\r |
| 366 | \r |
| 367 | { "TBROM", TBROM_Init,0},\r |
| 368 | { "TEROM", TEROM_Init,0},\r |
| 369 | { "TFROM", TFROM_Init,0},\r |
| 370 | { "TLROM", TLROM_Init,0},\r |
| 371 | { "TKROM", TKROM_Init,0},\r |
| 372 | { "TSROM", TSROM_Init,0},\r |
| 373 | \r |
| 374 | { "TLSROM", TLSROM_Init,0},\r |
| 375 | { "TKSROM", TKSROM_Init,0},\r |
| 376 | { "TQROM", TQROM_Init,0},\r |
| 377 | { "TVROM", TLROM_Init,BMCFLAG_FORCE4},\r |
| 378 | \r |
| 379 | { "NTBROM", Mapper68_Init,0},\r |
| 380 | \r |
| 381 | { "CPROM", CPROM_Init,BMCFLAG_16KCHRR},\r |
| 382 | { "CNROM", CNROM_Init,0},\r |
| 383 | { "NROM", NROM_Init,0 }, //NROM256_Init,0 },\r |
| 384 | { "NROM-128", NROM_Init,0 }, //NROM128_Init,0 },\r |
| 385 | { "NROM-256", NROM_Init,0 }, //NROM256_Init,0 },\r |
| 386 | { "RROM", NROM_Init,0 }, //NROM128_Init,0 },\r |
| 387 | { "RROM-128", NROM_Init,0 }, //NROM128_Init,0 },\r |
| 388 | { "MHROM", MHROM_Init,0},\r |
| 389 | { "UNROM", UNROM_Init,0},\r |
| 390 | { "UOROM", UNROM_Init,0},\r |
| 391 | { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init,0},\r |
| 392 | { "MARIO1-MALEE2", MALEE_Init,0},\r |
| 393 | { "3D-BLOCK", UNL3DBlock_Init, 0},\r |
| 394 | { "SMB2J", UNLSMB2J_Init, 0},\r |
| 395 | { "AX5705", UNLAX5705_Init, 0},\r |
| 396 | { "CC-21", UNLCC21_Init,0},\r |
| 397 | { "H2288", UNLH2288_Init,0},\r |
| 398 | { "KOF97", UNLKOF97_Init,0},\r |
| 399 | { "SL1632", UNLSL1632_Init,0},\r |
| 400 | { "SHERO", UNLSHeroes_Init,0},\r |
| 401 | { "8237", UNL8237_Init,0},\r |
| 402 | { "8237A", UNL8237A_Init,0},\r |
| 403 | { "8157", UNL8157_Init,0},\r |
| 404 | { "T-262", BMCT262_Init,0},\r |
| 405 | { "FK23C", BMCFK23C_Init,0},\r |
| 406 | { "A65AS", BMCA65AS_Init,0},\r |
| 407 | { "C-N22M", UNLCN22M_Init,0},\r |
| 408 | { "EDU2000", UNLEDU2000_Init,0},\r |
| 409 | { "603-5052", UNL6035052_Init,0},\r |
| 410 | { "N625092", UNLN625092_Init,0},\r |
| 411 | { "Supervision16in1", Supervision16_Init,0},\r |
| 412 | { "NovelDiamond9999999in1", Novel_Init,0},\r |
| 413 | { "Super24in1SC03", Super24_Init,0},\r |
| 414 | { "64in1NoRepeat", BMC64in1nr_Init, 0},\r |
| 415 | { "13in1JY110", BMC13in1JY110_Init, 0},\r |
| 416 | { "70in1", BMC70in1_Init, 0},\r |
| 417 | { "70in1B", BMC70in1B_Init, 0},\r |
| 418 | { "D1038", BMCD1038_Init, 0},\r |
| 419 | { "GK-192", BMCGK192_Init, 0},\r |
| 420 | { "SuperHIK8in1", Mapper45_Init,0},\r |
| 421 | { "22211", UNL22211_Init,0},\r |
| 422 | { "TF1201", UNLTF1201_Init, 0},\r |
| 423 | { "GS-2004", BMCGS2004_Init, 0},\r |
| 424 | { "GS-2013", BMCGS2013_Init, 0},\r |
| 425 | { "KS7032", UNLKS7032_Init, 0},\r |
| 426 | { "T-230", UNLT230_Init, 0},\r |
| 427 | { "190in1", BMC190in1_Init, 0},\r |
| 428 | { "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0},\r |
| 429 | { "BS-5",BMCBS5_Init, 0},\r |
| 430 | { "411120-C",BMC411120C_Init, 0},\r |
| 431 | { "830118C",BMC830118C_Init, 0},\r |
| 432 | { "T-227-1",BMCT2271_Init,0},\r |
| 433 | \r |
| 434 | { "DREAMTECH01", DreamTech01_Init,0},\r |
| 435 | { "KONAMI-QTAI", Mapper190_Init,0},\r |
| 436 | \r |
| 437 | { "DANCE", UNLDANCE_Init,0},\r |
| 438 | { "OneBus", UNLOneBus_Init,0},\r |
| 439 | { "SC-127", UNLSC127_Init,0},\r |
| 440 | \r |
| 441 | { "TEK90", Mapper90_Init,0},\r |
| 442 | \r |
| 443 | { "FK23C", BMCFK23C_Init,BMCFLAG_EXPCHRR},\r |
| 444 | { "FK23CA", BMCFK23CA_Init,BMCFLAG_EXPCHRR},\r |
| 445 | \r |
| 446 | {0,0,0}\r |
| 447 | };\r |
| 448 | \r |
| 449 | static BFMAPPING bfunc[] = {\r |
| 450 | { "CTRL", CTRL },\r |
| 451 | { "TVCI", TVCI },\r |
| 452 | { "BATR", EnableBattery },\r |
| 453 | { "MIRR", DoMirroring },\r |
| 454 | { "PRG", LoadPRG },\r |
| 455 | { "CHR", LoadCHR },\r |
| 456 | { "NAME", NAME },\r |
| 457 | { "MAPR", SetBoardName },\r |
| 458 | { "DINF", DINF },\r |
| 459 | { 0, 0 }\r |
| 460 | };\r |
| 461 | \r |
| 462 | int LoadUNIFChunks(int fp)\r |
| 463 | {\r |
| 464 | int x;\r |
| 465 | int t;\r |
| 466 | for(;;)\r |
| 467 | {\r |
| 468 | t=FCEU_fread(&uchead,1,4,fp);\r |
| 469 | if(t<4)\r |
| 470 | {\r |
| 471 | if(t>0)\r |
| 472 | return 0;\r |
| 473 | return 1;\r |
| 474 | }\r |
| 475 | if(!(FCEU_read32le(&uchead.info,fp)))\r |
| 476 | return 0;\r |
| 477 | t=0;\r |
| 478 | x=0;\r |
| 479 | //printf("Funky: %s\n",((uint8 *)&uchead));\r |
| 480 | while(bfunc[x].name)\r |
| 481 | {\r |
| 482 | if(!memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name)))\r |
| 483 | {\r |
| 484 | if(!bfunc[x].init(fp))\r |
| 485 | return 0;\r |
| 486 | t=1;\r |
| 487 | break;\r |
| 488 | }\r |
| 489 | x++;\r |
| 490 | }\r |
| 491 | if(!t)\r |
| 492 | if(FCEU_fseek(fp,uchead.info,SEEK_CUR)<0)\r |
| 493 | return(0);\r |
| 494 | }\r |
| 495 | }\r |
| 496 | \r |
| 497 | static int InitializeBoard(void)\r |
| 498 | {\r |
| 499 | int x=0;\r |
| 500 | \r |
| 501 | if(!sboardname) return(0);\r |
| 502 | \r |
| 503 | while(bmap[x].name)\r |
| 504 | {\r |
| 505 | if(!strcmp((char *)sboardname,(char *)bmap[x].name))\r |
| 506 | {\r |
| 507 | if(!malloced[16])\r |
| 508 | {\r |
| 509 | if(bmap[x].flags & BMCFLAG_16KCHRR)\r |
| 510 | CHRRAMSize = 16384;\r |
| 511 | else if(bmap[x].flags & BMCFLAG_32KCHRR)\r |
| 512 | CHRRAMSize = 32768;\r |
| 513 | else if(bmap[x].flags & BMCFLAG_EXPCHRR)\r |
| 514 | CHRRAMSize = 128 * 1024;\r |
| 515 | else\r |
| 516 | CHRRAMSize = 8192;\r |
| 517 | if((UNIFchrrama=(uint8 *)FCEU_malloc(CHRRAMSize)))\r |
| 518 | {\r |
| 519 | SetupCartCHRMapping(0,UNIFchrrama,CHRRAMSize,1);\r |
| 520 | AddExState(UNIFchrrama, CHRRAMSize, 0,"CHRR");\r |
| 521 | }\r |
| 522 | else\r |
| 523 | return(-1);\r |
| 524 | }\r |
| 525 | if(bmap[x].flags&BMCFLAG_FORCE4)\r |
| 526 | mirrortodo=4;\r |
| 527 | MooMirroring();\r |
| 528 | bmap[x].init(&UNIFCart);\r |
| 529 | return(1);\r |
| 530 | }\r |
| 531 | x++;\r |
| 532 | }\r |
| 533 | FCEU_PrintError("Board type not supported.");\r |
| 534 | return(0);\r |
| 535 | }\r |
| 536 | \r |
| 537 | static void UNIFGI(int h, void *param)\r |
| 538 | {\r |
| 539 | switch(h)\r |
| 540 | {\r |
| 541 | case GI_RESETSAVE:\r |
| 542 | //FCEU_ClearGameSave(&UNIFCart);\r |
| 543 | break;\r |
| 544 | \r |
| 545 | case GI_RESETM2:\r |
| 546 | if(UNIFCart.Reset)\r |
| 547 | UNIFCart.Reset();\r |
| 548 | break;\r |
| 549 | case GI_POWER:\r |
| 550 | if(UNIFCart.Power)\r |
| 551 | UNIFCart.Power();\r |
| 552 | if(UNIFchrrama) memset(UNIFchrrama,0,8192);\r |
| 553 | break;\r |
| 554 | case GI_CLOSE:\r |
| 555 | FCEU_SaveGameSave(&UNIFCart);\r |
| 556 | if(UNIFCart.Close)\r |
| 557 | UNIFCart.Close();\r |
| 558 | FreeUNIF();\r |
| 559 | break;\r |
| 560 | case GI_INFOSTRING:\r |
| 561 | {\r |
| 562 | char board[24];\r |
| 563 | strncpy(board, (char *)sboardname, 20);\r |
| 564 | board[20] = 0;\r |
| 565 | sprintf(param, "UNIF, %s, %s%s", board, PAL?"PAL":"NTSC", UNIFCart.battery?", BB":"");\r |
| 566 | }\r |
| 567 | break;\r |
| 568 | }\r |
| 569 | }\r |
| 570 | \r |
| 571 | int UNIFLoad(const char *name, int fp)\r |
| 572 | {\r |
| 573 | FCEU_fseek(fp,0,SEEK_SET);\r |
| 574 | FCEU_fread(&unhead,1,4,fp);\r |
| 575 | if(memcmp(&unhead,"UNIF",4))\r |
| 576 | return 0;\r |
| 577 | \r |
| 578 | ResetCartMapping();\r |
| 579 | \r |
| 580 | ResetExState(0,0);\r |
| 581 | ResetUNIF();\r |
| 582 | if(!FCEU_read32le(&unhead.info,fp))\r |
| 583 | goto aborto;\r |
| 584 | if(FCEU_fseek(fp,0x20,SEEK_SET)<0)\r |
| 585 | goto aborto;\r |
| 586 | if(!LoadUNIFChunks(fp))\r |
| 587 | goto aborto;\r |
| 588 | {\r |
| 589 | int x;\r |
| 590 | struct md5_context md5;\r |
| 591 | \r |
| 592 | md5_starts(&md5);\r |
| 593 | \r |
| 594 | for(x=0;x<32;x++)\r |
| 595 | if(malloced[x])\r |
| 596 | {\r |
| 597 | md5_update(&md5,malloced[x],mallocedsizes[x]);\r |
| 598 | }\r |
| 599 | md5_finish(&md5,UNIFCart.MD5);\r |
| 600 | FCEU_printf(" ROM MD5: 0x");\r |
| 601 | for(x=0;x<16;x++)\r |
| 602 | FCEU_printf("%02x",UNIFCart.MD5[x]);\r |
| 603 | FCEU_printf("\n");\r |
| 604 | memcpy(&GameInfo->MD5,&UNIFCart.MD5,sizeof(UNIFCart.MD5));\r |
| 605 | }\r |
| 606 | \r |
| 607 | if(!InitializeBoard())\r |
| 608 | goto aborto;\r |
| 609 | \r |
| 610 | FCEU_LoadGameSave(&UNIFCart);\r |
| 611 | \r |
| 612 | //strcpy(LoadedRomFName,name); //For the debugger list\r |
| 613 | GameInterface=UNIFGI;\r |
| 614 | return 1;\r |
| 615 | \r |
| 616 | aborto:\r |
| 617 | \r |
| 618 | FreeUNIF();\r |
| 619 | ResetUNIF();\r |
| 620 | \r |
| 621 | \r |
| 622 | return 0;\r |
| 623 | }\r |