From 6c4e3ec7900c0915bebaa349bd0a9d7cfdee344f Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Fri, 4 Mar 2011 19:57:00 +1100 Subject: [PATCH] Update to v076r03 release. byuu says: Changelog: - paths.cfg work completed - save states/archives and cheat files for multi-slot games are more intelligent now For paths.cfg, there are three types of entries. Each have different special prefixes. Folder paths: sfc, bs, st, gb, filter, shader By default, bsnes will remember the last path you loaded a file of said type from. It will be prefixed with "recent/" in the file. Specify an explicit hard-coded path to override this. BIOS paths: satellaviewBios, sufamiTurboBios, superGameBoyBios Remembers an explicit hard-coded path to the BIOS you selected last. I was thinking that a nice feature would be for the "Load Special" windows to pop open the slot A load dialog if a BIOS was selected. Select a game from this popup and it loads directly, cancel it to get the regular window to override the BIOS. Save paths: srm, rtc, bsa, bst, cht, log Paths to write various files that the emulator generates. Note: srm groups bsp, bss and sav for now. Was being lazy. There are four special prefixes for these: "base/" -- gets replaced with the executable path "user/" -- gets replaced with the same folder where bsnes.cfg goes (%APPDATA%/bsnes or ~/.config/bsnes) -- good for hiding files "./" -- gets replaced with the current ROM path "../" -- gets replaced with the folder above the current ROM path If you want to go up two folders or more, then use a hard-coded path. If that's not good enough, kill yourself because God hates you. --- bsnes/snes/cartridge/cartridge.hpp | 14 +++-- bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp | 4 +- bsnes/snes/snes.hpp | 10 ++-- bsnes/ui/cartridge/cartridge.cpp | 36 ++++++------- bsnes/ui/cartridge/cartridge.hpp | 4 +- bsnes/ui/debugger/console.cpp | 3 +- bsnes/ui/path/path.cpp | 58 +++++++++++++++++++-- bsnes/ui/path/path.hpp | 9 ++++ bsnes/ui/tools/cheat-editor.cpp | 10 ++-- bsnes/ui/tools/cheat-editor.hpp | 4 +- bsnes/ui/tools/state-manager.cpp | 7 ++- bsnes/ui/utility/utility.cpp | 16 ++++-- bsnes/ui/utility/utility.hpp | 1 + 13 files changed, 125 insertions(+), 51 deletions(-) diff --git a/bsnes/snes/cartridge/cartridge.hpp b/bsnes/snes/cartridge/cartridge.hpp index a1e7f896..d50f5c3d 100755 --- a/bsnes/snes/cartridge/cartridge.hpp +++ b/bsnes/snes/cartridge/cartridge.hpp @@ -13,6 +13,14 @@ public: PAL, }; + enum class Slot : unsigned { + Base, + Bsx, + SufamiTurboA, + SufamiTurboB, + GameBoy, + }; + MappedRAM rom; MappedRAM ram; @@ -46,9 +54,9 @@ public: const string id; uint8_t *data; unsigned size; - unsigned slot; - NonVolatileRAM() : id(""), data(0), size(0), slot(0) {} - NonVolatileRAM(const string id, uint8_t *data, unsigned size, unsigned slot = 0) + Slot slot; + NonVolatileRAM() : id(""), data(0), size(0), slot(Slot::Base) {} + NonVolatileRAM(const string id, uint8_t *data, unsigned size, Slot slot = Slot::Base) : id(id), data(data), size(size), slot(slot) {} }; linear_vector nvram; diff --git a/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp b/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp index 1eb6e91e..8104e3b5 100755 --- a/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp +++ b/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp @@ -11,13 +11,13 @@ void SufamiTurbo::load() { slotB.ram.map(allocate(128 * 1024, 0xff), 128 * 1024); if(slotA.rom.data()) { - cartridge.nvram.append({ "srm", slotA.ram.data(), slotA.ram.size(), 1 }); + cartridge.nvram.append({ "srm", slotA.ram.data(), slotA.ram.size(), Cartridge::Slot::SufamiTurboA }); } else { slotA.rom.map(allocate(128 * 1024, 0xff), 128 * 1024); } if(slotB.rom.data()) { - cartridge.nvram.append({ "srm", slotB.ram.data(), slotB.ram.size(), 2 }); + cartridge.nvram.append({ "srm", slotB.ram.data(), slotB.ram.size(), Cartridge::Slot::SufamiTurboB }); } else { slotB.rom.map(allocate(128 * 1024, 0xff), 128 * 1024); } diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index f109289a..cc227247 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,7 +1,7 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "076.02"; + static const char Version[] = "076.03"; static const unsigned SerializerVersion = 18; } } @@ -39,10 +39,10 @@ using namespace nall; #endif namespace SNES { - typedef int8_t int8; - typedef int16_t int16; - typedef int32_t int32; - typedef int64_t int64; + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; typedef uint8_t uint8; typedef uint16_t uint16; diff --git a/bsnes/ui/cartridge/cartridge.cpp b/bsnes/ui/cartridge/cartridge.cpp index 96f12b23..92504bf4 100755 --- a/bsnes/ui/cartridge/cartridge.cpp +++ b/bsnes/ui/cartridge/cartridge.cpp @@ -14,10 +14,10 @@ bool Cartridge::loadNormal(const char *basename) { bool Cartridge::loadBsxSlotted(const char *basename, const char *slotname) { unload(); if(loadCartridge(SNES::cartridge.rom, baseXML, basename) == false) return false; - loadCartridge(SNES::bsxflash.memory, slotAXML, slotname); + loadCartridge(SNES::bsxflash.memory, bsxXML, slotname); SNES::cartridge.basename = baseName = nall::basename(basename); - slotAName = nall::basename(slotname); - SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { baseXML, slotAXML }); + bsxName = nall::basename(slotname); + SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { baseXML, bsxXML }); foreach(memory, SNES::cartridge.nvram) loadMemory(memory); utility.cartridgeLoaded(); return true; @@ -26,10 +26,10 @@ bool Cartridge::loadBsxSlotted(const char *basename, const char *slotname) { bool Cartridge::loadBsx(const char *basename, const char *slotname) { unload(); if(loadCartridge(SNES::cartridge.rom, baseXML, basename) == false) return false; - loadCartridge(SNES::bsxflash.memory, slotAXML, slotname); + loadCartridge(SNES::bsxflash.memory, bsxXML, slotname); SNES::cartridge.basename = baseName = nall::basename(basename); - slotAName = nall::basename(slotname); - SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { baseXML, slotAXML }); + bsxName = nall::basename(slotname); + SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { baseXML, bsxXML }); foreach(memory, SNES::cartridge.nvram) loadMemory(memory); utility.cartridgeLoaded(); return true; @@ -38,12 +38,12 @@ bool Cartridge::loadBsx(const char *basename, const char *slotname) { bool Cartridge::loadSufamiTurbo(const char *basename, const char *slotAname, const char *slotBname) { unload(); if(loadCartridge(SNES::cartridge.rom, baseXML, basename) == false) return false; - loadCartridge(SNES::sufamiturbo.slotA.rom, slotAXML, slotAname); - loadCartridge(SNES::sufamiturbo.slotB.rom, slotBXML, slotBname); + loadCartridge(SNES::sufamiturbo.slotA.rom, sufamiTurboAXML, slotAname); + loadCartridge(SNES::sufamiturbo.slotB.rom, sufamiTurboBXML, slotBname); SNES::cartridge.basename = baseName = nall::basename(basename); - slotAName = nall::basename(slotAname); - slotBName = nall::basename(slotBname); - SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { baseXML, slotAXML, slotBXML }); + sufamiTurboAName = nall::basename(slotAname); + sufamiTurboBName = nall::basename(slotBname); + SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { baseXML, sufamiTurboAXML, sufamiTurboBXML }); foreach(memory, SNES::cartridge.nvram) loadMemory(memory); utility.cartridgeLoaded(); return true; @@ -69,11 +69,11 @@ bool Cartridge::loadSuperGameBoy(const char *basename, const char *slotname) { if(data) delete[] data; SNES::cartridge.basename = baseName = nall::basename(basename); - slotAName = nall::basename(slotname); + gameBoyName = nall::basename(slotname); SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { baseXML, "" }); foreach(memory, SNES::cartridge.nvram) loadMemory(memory); - if(GameBoy::cartridge.info.battery && fp.open(string(slotAName, ".sav"), file::mode::read)) { + if(GameBoy::cartridge.info.battery && fp.open(path.load(SNES::Cartridge::Slot::GameBoy, "sav"), file::mode::read)) { fp.read(GameBoy::cartridge.ramdata, min(GameBoy::cartridge.ramsize, fp.size())); fp.close(); } @@ -89,14 +89,14 @@ void Cartridge::unload() { foreach(memory, SNES::cartridge.nvram) saveMemory(memory); if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) { file fp; - if(GameBoy::cartridge.info.battery && fp.open(string(slotAName, ".sav"), file::mode::write)) { + if(GameBoy::cartridge.info.battery && fp.open(path.load(SNES::Cartridge::Slot::GameBoy, "sav"), file::mode::write)) { fp.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); fp.close(); } } utility.cartridgeUnloaded(); - baseName = slotAName = slotBName = ""; + baseName = bsxName = sufamiTurboAName = sufamiTurboBName = gameBoyName = ""; } bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char *filename) { @@ -133,8 +133,7 @@ bool Cartridge::loadCartridge(SNES::MappedRAM &memory, string &XML, const char * bool Cartridge::loadMemory(SNES::Cartridge::NonVolatileRAM &memory) { if(memory.size == 0) return true; - lstring filenames = { baseName, slotAName, slotBName }; - string filename = string(filenames[memory.slot], ".", memory.id); + string filename = path.load(memory.slot, memory.id); file fp; if(fp.open(filename, file::mode::read) == false) return false; fp.read(memory.data, min(memory.size, fp.size())); @@ -144,8 +143,7 @@ bool Cartridge::loadMemory(SNES::Cartridge::NonVolatileRAM &memory) { bool Cartridge::saveMemory(SNES::Cartridge::NonVolatileRAM &memory) { if(memory.size == 0) return true; - lstring filenames = { baseName, slotAName, slotBName }; - string filename = string(filenames[memory.slot], ".", memory.id); + string filename = path.load(memory.slot, memory.id); file fp; if(fp.open(filename, file::mode::write) == false) return false; fp.write(memory.data, memory.size); diff --git a/bsnes/ui/cartridge/cartridge.hpp b/bsnes/ui/cartridge/cartridge.hpp index c24b8765..1d8746e4 100755 --- a/bsnes/ui/cartridge/cartridge.hpp +++ b/bsnes/ui/cartridge/cartridge.hpp @@ -6,8 +6,8 @@ struct Cartridge { bool loadSuperGameBoy(const char *basename, const char *slotname); void unload(); - string baseName, slotAName, slotBName; - string baseXML, slotAXML, slotBXML; + string baseName, bsxName, sufamiTurboAName, sufamiTurboBName, gameBoyName; + string baseXML, bsxXML, sufamiTurboAXML, sufamiTurboBXML, gameBoyXML; bool patchApplied; private: diff --git a/bsnes/ui/debugger/console.cpp b/bsnes/ui/debugger/console.cpp index 026a7b99..36144aec 100755 --- a/bsnes/ui/debugger/console.cpp +++ b/bsnes/ui/debugger/console.cpp @@ -54,8 +54,7 @@ void Console::write(const string &text, bool echo) { void Console::tracerEnable(bool state) { if(state == true) { - string filename = { cartridge.baseName, ".log" }; - logfile.open(filename, file::mode::write); + logfile.open(path.load(SNES::Cartridge::Slot::Cartridge, "log"), file::mode::write); } else { logfile.close(); } diff --git a/bsnes/ui/path/path.cpp b/bsnes/ui/path/path.cpp index 9c8f2f24..3a93d597 100755 --- a/bsnes/ui/path/path.cpp +++ b/bsnes/ui/path/path.cpp @@ -30,7 +30,7 @@ string Path::load(const string &path) { if(path == "filter") value = filter; if(path == "shader") value = shader; - if(value.beginswith(":")) value.ltrim<1>(":"); + if(value.beginswith("recent/")) value.ltrim<1>("recent/"); if(value == "") value = base; return value; } @@ -48,12 +48,56 @@ void Path::save(const string &path, const string &value) { if(output) { string &s = *output; - if(s.beginswith(":") == false && s != "") return; - s = { ":", value }; + if(s.beginswith("recent/") == false && s != "") return; + s = { "recent/", value }; return; } } +string Path::load(SNES::Cartridge::Slot slot, const string &type, const string &suffix) { + string romPath; + switch(slot) { + case SNES::Cartridge::Slot::Base: romPath = cartridge.baseName; break; + case SNES::Cartridge::Slot::Bsx: romPath = cartridge.bsxName; break; + case SNES::Cartridge::Slot::SufamiTurboA: romPath = cartridge.sufamiTurboAName; break; + case SNES::Cartridge::Slot::SufamiTurboB: romPath = cartridge.sufamiTurboBName; break; + case SNES::Cartridge::Slot::GameBoy: romPath = cartridge.gameBoyName; break; + } + + string path = romPath; + if(type == "srm" && srm != "") path = string(srm, notdir(path)); + if(type == "bsp" && srm != "") path = string(srm, notdir(path)); + if(type == "bss" && srm != "") path = string(srm, notdir(path)); + if(type == "sav" && srm != "") path = string(srm, notdir(path)); + if(type == "rtc" && rtc != "") path = string(rtc, notdir(path)); + if(type == "bsa" && bsa != "") path = string(bsa, notdir(path)); + if(type == "bst" && bst != "") path = string(bst, notdir(path)); + if(type == "cht" && cht != "") path = string(cht, notdir(path)); + if(type == "log" && log != "") path = string(log, notdir(path)); + + if(path.beginswith("user/")) { + path.ltrim<1>("user/"); + #if defined(PLATFORM_X) || defined(PLATFORM_OSX) + path = string(user, ".config/bsnes/", path); + #else + path = string(user, "bsnes/", path); + #endif + } else if(path.beginswith("base/")) { + path.ltrim<1>("base/"); + path = string(base, path); + } else if(path.beginswith("./")) { + path.ltrim<1>("./"); + path = string(dir(romPath), path); + } else if(path.beginswith("../")) { + string base = dir(romPath); + base.rtrim<1>("/"); + path.ltrim<1>("../"); + path = string(dir(base), path); + } + + return { path, suffix, ".", type }; +} + void Path::load() { configuration::load(home("paths.cfg")); } @@ -74,4 +118,12 @@ Path::Path() { attach(satellaviewBios = "", "satellaviewBios"); attach(sufamiTurboBios = "", "sufamiTurboBios"); attach(superGameBoyBios = "", "superGameBoyBios"); + + attach(srm = "", "srm"); + attach(rtc = "", "rtc"); + + attach(bsa = "", "bsa"); + attach(bst = "", "bst"); + attach(cht = "", "cht"); + attach(log = "", "log"); } diff --git a/bsnes/ui/path/path.hpp b/bsnes/ui/path/path.hpp index cb364cc0..0eadc79b 100755 --- a/bsnes/ui/path/path.hpp +++ b/bsnes/ui/path/path.hpp @@ -14,9 +14,18 @@ struct Path : public configuration { string sufamiTurboBios; string superGameBoyBios; + string srm; + string rtc; + + string bsa; + string bst; + string cht; + string log; + string home(const string &filename); string load(const string &path); void save(const string &path, const string &value); + string load(SNES::Cartridge::Slot slot, const string &type, const string &suffix = ""); void load(); void save(); diff --git a/bsnes/ui/tools/cheat-editor.cpp b/bsnes/ui/tools/cheat-editor.cpp index 9d969db5..61f51896 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -1,6 +1,6 @@ CheatEditor cheatEditor; -void CheatEditor::load(string filename) { +void CheatEditor::load() { SNES::cheat.reset(); cheatList.reset(); for(unsigned i = 0; i < 128; i++) { @@ -12,7 +12,7 @@ void CheatEditor::load(string filename) { unsigned n = 0; string data; - data.readfile(string(filename, ".cht")); + data.readfile(path.load(utility.stateSlot(), "cht")); xml_element document = xml_parse(data); foreach(head, document.element) { if(head.name == "cartridge") { @@ -43,7 +43,7 @@ void CheatEditor::load(string filename) { synchronize(); } -void CheatEditor::save(string filename) { +void CheatEditor::save() { signed lastSave = -1; for(signed i = 127; i >= 0; i--) { if(cheatText[i][CheatCode] != "" || cheatText[i][CheatDesc] != "") { @@ -52,12 +52,12 @@ void CheatEditor::save(string filename) { } } if(lastSave == -1) { - unlink(string(filename, ".cht")); + unlink(path.load(utility.stateSlot(), "cht")); return; } file fp; - if(fp.open(string(filename, ".cht"), file::mode::write)) { + if(fp.open(path.load(utility.stateSlot(), "cht"), file::mode::write)) { fp.print("\n"); fp.print(string("\n")); for(unsigned i = 0; i <= lastSave; i++) { diff --git a/bsnes/ui/tools/cheat-editor.hpp b/bsnes/ui/tools/cheat-editor.hpp index cc55076c..7cda6042 100755 --- a/bsnes/ui/tools/cheat-editor.hpp +++ b/bsnes/ui/tools/cheat-editor.hpp @@ -13,8 +13,8 @@ struct CheatEditor : TopLevelWindow { Button clearAllButton; Button clearButton; - void load(string filename); - void save(string filename); + void load(); + void save(); void create(); private: diff --git a/bsnes/ui/tools/state-manager.cpp b/bsnes/ui/tools/state-manager.cpp index 6ee9d315..af4c37a3 100755 --- a/bsnes/ui/tools/state-manager.cpp +++ b/bsnes/ui/tools/state-manager.cpp @@ -59,9 +59,8 @@ void StateManager::load() { stateList.append(""); } - string filename = { cartridge.baseName, ".bsa" }; file fp; - if(fp.open(string(cartridge.baseName, ".bsa"), file::mode::read)) { + if(fp.open(path.load(utility.stateSlot(), "bsa"), file::mode::read)) { if(fp.readl(4) == 0x31415342) { if(fp.readl(4) == SNES::Info::SerializerVersion) { for(unsigned i = 0; i < 32; i++) { @@ -85,10 +84,10 @@ void StateManager::save() { } if(hasSave == false) { - unlink(string(cartridge.baseName, ".bsa")); + unlink(path.load(utility.stateSlot(), "bsa")); } else { file fp; - if(fp.open(string(cartridge.baseName, ".bsa"), file::mode::write)) { + if(fp.open(path.load(utility.stateSlot(), "bsa"), file::mode::write)) { fp.writel(0x31415342, 4); //'BSA1' fp.writel(SNES::Info::SerializerVersion, 4); diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index ef24669b..28e6802f 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -150,7 +150,7 @@ void Utility::setShader() { void Utility::cartridgeLoaded() { SNES::system.power(); - cheatEditor.load(cartridge.baseName); + cheatEditor.load(); stateManager.load(); mainWindow.synchronize(); utility.setTitle(notdir(cartridge.baseName)); @@ -162,13 +162,21 @@ void Utility::cartridgeLoaded() { void Utility::cartridgeUnloaded() { SNES::cartridge.unload(); - cheatEditor.save(cartridge.baseName); + cheatEditor.save(); stateManager.save(); mainWindow.synchronize(); } +SNES::Cartridge::Slot Utility::stateSlot() { + SNES::Cartridge::Slot slot = SNES::Cartridge::Slot::Base; + if(SNES::cartridge.mode() == SNES::Cartridge::Mode::Bsx) slot = SNES::Cartridge::Slot::Bsx; + if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SufamiTurbo) slot = SNES::Cartridge::Slot::SufamiTurboA; + if(SNES::cartridge.mode() == SNES::Cartridge::Mode::SuperGameBoy) slot = SNES::Cartridge::Slot::GameBoy; + return slot; +} + void Utility::saveState(unsigned slot) { - string filename = { cartridge.baseName, "-", slot, ".bst" }; + string filename = path.load(stateSlot(), "bst", { "-", slot }); SNES::system.runtosave(); serializer s = SNES::system.serialize(); file fp; @@ -182,7 +190,7 @@ void Utility::saveState(unsigned slot) { } void Utility::loadState(unsigned slot) { - string filename = { cartridge.baseName, "-", slot, ".bst" }; + string filename = path.load(stateSlot(), "bst", { "-", slot }); file fp; if(fp.open(filename, file::mode::read)) { unsigned size = fp.size(); diff --git a/bsnes/ui/utility/utility.hpp b/bsnes/ui/utility/utility.hpp index d182585d..4fd75551 100755 --- a/bsnes/ui/utility/utility.hpp +++ b/bsnes/ui/utility/utility.hpp @@ -15,6 +15,7 @@ struct Utility : property { void cartridgeLoaded(); void cartridgeUnloaded(); + SNES::Cartridge::Slot stateSlot(); void saveState(unsigned slot); void loadState(unsigned slot);