diff --git a/libsnes/libsnes.cpp b/libsnes/libsnes.cpp index 7c47ede1..3a9fa9b9 100644 --- a/libsnes/libsnes.cpp +++ b/libsnes/libsnes.cpp @@ -53,6 +53,21 @@ void snes_set_environment(snes_environment_t cb) environ_cb = cb; } +static void set_environ_timing() +{ + if (environ_cb) + { + snes_system_timing timing; + timing.sample_rate = 32040.5; + if (!Settings.PAL) + timing.fps = 21477272.0 / 357366.0; + else + timing.fps = 21281370.0 / 425568.0; + + environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); + } +} + static void S9xAudioCallback(void*) { // Just pick a big buffer. We won't use it all. @@ -137,10 +152,20 @@ void snes_cheat_set(unsigned, bool, const char*) {} bool snes_load_cartridge_bsx_slotted( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned + const char *, const uint8_t *rom_data, unsigned rom_size, + const char *, const uint8_t *bsx_data, unsigned bsx_size ) { + int loaded = Memory.LoadMultiCartMem(rom_data, rom_size, bsx_data, bsx_size, NULL, NULL); + + if (!loaded) + { + fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); + return false; + } + + set_environ_timing(); + return false; } @@ -153,12 +178,22 @@ bool snes_load_cartridge_bsx( } bool snes_load_cartridge_sufami_turbo( - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned, - const char *, const uint8_t *, unsigned + const char *, const uint8_t *rom_data, unsigned rom_size, + const char *, const uint8_t *sta_data, unsigned sta_size, + const char *, const uint8_t *stb_data, unsigned stb_size ) { - return false; + int loaded = Memory.LoadMultiCartMem(sta_data, sta_size, stb_data, stb_size, rom_data, rom_size); + + if (!loaded) + { + fprintf(stderr, "[libsnes]: Sufami Turbo Rom loading failed...\n"); + return false; + } + + set_environ_timing(); + + return true; } bool snes_load_cartridge_super_game_boy( @@ -435,17 +470,7 @@ bool snes_load_cartridge_normal(const char *, const uint8_t *rom_data, unsigned return false; } - if (environ_cb) - { - snes_system_timing timing; - timing.sample_rate = 32040.5; - if (!Settings.PAL) - timing.fps = 21477272.0 / 357366.0; - else - timing.fps = 21281370.0 / 425568.0; - - environ_cb(SNES_ENVIRONMENT_SET_TIMING, &timing); - } + set_environ_timing(); return true; } @@ -476,9 +501,13 @@ uint8_t* snes_get_memory_data(unsigned type) uint8_t* data; switch(type) { + case SNES_MEMORY_SUFAMI_TURBO_A_RAM: case SNES_MEMORY_CARTRIDGE_RAM: data = Memory.SRAM; break; + case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + data = Multi.sramB; + break; case SNES_MEMORY_CARTRIDGE_RTC: data = RTCData.reg; break; @@ -515,11 +544,15 @@ unsigned snes_get_memory_size(unsigned type) unsigned size; switch(type) { + case SNES_MEMORY_SUFAMI_TURBO_A_RAM: case SNES_MEMORY_CARTRIDGE_RAM: size = (unsigned) (Memory.SRAMSize ? (1 << (Memory.SRAMSize + 3)) * 128 : 0); if (size > 0x20000) size = 0x20000; break; + case SNES_MEMORY_SUFAMI_TURBO_B_RAM: + size = (unsigned) (Multi.cartType && Multi.sramSizeB ? (1 << (Multi.sramSizeB + 3)) * 128 : 0); + break; case SNES_MEMORY_CARTRIDGE_RTC: size = (Settings.SRTC || Settings.SPC7110RTC)?20:0; break; diff --git a/memmap.cpp b/memmap.cpp index 83effdbf..8eb52aec 100644 --- a/memmap.cpp +++ b/memmap.cpp @@ -936,12 +936,12 @@ static void S9xDeinterleaveType1 (int, uint8 *); static void S9xDeinterleaveType2 (int, uint8 *); static void S9xDeinterleaveGD24 (int, uint8 *); static bool8 allASCII (uint8 *, int); -static bool8 is_SufamiTurbo_BIOS (uint8 *, uint32); -static bool8 is_SufamiTurbo_Cart (uint8 *, uint32); -static bool8 is_SameGame_BIOS (uint8 *, uint32); -static bool8 is_SameGame_Add_On (uint8 *, uint32); -static bool8 is_GNEXT_BIOS (uint8 *, uint32); -static bool8 is_GNEXT_Add_On (uint8 *, uint32); +static bool8 is_SufamiTurbo_BIOS (const uint8 *, uint32); +static bool8 is_SufamiTurbo_Cart (const uint8 *, uint32); +static bool8 is_SameGame_BIOS (const uint8 *, uint32); +static bool8 is_SameGame_Add_On (const uint8 *, uint32); +static bool8 is_GNEXT_BIOS (const uint8 *, uint32); +static bool8 is_GNEXT_Add_On (const uint8 *, uint32); static uint32 caCRC32 (uint8 *, uint32, uint32 crc32 = 0xffffffff); static uint32 ReadUPSPointer (const uint8 *, unsigned &, unsigned); static bool8 ReadUPSPatch (Stream *, long, int32 &); @@ -1206,7 +1206,7 @@ static bool8 allASCII (uint8 *b, int size) return (TRUE); } -static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) +static bool8 is_SufamiTurbo_BIOS (const uint8 *data, uint32 size) { if (size == 0x40000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0) @@ -1215,7 +1215,7 @@ static bool8 is_SufamiTurbo_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) +static bool8 is_SufamiTurbo_Cart (const uint8 *data, uint32 size) { if (size >= 0x80000 && size <= 0x100000 && strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0) @@ -1224,7 +1224,7 @@ static bool8 is_SufamiTurbo_Cart (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) +static bool8 is_SameGame_BIOS (const uint8 *data, uint32 size) { if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0) return (TRUE); @@ -1232,7 +1232,7 @@ static bool8 is_SameGame_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) +static bool8 is_SameGame_Add_On (const uint8 *data, uint32 size) { if (size == 0x80000) return (TRUE); @@ -1240,7 +1240,7 @@ static bool8 is_SameGame_Add_On (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_GNEXT_BIOS (uint8 *data, uint32 size) +static bool8 is_GNEXT_BIOS (const uint8 *data, uint32 size) { if (size == 0x180000 && strncmp((char *) (data + 0x7fc0), "SFC SDGUNDAMGNEXT", 17) == 0) return (TRUE); @@ -1248,7 +1248,7 @@ static bool8 is_GNEXT_BIOS (uint8 *data, uint32 size) return (FALSE); } -static bool8 is_GNEXT_Add_On (uint8 *data, uint32 size) +static bool8 is_GNEXT_Add_On (const uint8 *data, uint32 size) { if (size == 0x80000) return (TRUE); @@ -1543,6 +1543,9 @@ bool8 CMemory::LoadROM (const char *filename) if (!totalFileSize) return (FALSE); + + if (!Settings.NoPatch) + CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize); } while(!LoadROMInt(totalFileSize)); @@ -1557,9 +1560,6 @@ bool8 CMemory::LoadROMInt (int32 ROMfillSize) CalculatedSize = 0; ExtendedFormat = NOPE; - if (!Settings.NoPatch) - CheckForAnyPatch(ROMFilename, HeaderCount != 0, ROMfillSize); - int hi_score, lo_score; hi_score = ScoreHiROM(FALSE); @@ -1766,60 +1766,144 @@ bool8 CMemory::LoadROMInt (int32 ROMfillSize) return (TRUE); } +bool8 CMemory::LoadMultiCartMem (const uint8 *sourceA, uint32 sourceASize, + const uint8 *sourceB, uint32 sourceBSize, + const uint8 *bios, uint32 biosSize) +{ + uint32 offset = 0; + ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(&Multi, sizeof(Multi)); + + if(bios) { + if(!is_SufamiTurbo_BIOS(bios,biosSize)) + return FALSE; + + memcpy(ROM,bios,biosSize); + offset+=biosSize; + } + + if(sourceA) { + memcpy(ROM + offset,sourceA,sourceASize); + Multi.cartOffsetA = offset; + Multi.cartSizeA = sourceASize; + offset += sourceASize; + strcpy(Multi.fileNameA,"MemCartA"); + } + + if(sourceB) { + memcpy(ROM + offset,sourceB,sourceBSize); + Multi.cartOffsetB = offset; + Multi.cartSizeB = sourceBSize; + offset += sourceBSize; + strcpy(Multi.fileNameB,"MemCartB"); + } + + return LoadMultiCartInt(); +} + bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) { - bool8 r = TRUE; - - ZeroMemory(ROM, MAX_ROM_SIZE); + ZeroMemory(ROM, MAX_ROM_SIZE); ZeroMemory(&Multi, sizeof(Multi)); Settings.DisplayColor = BUILD_PIXEL(31, 31, 31); SET_UI_COLOR(255, 255, 255); - CalculatedSize = 0; - ExtendedFormat = NOPE; + if (cartB && cartB[0]) + Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); + + if (Multi.cartSizeB) { + strcpy(Multi.fileNameB, cartB); + + if(!Settings.NoPatch) + CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); + + Multi.cartOffsetB = 0x400000; + memcpy(ROM + Multi.cartOffsetB,ROM,Multi.cartSizeB); + } if (cartA && cartA[0]) Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE); - if (Multi.cartSizeA == 0) - { - if (cartB && cartB[0]) - Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); - } + if (Multi.cartSizeA) { + strcpy(Multi.fileNameA, cartA); + + if(!Settings.NoPatch) + CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); + } + + return LoadMultiCartInt(); +} + +bool8 CMemory::LoadMultiCartInt () +{ + bool8 r = TRUE; + + CalculatedSize = 0; + ExtendedFormat = NOPE; if (Multi.cartSizeA) { - if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA)) + if (is_SufamiTurbo_Cart(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 4; else - if (is_SameGame_BIOS(ROM, Multi.cartSizeA)) + if (is_SameGame_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 3; else - if (is_GNEXT_BIOS(ROM, Multi.cartSizeA)) + if (is_GNEXT_BIOS(ROM + Multi.cartOffsetA, Multi.cartSizeA)) Multi.cartType = 5; } else if (Multi.cartSizeB) { - if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) + if (is_SufamiTurbo_Cart(ROM + Multi.cartOffsetB, Multi.cartSizeB)) Multi.cartType = 4; } else Multi.cartType = 4; // assuming BIOS only + + if(Multi.cartType == 4 && Multi.cartOffsetA == 0) { // try to load bios from file + Multi.cartOffsetA = 0x40000; + if(Multi.cartSizeA) + memmove(ROM + Multi.cartOffsetA,ROM,Multi.cartOffsetB - Multi.cartOffsetA); + else // clear cart A so the bios can detect that it's not present + memset(ROM,0,Multi.cartOffsetB); + + FILE *fp; + size_t size; + char path[PATH_MAX + 1]; + + strcpy(path, S9xGetDirectory(BIOS_DIR)); + strcat(path, SLASH_STR); + strcat(path, "STBIOS.bin"); + + fp = fopen(path, "rb"); + if (fp) + { + size = fread((void *) ROM, 1, 0x40000, fp); + fclose(fp); + if (!is_SufamiTurbo_BIOS(ROM, size)) + return (FALSE); + } + else + return (FALSE); + + strcpy(ROMFilename, path); + } + switch (Multi.cartType) { case 4: - r = LoadSufamiTurbo(cartA, cartB); + r = LoadSufamiTurbo(); break; case 3: - r = LoadSameGame(cartA, cartB); + r = LoadSameGame(); break; case 5: - r = LoadGNEXT(cartA, cartB); + r = LoadGNEXT(); break; default: @@ -1832,6 +1916,12 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (FALSE); } + if (Multi.cartSizeA) + strcpy(ROMFilename, Multi.fileNameA); + else + if (Multi.cartSizeB) + strcpy(ROMFilename, Multi.fileNameB); + ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes)); SNESGameFixes.SRAMInitialValue = 0x60; @@ -1847,10 +1937,8 @@ bool8 CMemory::LoadMultiCart (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) +bool8 CMemory::LoadSufamiTurbo () { - Multi.cartOffsetA = 0x100000; - Multi.cartOffsetB = 0x200000; Multi.sramA = SRAM; Multi.sramB = SRAM + 0x10000; @@ -1858,65 +1946,20 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) { Multi.sramSizeA = 4; // ROM[0x37]? Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0; - - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - strcpy(Multi.fileNameA, cartA); - memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA); } - if (Multi.cartSizeA && !Multi.cartSizeB) + if (Multi.cartSizeB) { - if (cartB && cartB[0]) - Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE); - - if (Multi.cartSizeB) - { - if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB)) - Multi.cartSizeB = 0; - } + if (!is_SufamiTurbo_Cart(ROM + Multi.cartOffsetB, Multi.cartSizeB)) + Multi.cartSizeB = 0; } if (Multi.cartSizeB) { Multi.sramSizeB = 4; // ROM[0x37]? Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0; - - if (!Settings.NoPatch) - CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB); - - strcpy(Multi.fileNameB, cartB); - memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB); } - FILE *fp; - size_t size; - char path[PATH_MAX + 1]; - - strcpy(path, S9xGetDirectory(BIOS_DIR)); - strcat(path, SLASH_STR); - strcat(path, "STBIOS.bin"); - - fp = fopen(path, "rb"); - if (fp) - { - size = fread((void *) ROM, 1, 0x40000, fp); - fclose(fp); - if (!is_SufamiTurbo_BIOS(ROM, size)) - return (FALSE); - } - else - return (FALSE); - - if (Multi.cartSizeA) - strcpy(ROMFilename, Multi.fileNameA); - else - if (Multi.cartSizeB) - strcpy(ROMFilename, Multi.fileNameB); - else - strcpy(ROMFilename, path); - LoROM = TRUE; HiROM = FALSE; CalculatedSize = 0x40000; @@ -1924,10 +1967,8 @@ bool8 CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) +bool8 CMemory::LoadSameGame () { - Multi.cartOffsetA = 0; - Multi.cartOffsetB = 0x200000; Multi.sramA = SRAM; Multi.sramB = NULL; @@ -1936,24 +1977,12 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) Multi.sramSizeB = 0; Multi.sramMaskB = 0; - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - strcpy(Multi.fileNameA, cartA); - - if (cartB && cartB[0]) - Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB); - if (Multi.cartSizeB) { if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) Multi.cartSizeB = 0; - else - strcpy(Multi.fileNameB, cartB); } - strcpy(ROMFilename, Multi.fileNameA); - LoROM = FALSE; HiROM = TRUE; CalculatedSize = Multi.cartSizeA; @@ -1961,10 +1990,8 @@ bool8 CMemory::LoadSameGame (const char *cartA, const char *cartB) return (TRUE); } -bool8 CMemory::LoadGNEXT (const char *cartA, const char *cartB) +bool8 CMemory::LoadGNEXT () { - Multi.cartOffsetA = 0; - Multi.cartOffsetB = 0x400000; Multi.sramA = SRAM; Multi.sramB = NULL; @@ -1973,24 +2000,12 @@ bool8 CMemory::LoadGNEXT (const char *cartA, const char *cartB) Multi.sramSizeB = 0; Multi.sramMaskB = 0; - if (!Settings.NoPatch) - CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA); - - strcpy(Multi.fileNameA, cartA); - - if (cartB && cartB[0]) - Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB); - if (Multi.cartSizeB) { if (!is_GNEXT_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB)) Multi.cartSizeB = 0; - else - strcpy(Multi.fileNameB, cartB); } - strcpy(ROMFilename, Multi.fileNameA); - LoROM = TRUE; HiROM = FALSE; CalculatedSize = Multi.cartSizeA; diff --git a/memmap.h b/memmap.h index 4bf43d36..0f943542 100644 --- a/memmap.h +++ b/memmap.h @@ -277,10 +277,12 @@ struct CMemory bool8 LoadROMMem (const uint8 *, uint32); bool8 LoadROM (const char *); bool8 LoadROMInt (int32); + bool8 LoadMultiCartMem (const uint8 *, uint32, const uint8 *, uint32, const uint8 *, uint32); bool8 LoadMultiCart (const char *, const char *); - bool8 LoadSufamiTurbo (const char *, const char *); - bool8 LoadSameGame (const char *, const char *); - bool8 LoadGNEXT (const char *, const char *); + bool8 LoadMultiCartInt (); + bool8 LoadSufamiTurbo (); + bool8 LoadSameGame (); + bool8 LoadGNEXT (); bool8 LoadSRAM (const char *); bool8 SaveSRAM (const char *); void ClearSRAM (bool8 onlyNonSavedSRAM = 0);