diff --git a/bsnes/target-libretro/libretro.cpp b/bsnes/target-libretro/libretro.cpp index fcec9723..31537e78 100644 --- a/bsnes/target-libretro/libretro.cpp +++ b/bsnes/target-libretro/libretro.cpp @@ -41,8 +41,10 @@ static int aspect_ratio_mode = 0; #define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_LIGHTGUN, 2) #define RETRO_GAME_TYPE_SGB 0x101 | 0x1000 +#define RETRO_GAME_TYPE_BSX 0x110 | 0x1000 #define RETRO_MEMORY_SGB_SRAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) #define RETRO_MEMORY_GB_SRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_BSX_SRAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) static double get_aspect_ratio() { @@ -333,23 +335,33 @@ static void set_controller_ports(unsigned port, unsigned device) static void set_environment_info(retro_environment_t cb) { - static const struct retro_subsystem_memory_info sgb_memory[] = { - { "srm", RETRO_MEMORY_SGB_SRAM }, - }; + static const struct retro_subsystem_memory_info sgb_memory[] = { + { "srm", RETRO_MEMORY_SGB_SRAM }, + }; - static const struct retro_subsystem_memory_info gb_memory[] = { - { "srm", RETRO_MEMORY_GB_SRAM }, - }; + static const struct retro_subsystem_memory_info gb_memory[] = { + { "srm", RETRO_MEMORY_GB_SRAM }, + }; - static const struct retro_subsystem_rom_info sgb_roms[] = { - { "Game Boy ROM", "gb|gbc", true, false, true, gb_memory, 1 }, - { "Super Game Boy ROM", "smc|sfc|swc|fig|bs", true, false, true, sgb_memory, 1 }, - }; + static const struct retro_subsystem_memory_info bsx_memory[] = { + { "srm", RETRO_MEMORY_BSX_SRAM }, + }; - static const struct retro_subsystem_info subsystems[] = { - { "Super Game Boy", "sgb", sgb_roms, 2, RETRO_GAME_TYPE_SGB }, - {} - }; + static const struct retro_subsystem_rom_info sgb_roms[] = { + { "Game Boy ROM", "gb|gbc", true, false, true, gb_memory, 1 }, + { "Super Game Boy ROM", "smc|sfc|swc|fig", true, false, true, sgb_memory, 1 }, + }; + + static const struct retro_subsystem_rom_info bsx_roms[] = { + { "BS-X ROM", "bs", true, false, true, bsx_memory, 1 }, + { "BS-X BIOS ROM", "smc|sfc|swc|fig", true, false, true, bsx_memory, 1 }, + }; + + static const struct retro_subsystem_info subsystems[] = { + { "Super Game Boy", "sgb", sgb_roms, 2, RETRO_GAME_TYPE_SGB }, + { "BS-X Satellaview", "bsx", bsx_roms, 2, RETRO_GAME_TYPE_BSX }, + {} + }; cb(RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO, (void*)subsystems); @@ -533,7 +545,7 @@ RETRO_API void retro_get_system_info(retro_system_info *info) info->library_name = "bsnes"; info->library_version = Emulator::Version; info->need_fullpath = true; - info->valid_extensions = "smc|sfc|gb|gbc"; + info->valid_extensions = "smc|sfc|gb|gbc|bs"; info->block_extract = false; } @@ -693,6 +705,14 @@ RETRO_API bool retro_load_game_special(unsigned game_type, program->superFamicom.location = info[1].path; } break; + case RETRO_GAME_TYPE_BSX: + { + libretro_print(RETRO_LOG_INFO, "BS-X ROM: %s\n", info[0].path); + libretro_print(RETRO_LOG_INFO, "BS-X BIOS ROM: %s\n", info[1].path); + program->bsMemory.location = info[0].path; + program->superFamicom.location = info[1].path; + } + break; default: return false; } diff --git a/bsnes/target-libretro/program.cpp b/bsnes/target-libretro/program.cpp index af314de6..1a0034b1 100644 --- a/bsnes/target-libretro/program.cpp +++ b/bsnes/target-libretro/program.cpp @@ -15,6 +15,7 @@ using namespace nall; #include #include #include +#include #include "resources.hpp" @@ -36,11 +37,13 @@ struct Program : Emulator::Platform auto loadFile(string location) -> vector; auto loadSuperFamicom(string location) -> bool; auto loadGameBoy(string location) -> bool; + auto loadBSMemory(string location) -> bool; auto save() -> void; auto openRomSuperFamicom(string name, vfs::file::mode mode) -> shared_pointer; auto openRomGameBoy(string name, vfs::file::mode mode) -> shared_pointer; + auto openRomBSMemory(string name, vfs::file::mode mode) -> shared_pointer; auto hackPatchMemory(vector& data) -> void; @@ -72,6 +75,10 @@ public: struct GameBoy : Game { vector program; } gameBoy; + + struct BSMemory : Game { + vector program; + } bsMemory; }; static Program *program = nullptr; @@ -132,6 +139,21 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> result = openRomGameBoy(name, mode); } } + else if (id == 3) { //BS Memory + if (name == "manifest.bml" && mode == vfs::file::mode::read) { + result = vfs::memory::file::open(bsMemory.manifest.data(), bsMemory.manifest.size()); + } + else if (name == "program.rom" && mode == vfs::file::mode::read) { + result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size()); + } + else if(name == "program.flash") { + //writes are not flushed to disk in bsnes + result = vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size()); + } + else { + result = openRomBSMemory(name, mode); + } + } return result; } @@ -217,6 +239,11 @@ auto Program::load(uint id, string name, string type, vector options) -> return { id, NULL }; } } + else if (id == 3) { + if (loadBSMemory(bsMemory.location)) { + return { id, NULL }; + } + } return { id, options(0) }; } @@ -417,6 +444,21 @@ auto Program::openRomGameBoy(string name, vfs::file::mode mode) -> shared_pointe return {}; } +auto Program::openRomBSMemory(string name, vfs::file::mode mode) -> shared_pointer { + if (name == "program.rom" && mode == vfs::file::mode::read) + { + return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size()); + } + + if (name == "program.flash") + { + //writes are not flushed to disk + return vfs::memory::file::open(bsMemory.program.data(), bsMemory.program.size()); + } + + return {}; +} + auto Program::loadFile(string location) -> vector { if(Location::suffix(location).downcase() == ".zip") { @@ -506,6 +548,23 @@ auto Program::loadGameBoy(string location) -> bool { return true; } +auto Program::loadBSMemory(string location) -> bool { + vector rom; + rom = loadFile(location); + + if (rom.size() < 0x8000) return false; + + auto heuristics = Heuristics::BSMemory(rom, location); + auto sha256 = Hash::SHA256(rom).digest(); + + bsMemory.manifest = heuristics.manifest(); + bsMemory.document = BML::unserialize(bsMemory.manifest); + bsMemory.location = location; + + bsMemory.program = rom; + return true; +} + auto Program::hackPatchMemory(vector& data) -> void { auto title = superFamicom.title;