memory.cpp
1 /*****************************************************************************\ 2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 This file is licensed under the Snes9x License. 4 For further information, consult the LICENSE file in the root directory. 5 \*****************************************************************************/ 6 7 #include <Arduino.h> 8 9 #include "snes9x.h" 10 #include "memory.h" 11 #include "apu.h" 12 #include "controls.h" 13 #include "hacks.h" 14 15 CMemory Memory; 16 uint32 OpenBus = 0; 17 18 #define match_nn(str) (strncmp(Memory.ROMName, (str), strlen((str))) == 0) 19 20 static int First512BytesCountZeroes(void) 21 { 22 int zeroCount = 0; 23 for (int i = 0; i < 512; i++) 24 { 25 if (Memory.ROM[i] == 0) 26 zeroCount++; 27 } 28 return zeroCount; 29 } 30 31 static void sanitize(char *b, int size) 32 { 33 for (int pos = 0; pos < size; pos++) 34 { 35 if (b[pos] == 0) 36 continue; 37 if (b[pos] < 32 || b[pos] > 126) 38 b[pos] = '_'; 39 } 40 b[size - 1] = 0; 41 } 42 43 static bool8 allASCII (uint8 *b, int size) 44 { 45 for (int i = 0; i < size; i++) 46 { 47 if (b[i] < 32 || b[i] > 126) 48 return (FALSE); 49 } 50 51 return (TRUE); 52 } 53 54 static void ShowInfoString (void) 55 { 56 const char *contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" }; 57 char contentstr[20], sizestr[20], sramstr[20]; 58 59 bool8 isChecksumOK = (Memory.ROMChecksum + Memory.ROMComplementChecksum == 0xffff) & 60 (Memory.ROMChecksum == Memory.CalculatedChecksum); 61 62 if (!isChecksumOK || ((uint32) Memory.CalculatedSize > (uint32) (((1 << (Memory.ROMSize - 7)) * 128) * 1024))) 63 { 64 // Use yellow tint to indicate corrupted ROM. 65 Settings.DisplayColor = BUILD_PIXEL(31, 31, 0); 66 } 67 else if (Memory.ROMIsPatched) 68 { 69 // Use slight blue tint to indicate ROM was patched. 70 Settings.DisplayColor = BUILD_PIXEL(26, 26, 31); 71 } 72 else 73 { 74 Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); 75 } 76 77 strcpy(contentstr, contents[(Memory.ROMType & 0xf) % 3]); 78 79 if (Settings.DSP == 1) 80 strcat(contentstr, "+DSP-1"); 81 else if (Settings.DSP == 2) 82 strcat(contentstr, "+DSP-2"); 83 84 if (Memory.ROMSize < 7 || Memory.ROMSize - 7 > 23) 85 strcpy(sizestr, "Corrupt"); 86 else 87 sprintf(sizestr, "%dMbits", 1 << (Memory.ROMSize - 7)); 88 89 if (Memory.SRAMSize > 16) 90 strcpy(sramstr, "Corrupt"); 91 else 92 sprintf(sramstr, "%dKbits", 8 * (Memory.SRAMMask + 1) / 1024); 93 94 sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X", 95 Memory.ROMName, 96 isChecksumOK ? "checksum ok" : "bad checksum", 97 Memory.HiROM ? "HiROM" : "LoROM", 98 sizestr, 99 contentstr, 100 (Settings.Region == S9X_PAL) ? "PAL" : "NTSC", 101 sramstr, 102 Memory.ROMId, 103 Memory.ROMCRC32); 104 105 S9xMessage(S9X_INFO, S9X_ROM_INFO, String); 106 } 107 108 static uint32 map_mirror (uint32 size, uint32 pos) 109 { 110 // from bsnes 111 if (size == 0) 112 return (0); 113 if (pos < size) 114 return (pos); 115 116 uint32 mask = 1 << 31; 117 while (!(pos & mask)) 118 mask >>= 1; 119 120 if (size <= (pos & mask)) 121 return (map_mirror(size, pos - mask)); 122 else 123 return (mask + map_mirror(size - mask, pos - mask)); 124 } 125 126 static void map_lorom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) 127 { 128 uint32 c, i, p, addr; 129 130 for (c = bank_s; c <= bank_e; c++) 131 { 132 for (i = addr_s; i <= addr_e; i += 0x1000) 133 { 134 p = (c << 4) | (i >> 12); 135 addr = (c & 0x7f) * 0x8000; 136 Memory.ReadMap[p] = Memory.ROM + map_mirror(size, addr) - (i & 0x8000); 137 } 138 } 139 } 140 141 static void map_hirom (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint32 size) 142 { 143 uint32 c, i, p, addr; 144 145 for (c = bank_s; c <= bank_e; c++) 146 { 147 for (i = addr_s; i <= addr_e; i += 0x1000) 148 { 149 p = (c << 4) | (i >> 12); 150 addr = c << 16; 151 Memory.ReadMap[p] = Memory.ROM + map_mirror(size, addr); 152 } 153 } 154 } 155 156 static void map_space (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, uint8 *data) 157 { 158 uint32 c, i, p; 159 160 for (c = bank_s; c <= bank_e; c++) 161 { 162 for (i = addr_s; i <= addr_e; i += 0x1000) 163 { 164 p = (c << 4) | (i >> 12); 165 Memory.ReadMap[p] = data; 166 Memory.WriteMap[p] = data; 167 } 168 } 169 } 170 171 static void map_index (uint32 bank_s, uint32 bank_e, uint32 addr_s, uint32 addr_e, int index, int type) 172 { 173 uint32 c, i, p; 174 175 for (c = bank_s; c <= bank_e; c++) 176 { 177 for (i = addr_s; i <= addr_e; i += 0x1000) 178 { 179 p = (c << 4) | (i >> 12); 180 Memory.ReadMap[p] = (uint8 *) (pint) index; 181 Memory.WriteMap[p] = (uint8 *) (pint) index; 182 } 183 } 184 } 185 186 static void Map_Initialize (void) 187 { 188 for (int c = 0; c < MEMMAP_NUM_BLOCKS; c++) 189 { 190 Memory.ReadMap[c] = (uint8 *) MAP_NONE; 191 Memory.WriteMap[c] = (uint8 *) MAP_NONE; 192 } 193 194 // will be overwritten 195 map_space(0x00, 0x3f, 0x0000, 0x1fff, Memory.RAM); 196 map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); 197 map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); 198 map_space(0x80, 0xbf, 0x0000, 0x1fff, Memory.RAM); 199 map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O); 200 map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O); 201 } 202 203 static void Map_Finalize (void) 204 { 205 // Map Work RAM 206 map_space(0x7e, 0x7e, 0x0000, 0xffff, Memory.RAM); 207 map_space(0x7f, 0x7f, 0x0000, 0xffff, Memory.RAM + 0x10000); 208 } 209 210 static void Map_DSP (void) 211 { 212 switch (DSP0.maptype) 213 { 214 case M_DSP1_LOROM_S: 215 map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); 216 map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O); 217 break; 218 219 case M_DSP1_LOROM_L: 220 map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); 221 map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); 222 break; 223 224 case M_DSP1_HIROM: 225 map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); 226 map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O); 227 break; 228 229 case M_DSP2_LOROM: 230 map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); 231 map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); 232 map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O); 233 map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O); 234 break; 235 } 236 } 237 238 static void Map_LoROMMap (void) 239 { 240 Map_Initialize(); 241 242 map_lorom(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize); 243 map_lorom(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize); 244 map_lorom(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize); 245 map_lorom(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize); 246 247 if (Settings.DSP) 248 Map_DSP(); 249 250 if (Memory.SRAMSize > 0) 251 { 252 uint32 hi = (Memory.ROMSize > 11 || Memory.SRAMSize > 5) ? 0x7fff : 0xffff; 253 map_index(0x70, 0x7d, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM); 254 map_index(0xf0, 0xff, 0x0000, hi, MAP_LOROM_SRAM, MAP_TYPE_RAM); 255 } 256 257 Map_Finalize(); 258 } 259 260 static void Map_HiROMMap (void) 261 { 262 Map_Initialize(); 263 264 map_hirom(0x00, 0x3f, 0x8000, 0xffff, Memory.CalculatedSize); 265 map_hirom(0x40, 0x7f, 0x0000, 0xffff, Memory.CalculatedSize); 266 map_hirom(0x80, 0xbf, 0x8000, 0xffff, Memory.CalculatedSize); 267 map_hirom(0xc0, 0xff, 0x0000, 0xffff, Memory.CalculatedSize); 268 269 if (Settings.DSP) 270 Map_DSP(); 271 272 map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); 273 map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM); 274 275 Map_Finalize(); 276 } 277 278 static uint16 checksum_calc_sum (uint8 *data, uint32 length) 279 { 280 uint16 sum = 0; 281 282 for (size_t i = 0; i < length; i++) 283 sum += data[i]; 284 285 return (sum); 286 } 287 288 static uint16 checksum_mirror_sum (uint8 *start, uint32 *length, uint32 mask) 289 { 290 // from NSRT 291 while (!(*length & mask) && mask) 292 mask >>= 1; 293 294 uint16 part1 = checksum_calc_sum(start, mask); 295 uint16 part2 = 0; 296 297 uint32 next_length = *length - mask; 298 if (next_length) 299 { 300 part2 = checksum_mirror_sum(start + mask, &next_length, mask >> 1); 301 302 while (next_length < mask) 303 { 304 next_length += next_length; 305 part2 += part2; 306 } 307 308 *length = mask + mask; 309 } 310 311 return (part1 + part2); 312 } 313 314 static uint16 CalcChecksum (uint8 *data, uint32 length) 315 { 316 if (length & 0x7fff) 317 return checksum_calc_sum(data, length); 318 else 319 return checksum_mirror_sum(data, &length, 0x800000); 320 } 321 322 static int ScoreHiROM (void) 323 { 324 uint8 *buf = Memory.ROM + 0xff00; 325 int score = 0; 326 327 if (buf[0xd5] & 0x1) 328 score += 2; 329 330 // Mode23 is SA-1 331 if (buf[0xd5] == 0x23) 332 score -= 2; 333 334 if (buf[0xd4] == 0x20) 335 score += 2; 336 337 if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) 338 { 339 score += 2; 340 if (0 != (buf[0xde] + (buf[0xdf] << 8))) 341 score++; 342 } 343 344 if (buf[0xda] == 0x33) 345 score += 2; 346 347 if ((buf[0xd5] & 0xf) < 4) 348 score += 2; 349 350 if (!(buf[0xfd] & 0x80)) 351 score -= 6; 352 353 if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) 354 score -= 2; // reduced after looking at a scan by Cowering 355 356 if (Memory.CalculatedSize > 1024 * 1024 * 3) 357 score += 4; 358 359 if ((1 << (buf[0xd7] - 7)) > 48) 360 score -= 1; 361 362 if (!allASCII(&buf[0xb0], 6)) 363 score -= 1; 364 365 if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) 366 score -= 1; 367 368 return (score); 369 } 370 371 static int ScoreLoROM (void) 372 { 373 uint8 *buf = Memory.ROM + 0x7f00; 374 int score = 0; 375 376 if (!(buf[0xd5] & 0x1)) 377 score += 3; 378 379 // Mode23 is SA-1 380 if (buf[0xd5] == 0x23) 381 score += 2; 382 383 if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff) 384 { 385 score += 2; 386 if (0 != (buf[0xde] + (buf[0xdf] << 8))) 387 score++; 388 } 389 390 if (buf[0xda] == 0x33) 391 score += 2; 392 393 if ((buf[0xd5] & 0xf) < 4) 394 score += 2; 395 396 if (!(buf[0xfd] & 0x80)) 397 score -= 6; 398 399 if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0) 400 score -= 2; // reduced per Cowering suggestion 401 402 if (Memory.CalculatedSize <= 1024 * 1024 * 16) 403 score += 2; 404 405 if ((1 << (buf[0xd7] - 7)) > 48) 406 score -= 1; 407 408 if (!allASCII(&buf[0xb0], 6)) 409 score -= 1; 410 411 if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1)) 412 score -= 1; 413 414 return (score); 415 } 416 417 int ApplyGameSpecificHacks (void) 418 { 419 int applied = 0; 420 421 for (const s9x_hack_t *hack = &GameHacks[0]; hack->checksum; hack++) 422 { 423 if (hack->checksum == Memory.ROMCRC32) 424 { 425 printf("Applying patch %s: '%s'\n", hack->name, hack->patch); 426 427 char *ptr = (char*)hack->patch; 428 429 while (ptr && *ptr) 430 { 431 int offset = strtol(ptr, &ptr, 16); 432 int value = strtol(ptr + 1, &ptr, 16); 433 434 if ((ptr = strchr(ptr, ','))) 435 ptr++; 436 437 // We only care about opcode 0x42 for now 438 if ((value != 0x42) && ((value >> 8) != 0x42)) 439 { 440 printf(" - Warning: Ignoring patch %X=%X...\n", offset, value); 441 } 442 else if (offset < 1 || offset >= Memory.CalculatedSize) 443 { 444 printf(" - Warning: Offset %d (%X) is out of range...\n", offset, offset); 445 } 446 else if (value & 0xFF00) // 16 bit replacement 447 { 448 printf(" - Applying 16bit patch %X=%X\n", offset, value); 449 // Memory.ROM[offset] = (value >> 8) & 0xFF; 450 // Memory.ROM[offset + 1] = value & 0xFF; 451 applied++; 452 } 453 else // 8 bit replacement 454 { 455 printf(" - Applying 8bit patch %X=%X\n", offset, value); 456 // Memory.ROM[offset] = value; 457 applied++; 458 } 459 } 460 } 461 } 462 463 return applied; 464 } 465 466 static bool8 InitROM () 467 { 468 if (!Memory.ROM || Memory.ROM_SIZE < 0x200) 469 return (FALSE); 470 471 if ((Memory.ROM_SIZE & 0x7FF) == 512 || First512BytesCountZeroes() > 400) 472 { 473 emu_printf("Found ROM file header (and ignored it).\n"); 474 memmove(Memory.ROM, Memory.ROM + 512, Memory.ROM_SIZE - 512); 475 Memory.ROM_SIZE -= 512; 476 } 477 478 Memory.CalculatedSize = ((Memory.ROM_SIZE + 0x1fff) / 0x2000) * 0x2000; 479 480 //// these two games fail to be detected 481 if (strncmp((char *) &Memory.ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 || 482 (strncmp((char *) &Memory.ROM[0xffc0], "BATMAN--REVENGE JOKER", 21) == 0)) 483 { 484 Memory.LoROM = TRUE; 485 Memory.HiROM = FALSE; 486 } 487 else 488 { 489 Memory.LoROM = (ScoreLoROM() >= ScoreHiROM()); 490 Memory.HiROM = !Memory.LoROM; 491 } 492 493 //// Parse ROM header and read ROM informatoin 494 495 uint8 *RomHeader = Memory.ROM + (Memory.HiROM ? 0xFFB0 : 0x7FB0); 496 497 strncpy(Memory.ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1); 498 sanitize(Memory.ROMName, ROM_NAME_LEN); 499 500 Memory.ROMName[ROM_NAME_LEN - 1] = 0; 501 if (strlen(Memory.ROMName)) 502 { 503 char *p = Memory.ROMName + strlen(Memory.ROMName); 504 if (p > Memory.ROMName + 21 && Memory.ROMName[20] == ' ') 505 p = Memory.ROMName + 21; 506 while (p > Memory.ROMName && *(p - 1) == ' ') 507 p--; 508 *p = 0; 509 } 510 511 Memory.ROMSize = RomHeader[0x27]; 512 Memory.SRAMSize = RomHeader[0x28]; 513 Memory.ROMSpeed = RomHeader[0x25]; 514 Memory.ROMType = RomHeader[0x26]; 515 Memory.ROMRegion = RomHeader[0x29]; 516 Memory.ROMChecksum = RomHeader[0x2E] + (RomHeader[0x2F] << 8); 517 Memory.ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8); 518 519 memmove(Memory.ROMId, &RomHeader[0x02], 4); 520 sanitize(Memory.ROMId, 4); 521 522 //// Detect DSP 1 & 2 523 if (Memory.ROMType == 0x03 || (Memory.ROMType == 0x05 && Memory.ROMSpeed != 0x20)) 524 { 525 Settings.DSP = 1; 526 if (Memory.HiROM) 527 { 528 DSP0.boundary = 0x7000; 529 DSP0.maptype = M_DSP1_HIROM; 530 } 531 else 532 if (Memory.CalculatedSize > 0x100000) 533 { 534 DSP0.boundary = 0x4000; 535 DSP0.maptype = M_DSP1_LOROM_L; 536 } 537 else 538 { 539 DSP0.boundary = 0xc000; 540 DSP0.maptype = M_DSP1_LOROM_S; 541 } 542 543 SetDSP = &DSP1SetByte; 544 GetDSP = &DSP1GetByte; 545 } 546 else 547 if (Memory.ROMType == 0x05 && Memory.ROMSpeed == 0x20) 548 { 549 Settings.DSP = 2; 550 DSP0.boundary = 0x10000; 551 DSP0.maptype = M_DSP2_LOROM; 552 SetDSP = &DSP2SetByte; 553 GetDSP = &DSP2GetByte; 554 } 555 else 556 { 557 Settings.DSP = 0; 558 SetDSP = NULL; 559 GetDSP = NULL; 560 } 561 562 //// SRAM size 563 if (strncmp("HITOMI3 ", Memory.ROMName, 8) == 0) 564 { 565 Memory.SRAMSize = 1; 566 } 567 Memory.SRAMMask = Memory.SRAMSize ? ((1 << (Memory.SRAMSize + 3)) * 128) - 1 : 0; 568 Memory.SRAMBytes = Memory.SRAMSize ? ((1 << (Memory.SRAMSize + 3)) * 128) : 0; 569 if (Memory.SRAMBytes > 0x8000) 570 { 571 emu_printf("\n\nWARNING: Default SRAM size too small!, need bytes"); 572 emu_printi(Memory.SRAMBytes); 573 } 574 575 //// Map memory 576 if (Memory.HiROM) 577 { 578 Map_HiROMMap(); 579 } 580 else 581 { 582 Map_LoROMMap(); 583 } 584 585 //// Checksums 586 Memory.ROMCRC32 = crc32_le(0, Memory.ROM, Memory.CalculatedSize); 587 Memory.CalculatedChecksum = CalcChecksum(Memory.ROM, Memory.CalculatedSize); 588 589 //// ROM Region 590 if ((Memory.ROMRegion >= 2) && (Memory.ROMRegion <= 12)) 591 { 592 Settings.Region = S9X_PAL; 593 Settings.FrameRate = 50; 594 } 595 else 596 { 597 Settings.Region = S9X_NTSC; 598 Settings.FrameRate = 60; 599 } 600 601 // Setup APU timings 602 S9xAPUTimingSetSpeedup(0); 603 604 //// Apply Game hacks 605 if (!Settings.DisableGameSpecificHacks) 606 { 607 ApplyGameSpecificHacks(); 608 } 609 610 //// Show ROM information 611 ShowInfoString(); 612 613 //// Reset system, then we're ready 614 S9xReset(); 615 616 return (TRUE); 617 } 618 619 620 // Public functions 621 622 bool8 S9xMemoryInit (void) 623 { 624 memset(&Memory, 0, sizeof(Memory)); 625 626 Memory.RAM = (uint8 *) emu_Malloc(0x20000); // calloc(1, 0x20000); // 128k 627 Memory.VRAM = (uint8 *) emu_SMalloc(0x10000); //calloc(1, 0x10000); // 64k Malloc? 628 Memory.SRAM = (uint8 *) emu_Malloc(0x8000); //calloc(1, 0x8000); // 32k 629 Memory.ROM_MAX_SIZE = 0x600000; 630 //Memory.ROM = (uint8 *) calloc(1, Memory.ROM_MAX_SIZE); 631 // Note: we don't care if ROM alloc fails. It's just to grab a large heap block 632 // before it gets fragmented. The actual useful alloc is done in S9xLoadROM() 633 634 if (!Memory.RAM || !Memory.SRAM || !Memory.VRAM) 635 { 636 S9xMemoryDeinit(); 637 return (FALSE); 638 } 639 640 return (TRUE); 641 } 642 643 void S9xMemoryDeinit (void) 644 { 645 emu_Free(Memory.RAM); //free(Memory.RAM); 646 emu_Free(Memory.SRAM); //free(Memory.SRAM); 647 emu_Free(Memory.VRAM); // free(Memory.VRAM); 648 emu_SFree(Memory.ROM); //free(Memory.ROM); 649 650 Memory.RAM = NULL; 651 Memory.SRAM = NULL; 652 Memory.VRAM = NULL; 653 Memory.ROM = NULL; 654 } 655 656 657 bool8 S9xLoadROM (const char *filename) 658 { 659 //FILE *stream = fopen(filename, "rb"); 660 //if (!stream) 661 // return (FALSE); 662 663 //fseek(stream, 0, SEEK_END); 664 //Memory.ROM_SIZE = ftell(stream); 665 666 Memory.ROM_SIZE = emu_FileSize((char*)filename); 667 Memory.ROM = (uint8 *) emu_SMalloc(Memory.ROM_SIZE); 668 669 // We shrink if possible because we need all the memory we can get for savestates and buffers 670 //uint8 *temp = (uint8 *)realloc(Memory.ROM, Memory.ROM_SIZE); 671 //if (temp) 672 //{ 673 // Memory.ROM_MAX_SIZE = Memory.ROM_SIZE; 674 // Memory.ROM = temp; 675 //} 676 677 if (!Memory.ROM || Memory.ROM_MAX_SIZE < Memory.ROM_SIZE) 678 { 679 //fclose(stream); 680 return (FALSE); 681 } 682 683 //fseek(stream, 0, SEEK_SET); 684 //fread(Memory.ROM, Memory.ROM_SIZE, 1, stream); 685 //fclose(stream); 686 687 emu_LoadFile((char*)filename, (char*)Memory.ROM, Memory.ROM_SIZE); 688 689 emu_printf("loaded"); 690 return InitROM(); 691 } 692 693 // BPS % UPS % IPS 694 #if 0 695 696 static long ReadInt (Stream *r, unsigned nbytes) 697 { 698 long v = 0; 699 700 while (nbytes--) 701 { 702 int c = r->get_char(); 703 if (c == EOF) 704 return (-1); 705 v = (v << 8) | (c & 0xFF); 706 } 707 708 return (v); 709 } 710 711 static bool8 ReadIPSPatch (Stream *r, long offset, int32 &rom_size) 712 { 713 const int32 IPS_EOF = 0x00454F46l; 714 int32 ofs; 715 char fname[6]; 716 717 fname[5] = 0; 718 for (int i = 0; i < 5; i++) 719 { 720 int c = r->get_char(); 721 if (c == EOF) 722 return (0); 723 fname[i] = (char) c; 724 } 725 726 if (strncmp(fname, "PATCH", 5)) 727 return (0); 728 729 for (;;) 730 { 731 long len, rlen; 732 int rchar; 733 734 ofs = ReadInt(r, 3); 735 if (ofs == -1) 736 return (0); 737 738 if (ofs == IPS_EOF) 739 break; 740 741 ofs -= offset; 742 743 len = ReadInt(r, 2); 744 if (len == -1) 745 return (0); 746 747 if (len) 748 { 749 if (ofs + len > Memory.ROM_SIZE) 750 return (0); 751 752 while (len--) 753 { 754 rchar = r->get_char(); 755 if (rchar == EOF) 756 return (0); 757 Memory.ROM[ofs++] = (uint8) rchar; 758 } 759 760 if (ofs > rom_size) 761 rom_size = ofs; 762 } 763 else 764 { 765 rlen = ReadInt(r, 2); 766 if (rlen == -1) 767 return (0); 768 769 rchar = r->get_char(); 770 if (rchar == EOF) 771 return (0); 772 773 if (ofs + rlen > Memory.ROM_SIZE) 774 return (0); 775 776 while (rlen--) 777 Memory.ROM[ofs++] = (uint8) rchar; 778 779 if (ofs > rom_size) 780 rom_size = ofs; 781 } 782 } 783 784 ofs = ReadInt(r, 3); 785 if (ofs != -1 && ofs - offset < rom_size) 786 rom_size = ofs - offset; 787 788 ROMIsPatched = 1; 789 return (1); 790 } 791 /* 792 void CMemory::CheckForAnyPatch (const char *rom_filename, bool8 header, int32 &rom_size) 793 { 794 ROMIsPatched = false; 795 796 FSTREAM patch_file = NULL; 797 uint32 i; 798 long offset = header ? 512 : 0; 799 int ret; 800 bool flag; 801 char dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1]; 802 const char *n; 803 804 _splitpath(rom_filename, drive, dir, name, ext); 805 806 // IPS 807 808 _makepath(fname, drive, dir, name, "ips"); 809 810 if ((patch_file = OPEN_FSTREAM(fname, "rb")) != NULL) 811 { 812 printf("Using IPS patch %s", fname); 813 814 Stream *s = new fStream(patch_file); 815 ret = ReadIPSPatch(s, offset, rom_size); 816 s->closeStream(); 817 818 if (ret) 819 { 820 printf("!\n"); 821 return; 822 } 823 else 824 printf(" failed!\n"); 825 } 826 827 if (_MAX_EXT > 6) 828 { 829 i = 0; 830 flag = false; 831 832 do 833 { 834 snprintf(ips, 8, "%03d.ips", i); 835 _makepath(fname, drive, dir, name, ips); 836 837 if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) 838 break; 839 840 printf("Using IPS patch %s", fname); 841 842 Stream *s = new fStream(patch_file); 843 ret = ReadIPSPatch(s, offset, rom_size); 844 s->closeStream(); 845 846 if (ret) 847 { 848 printf("!\n"); 849 flag = true; 850 } 851 else 852 { 853 printf(" failed!\n"); 854 break; 855 } 856 } while (++i < 1000); 857 858 if (flag) 859 return; 860 } 861 862 if (_MAX_EXT > 3) 863 { 864 i = 0; 865 flag = false; 866 867 do 868 { 869 snprintf(ips, _MAX_EXT + 2, "ips%d", i); 870 if (strlen(ips) > _MAX_EXT) 871 break; 872 _makepath(fname, drive, dir, name, ips); 873 874 if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) 875 break; 876 877 printf("Using IPS patch %s", fname); 878 879 Stream *s = new fStream(patch_file); 880 ret = ReadIPSPatch(s, offset, rom_size); 881 s->closeStream(); 882 883 if (ret) 884 { 885 printf("!\n"); 886 flag = true; 887 } 888 else 889 { 890 printf(" failed!\n"); 891 break; 892 } 893 } while (++i != 0); 894 895 if (flag) 896 return; 897 } 898 899 if (_MAX_EXT > 2) 900 { 901 i = 0; 902 flag = false; 903 904 do 905 { 906 snprintf(ips, 4, "ip%d", i); 907 _makepath(fname, drive, dir, name, ips); 908 909 if (!(patch_file = OPEN_FSTREAM(fname, "rb"))) 910 break; 911 912 printf("Using IPS patch %s", fname); 913 914 Stream *s = new fStream(patch_file); 915 ret = ReadIPSPatch(s, offset, rom_size); 916 s->closeStream(); 917 918 if (ret) 919 { 920 printf("!\n"); 921 flag = true; 922 } 923 else 924 { 925 printf(" failed!\n"); 926 break; 927 } 928 } while (++i < 10); 929 930 if (flag) 931 return; 932 } 933 934 n = S9xGetFilename(".ips", PATCH_DIR); 935 936 if ((patch_file = OPEN_FSTREAM(n, "rb")) != NULL) 937 { 938 printf("Using IPS patch %s", n); 939 940 Stream *s = new fStream(patch_file); 941 ret = ReadIPSPatch(s, offset, rom_size); 942 s->closeStream(); 943 944 if (ret) 945 { 946 printf("!\n"); 947 return; 948 } 949 else 950 printf(" failed!\n"); 951 } 952 953 if (_MAX_EXT > 6) 954 { 955 i = 0; 956 flag = false; 957 958 do 959 { 960 snprintf(ips, 9, ".%03d.ips", i); 961 n = S9xGetFilename(ips, PATCH_DIR); 962 963 if (!(patch_file = OPEN_FSTREAM(n, "rb"))) 964 break; 965 966 printf("Using IPS patch %s", n); 967 968 Stream *s = new fStream(patch_file); 969 ret = ReadIPSPatch(s, offset, rom_size); 970 s->closeStream(); 971 972 if (ret) 973 { 974 printf("!\n"); 975 flag = true; 976 } 977 else 978 { 979 printf(" failed!\n"); 980 break; 981 } 982 } while (++i < 1000); 983 984 if (flag) 985 return; 986 } 987 988 if (_MAX_EXT > 3) 989 { 990 i = 0; 991 flag = false; 992 993 do 994 { 995 snprintf(ips, _MAX_EXT + 3, ".ips%d", i); 996 if (strlen(ips) > _MAX_EXT + 1) 997 break; 998 n = S9xGetFilename(ips, PATCH_DIR); 999 1000 if (!(patch_file = OPEN_FSTREAM(n, "rb"))) 1001 break; 1002 1003 printf("Using IPS patch %s", n); 1004 1005 Stream *s = new fStream(patch_file); 1006 ret = ReadIPSPatch(s, offset, rom_size); 1007 s->closeStream(); 1008 1009 if (ret) 1010 { 1011 printf("!\n"); 1012 flag = true; 1013 } 1014 else 1015 { 1016 printf(" failed!\n"); 1017 break; 1018 } 1019 } while (++i != 0); 1020 1021 if (flag) 1022 return; 1023 } 1024 1025 if (_MAX_EXT > 2) 1026 { 1027 i = 0; 1028 flag = false; 1029 1030 do 1031 { 1032 snprintf(ips, 5, ".ip%d", i); 1033 n = S9xGetFilename(ips, PATCH_DIR); 1034 1035 if (!(patch_file = OPEN_FSTREAM(n, "rb"))) 1036 break; 1037 1038 printf("Using IPS patch %s", n); 1039 1040 Stream *s = new fStream(patch_file); 1041 ret = ReadIPSPatch(s, offset, rom_size); 1042 s->closeStream(); 1043 1044 if (ret) 1045 { 1046 printf("!\n"); 1047 flag = true; 1048 } 1049 else 1050 { 1051 printf(" failed!\n"); 1052 break; 1053 } 1054 } while (++i < 10); 1055 1056 if (flag) 1057 return; 1058 } 1059 } 1060 */ 1061 #endif