From a37ce1cb2fb8c53fa311f7a622f687444a56a94d Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 16 Feb 2012 01:01:22 +1100 Subject: [PATCH] Update to v086r01 release. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit byuu says: The goals for v087 are to have a unified cartridge-folder concept, as well as a more functional SNES debugger. Starting with the cartridge folders. What I have so far: Code: NES: - program.rom - character.rom - program.ram - … SNES: - program.rom - program.rtc - data.rom (SPC7110) - { dsp1.rom, dsp1b.rom, cx4.rom, … } - msu1.rom - track-#.pcm Game Boy, Game Boy Color: - program.rom - program.ram - program.rtc Sub-cartridges (BS-X, Sufami Turbo, …) are stored as separate folders Folder names must be UTF-8 based, with all-lowercase extensions File names must be all-lowercase SNES: - "program.ram" (.srm, .sts) - "msu1.rom" (name.msu) - "track-#.pcm" (name-#.pcm) - "upd96050.ram" -> "name.ram" - "bsx.ram" (.bss) - "bsx.psram" (.bsp) - "serial.so" -> "libserial.so" (broken) Need: - Super Game Boy (not even sure how this loads and saves memory, it's obviously broken) And I need to think of some way of handling multi-cart loaded games. Eg Satellaview-slotted and Sufami Turbo. It was { base + slot ( + slot ... } }, but this gets trickier with folders and fixed names. Actual markup for the NES needs to change as well. --- bsnes/base/base.hpp | 2 +- bsnes/nall/snes/cartridge.hpp | 14 +-- bsnes/snes/alt/smp/smp.cpp | 1 - bsnes/snes/cartridge/cartridge.cpp | 2 +- bsnes/snes/cartridge/markup.cpp | 6 +- bsnes/snes/chip/bsx/cartridge/cartridge.cpp | 4 +- bsnes/snes/chip/msu1/msu1.cpp | 4 +- bsnes/snes/chip/msu1/serialization.cpp | 4 +- bsnes/snes/chip/necdsp/necdsp.cpp | 2 +- bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp | 4 +- bsnes/snes/controller/serial/serial.cpp | 2 +- bsnes/ui-debugger/console/console.cpp | 2 +- bsnes/ui-debugger/debugger/usage.cpp | 4 +- bsnes/ui-debugger/interface/interface.cpp | 28 +++-- bsnes/ui-debugger/interface/interface.hpp | 4 +- bsnes/ui-debugger/main.cpp | 7 +- bsnes/ui/interface/gameboy/gameboy.cpp | 19 ++- bsnes/ui/interface/interface.cpp | 19 +-- bsnes/ui/interface/interface.hpp | 11 +- bsnes/ui/interface/nes/nes.cpp | 31 ++--- bsnes/ui/interface/snes/snes.cpp | 128 +++++++++++--------- bsnes/ui/interface/snes/snes.hpp | 3 +- 22 files changed, 157 insertions(+), 144 deletions(-) diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index 39256a19..6f20fe62 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -const char Version[] = "086"; +const char Version[] = "086.01"; #include #include diff --git a/bsnes/nall/snes/cartridge.hpp b/bsnes/nall/snes/cartridge.hpp index baa45b22..c24dcaa1 100755 --- a/bsnes/nall/snes/cartridge.hpp +++ b/bsnes/nall/snes/cartridge.hpp @@ -145,7 +145,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); else if(has_cx4) markup.append( - " \n" + " \n" " \n" " \n" " \n" @@ -420,7 +420,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); if(has_dsp1) { - markup.append(" \n"); + markup.append(" \n"); if(dsp1_mapper == DSP1LoROM1MB) markup.append( " \n" " \n" @@ -455,7 +455,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { } if(has_dsp2) markup.append( - " \n" + " \n" " \n" " \n" " \n" @@ -468,7 +468,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); if(has_dsp3) markup.append( - " \n" + " \n" " \n" " \n" " \n" @@ -481,7 +481,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); if(has_dsp4) markup.append( - " \n" + " \n" " \n" " \n" " \n" @@ -494,7 +494,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); if(has_st010) markup.append( - " \n" + " \n" " \n" " \n" " \n" @@ -511,7 +511,7 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { ); if(has_st011) markup.append( - " \n" + " \n" " \n" " \n" " \n" diff --git a/bsnes/snes/alt/smp/smp.cpp b/bsnes/snes/alt/smp/smp.cpp index 76b9fa8a..c3ac43e3 100755 --- a/bsnes/snes/alt/smp/smp.cpp +++ b/bsnes/snes/alt/smp/smp.cpp @@ -5,7 +5,6 @@ #define SMP_CPP namespace SNES { -#include "disassembler.cpp" SMP smp; #include "algorithms.cpp" diff --git a/bsnes/snes/cartridge/cartridge.cpp b/bsnes/snes/cartridge/cartridge.cpp index 070623b5..fdfff8a0 100755 --- a/bsnes/snes/cartridge/cartridge.cpp +++ b/bsnes/snes/cartridge/cartridge.cpp @@ -38,7 +38,7 @@ void Cartridge::load(Mode cartridge_mode, const char *markup) { if(ram_size > 0) { ram.map(allocate(ram_size, 0xff), ram_size); - nvram.append({ ".srm", ram.data(), ram.size() }); + nvram.append({ "program.ram", ram.data(), ram.size() }); } rom.write_protect(true); diff --git a/bsnes/snes/cartridge/markup.cpp b/bsnes/snes/cartridge/markup.cpp index 753c73cf..aec2b2f4 100755 --- a/bsnes/snes/cartridge/markup.cpp +++ b/bsnes/snes/cartridge/markup.cpp @@ -223,7 +223,7 @@ void Cartridge::parse_markup_necdsp(XML::Node &root) { string firmware = root["firmware"].data; string sha256 = root["sha256"].data; - string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; + string path = interface->path(Slot::Base, firmware); unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384); unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048); unsigned filesize = promsize * 3 + dromsize * 2; @@ -288,7 +288,7 @@ void Cartridge::parse_markup_hitachidsp(XML::Node &root) { string firmware = root["firmware"].data; string sha256 = root["sha256"].data; - string path = { dir(interface->path(Slot::Base, ".dsp")), firmware }; + string path = interface->path(Slot::Base, firmware); file fp; if(fp.open(path, file::mode::read) == false) { interface->message({ "Warning: Hitachi DSP firmware ", firmware, " is missing." }); @@ -496,7 +496,7 @@ void Cartridge::parse_markup_setarisc(XML::Node &root) { void Cartridge::parse_markup_msu1(XML::Node &root) { if(root.exists() == false) { - has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, ".msu")); + has_msu1 = file::exists(interface->path(Cartridge::Slot::Base, "msu1.rom")); if(has_msu1) { Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); m.banklo = 0x00, m.bankhi = 0x3f, m.addrlo = 0x2000, m.addrhi = 0x2007; diff --git a/bsnes/snes/chip/bsx/cartridge/cartridge.cpp b/bsnes/snes/chip/bsx/cartridge/cartridge.cpp index 8192942f..8b77d1d0 100755 --- a/bsnes/snes/chip/bsx/cartridge/cartridge.cpp +++ b/bsnes/snes/chip/bsx/cartridge/cartridge.cpp @@ -8,11 +8,11 @@ void BSXCartridge::init() { void BSXCartridge::load() { sram.map(allocate(32 * 1024, 0xff), 32 * 1024); sram.write_protect(false); - cartridge.nvram.append({ ".bss", sram.data(), sram.size() }); + cartridge.nvram.append({ "bsx.ram", sram.data(), sram.size() }); psram.map(allocate(512 * 1024, 0xff), 512 * 1024); psram.write_protect(false); - cartridge.nvram.append({ ".bsp", psram.data(), psram.size() }); + cartridge.nvram.append({ "bsx.psram", psram.data(), psram.size() }); } void BSXCartridge::unload() { diff --git a/bsnes/snes/chip/msu1/msu1.cpp b/bsnes/snes/chip/msu1/msu1.cpp index 71700e60..f12a9102 100755 --- a/bsnes/snes/chip/msu1/msu1.cpp +++ b/bsnes/snes/chip/msu1/msu1.cpp @@ -50,7 +50,7 @@ void MSU1::init() { void MSU1::load() { if(datafile.open()) datafile.close(); - datafile.open(interface->path(Cartridge::Slot::Base, ".msu"), file::mode::read); + datafile.open(interface->path(Cartridge::Slot::Base, "msu1.rom"), file::mode::read); } void MSU1::unload() { @@ -110,7 +110,7 @@ void MSU1::mmio_write(unsigned addr, uint8 data) { case 4: mmio.audio_track = (mmio.audio_track & 0xff00) | (data << 0); case 5: mmio.audio_track = (mmio.audio_track & 0x00ff) | (data << 8); if(audiofile.open()) audiofile.close(); - if(audiofile.open(interface->path(Cartridge::Slot::Base, { "-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) { + if(audiofile.open(interface->path(Cartridge::Slot::Base, { "track-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) { uint32 header = audiofile.readm(4); if(header != 0x4d535531) { //verify 'MSU1' header audiofile.close(); diff --git a/bsnes/snes/chip/msu1/serialization.cpp b/bsnes/snes/chip/msu1/serialization.cpp index a5806b75..50c22d4d 100755 --- a/bsnes/snes/chip/msu1/serialization.cpp +++ b/bsnes/snes/chip/msu1/serialization.cpp @@ -16,12 +16,12 @@ void MSU1::serialize(serializer &s) { s.integer(mmio.audio_play); if(datafile.open()) datafile.close(); - if(datafile.open(interface->path(Cartridge::Slot::Base, ".msu"), file::mode::read)) { + if(datafile.open(interface->path(Cartridge::Slot::Base, "msu1.rom"), file::mode::read)) { datafile.seek(mmio.data_offset); } if(audiofile.open()) audiofile.close(); - if(audiofile.open(interface->path(Cartridge::Slot::Base, { "-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) { + if(audiofile.open(interface->path(Cartridge::Slot::Base, { "track-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) { audiofile.seek(mmio.audio_offset); } } diff --git a/bsnes/snes/chip/necdsp/necdsp.cpp b/bsnes/snes/chip/necdsp/necdsp.cpp index 04974a00..9f92131a 100755 --- a/bsnes/snes/chip/necdsp/necdsp.cpp +++ b/bsnes/snes/chip/necdsp/necdsp.cpp @@ -247,7 +247,7 @@ void NECDSP::init() { void NECDSP::load() { if(revision == Revision::uPD96050) { - cartridge.nvram.append({ ".nec", (uint8_t*)dataRAM, 4096 }); + cartridge.nvram.append({ "upd96050.ram", (uint8_t*)dataRAM, 4096 }); } } diff --git a/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp b/bsnes/snes/chip/sufamiturbo/sufamiturbo.cpp index 14fbb633..a81fe546 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({ ".sts", slotA.ram.data(), slotA.ram.size(), Cartridge::Slot::SufamiTurboA }); + cartridge.nvram.append({ "program.ram", 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({ ".sts", slotB.ram.data(), slotB.ram.size(), Cartridge::Slot::SufamiTurboB }); + cartridge.nvram.append({ "program.ram", slotB.ram.data(), slotB.ram.size(), Cartridge::Slot::SufamiTurboB }); } else { slotB.rom.map(allocate(128 * 1024, 0xff), 128 * 1024); } diff --git a/bsnes/snes/controller/serial/serial.cpp b/bsnes/snes/controller/serial/serial.cpp index 24491146..43b76bab 100755 --- a/bsnes/snes/controller/serial/serial.cpp +++ b/bsnes/snes/controller/serial/serial.cpp @@ -79,7 +79,7 @@ void Serial::latch(bool data) { Serial::Serial(bool port) : Controller(port) { enable = false; - string basename = interface->path(Cartridge::Slot::Base, ""); + string basename = interface->path(Cartridge::Slot::Base, "serial.so"); string name = notdir(basename); string path = dir(basename); if(open(name, path)) { diff --git a/bsnes/ui-debugger/console/console.cpp b/bsnes/ui-debugger/console/console.cpp index aa1cb0ed..e48dad83 100755 --- a/bsnes/ui-debugger/console/console.cpp +++ b/bsnes/ui-debugger/console/console.cpp @@ -86,7 +86,7 @@ ConsoleWindow::ConsoleWindow() { onClose = [] { application->quit = true; }; menuEmulationReloadCartridge.onActivate = [&] { - interface->loadCartridge(interface->fileName); + interface->loadCartridge(interface->pathName); }; menuEmulationPowerCycle.onActivate = [&] { diff --git a/bsnes/ui-debugger/debugger/usage.cpp b/bsnes/ui-debugger/debugger/usage.cpp index bd2a2aa8..c3d588ca 100755 --- a/bsnes/ui-debugger/debugger/usage.cpp +++ b/bsnes/ui-debugger/debugger/usage.cpp @@ -20,7 +20,7 @@ void Debugger::loadUsage() { //then it is possible that the memory map has changed. //will print invalidation message when files do not exist as well. - if(file::timestamp(interface->fileName, file::time::modify) >= + if(file::timestamp({ interface->pathName, "program.rom" }, file::time::modify) >= file::timestamp({ interface->pathName, "debug/usage.cpu" }, file::time::modify) ) { print("CPU usage invalidated\n"); @@ -31,7 +31,7 @@ void Debugger::loadUsage() { } } - if(file::timestamp(interface->fileName, file::time::modify) >= + if(file::timestamp({ interface->pathName, "program.rom" }, file::time::modify) >= file::timestamp({ interface->pathName, "debug/usage.apu" }, file::time::modify) ) { print("APU usage invalidated\n"); diff --git a/bsnes/ui-debugger/interface/interface.cpp b/bsnes/ui-debugger/interface/interface.cpp index c9bda043..54e35f6b 100755 --- a/bsnes/ui-debugger/interface/interface.cpp +++ b/bsnes/ui-debugger/interface/interface.cpp @@ -1,10 +1,10 @@ #include "../base.hpp" Interface *interface = nullptr; -bool Interface::loadCartridge(const string &filename) { +bool Interface::loadCartridge(const string &foldername) { uint8_t *data; unsigned size; - if(file::read(filename, data, size) == false) return false; + if(file::read({ foldername, "program.rom" }, data, size) == false) return false; if(SNES::cartridge.loaded()) { saveMemory(); @@ -12,23 +12,25 @@ bool Interface::loadCartridge(const string &filename) { debugger->print("Cartridge unloaded\n"); } - fileName = filename; - baseName = nall::basename(fileName); - pathName = dir(baseName); + pathName = foldername; mkdir(string(pathName, "debug/"), 0755); string markup; - markup.readfile({ baseName, ".xml" }); + markup.readfile({ pathName, "manifest.xml" }); if(markup.empty()) markup = SnesCartridge(data, size).markup; SNES::cartridge.rom.copy(data, size); SNES::cartridge.load(SNES::Cartridge::Mode::Normal, markup); SNES::system.power(); + string name = pathName; + name.rtrim<1>("/"); + name = notdir(name); + delete[] data; - videoWindow->setTitle(notdir(baseName)); + videoWindow->setTitle(name); SNES::video.generate(SNES::Video::Format::RGB24); - debugger->print("Loaded ", fileName, "\n"); + debugger->print("Loaded ", pathName, "program.rom\n"); loadMemory(); debugger->print(markup, "\n"); debugger->suspend(); @@ -38,7 +40,7 @@ bool Interface::loadCartridge(const string &filename) { void Interface::loadMemory() { for(auto &memory : SNES::cartridge.nvram) { if(memory.size == 0) continue; - string filename = { baseName, memory.id }; + string filename = { pathName, memory.id }; uint8_t *data; unsigned size; if(file::read(filename, data, size)) { @@ -54,7 +56,7 @@ void Interface::loadMemory() { void Interface::saveMemory() { for(auto &memory : SNES::cartridge.nvram) { if(memory.size == 0) continue; - string filename = { baseName, memory.id }; + string filename = { pathName, memory.id }; if(file::write(filename, memory.data, memory.size)) { debugger->print("Saved ", filename, "\n"); } @@ -64,7 +66,7 @@ void Interface::saveMemory() { } bool Interface::loadState(unsigned slot) { - string filename = { baseName, "-", slot, ".bst" }; + string filename = { pathName, "state-", slot, ".bst" }; uint8_t *data; unsigned size; if(file::read(filename, data, size) == false) return false; @@ -78,7 +80,7 @@ bool Interface::loadState(unsigned slot) { bool Interface::saveState(unsigned slot) { SNES::system.runtosave(); serializer s = SNES::system.serialize(); - string filename = { baseName, "-", slot, ".bst" }; + string filename = { pathName, "state-", slot, ".bst" }; bool result = file::write(filename, s.data(), s.size()); if(result) debugger->print("Saved state to ", filename, "\n"); return result; @@ -144,7 +146,7 @@ int16_t Interface::inputPoll(bool port, SNES::Input::Device device, unsigned ind } string Interface::path(SNES::Cartridge::Slot slot, const string &hint) { - return { baseName, hint }; + return { pathName, hint }; } void Interface::message(const string &text) { diff --git a/bsnes/ui-debugger/interface/interface.hpp b/bsnes/ui-debugger/interface/interface.hpp index 89ff6186..0c4fe1bf 100755 --- a/bsnes/ui-debugger/interface/interface.hpp +++ b/bsnes/ui-debugger/interface/interface.hpp @@ -1,9 +1,7 @@ struct Interface : SNES::Interface { - string fileName; - string baseName; string pathName; - bool loadCartridge(const string &filename); + bool loadCartridge(const string &foldername); void loadMemory(); void saveMemory(); bool loadState(unsigned slot); diff --git a/bsnes/ui-debugger/main.cpp b/bsnes/ui-debugger/main.cpp index 15eb4a5a..ed29f4e3 100755 --- a/bsnes/ui-debugger/main.cpp +++ b/bsnes/ui-debugger/main.cpp @@ -38,10 +38,7 @@ Application::Application(int argc, char **argv) { //if(!directory::exists(foldername)) foldername = "/media/sdb1/root/cartridges/The Legend of Zelda - A Link to the Past (US).sfc/"; if(!directory::exists(foldername)) foldername = DialogWindow::folderSelect(Window::None, settings->folderpath); if(!foldername.endswith(".sfc/")) return; - lstring contents = directory::files(foldername, "*.sfc"); - if(contents.size() != 1) return; - string filename = { foldername, contents[0] }; - if(!file::exists(filename)) return; + if(!directory::exists(foldername)) return; //save path for later; remove cartridge name from path settings->folderpath = foldername; @@ -76,7 +73,7 @@ Application::Application(int argc, char **argv) { audio.set(Audio::Synchronize, settings->synchronizeAudio); audio.set(Audio::Frequency, 32000u); - if(interface->loadCartridge(filename) == false) return; + if(interface->loadCartridge(foldername) == false) return; cpuDebugger->updateDisassembly(); smpDebugger->updateDisassembly(); memoryEditor->selectSource(); diff --git a/bsnes/ui/interface/gameboy/gameboy.cpp b/bsnes/ui/interface/gameboy/gameboy.cpp index 72fd9510..3c390903 100755 --- a/bsnes/ui/interface/gameboy/gameboy.cpp +++ b/bsnes/ui/interface/gameboy/gameboy.cpp @@ -12,21 +12,18 @@ bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const s unsigned size; if(filename.endswith("/")) { - string basename = filename; - basename.rtrim<1>("/"); - basename.append("/", notdir(basename)); - if(file::read(basename, data, size) == false) return false; - interface->baseName = nall::basename(basename); + if(file::read({ filename, "program.rom" }, data, size) == false) return false; + interface->base = { true, filename }; } else { if(file::read(filename, data, size) == false) return false; - interface->baseName = nall::basename(filename); + interface->base.name = { false, nall::basename(filename) }; } interface->unloadCartridge(); - interface->applyPatch(interface->baseName, data, size); +//interface->applyPatch(interface->baseName, data, size); string markup; - markup.readfile({ interface->baseName, ".xml" }); + markup.readfile(interface->base.filename("manifest.xml", ".xml")); GameBoyCartridge info(data, size); if(markup.empty()) markup = info.markup; @@ -37,7 +34,7 @@ bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const s if(GameBoy::cartridge.ramsize) { filemap fp; - if(fp.open(string{ interface->baseName, ".sav" }, filemap::mode::read)) { + if(fp.open(interface->base.filename("program.ram", ".sav"), filemap::mode::read)) { memcpy(GameBoy::cartridge.ramdata, fp.data(), min(GameBoy::cartridge.ramsize, fp.size())); } } @@ -50,11 +47,11 @@ bool InterfaceGameBoy::loadCartridge(GameBoy::System::Revision revision, const s void InterfaceGameBoy::unloadCartridge() { if(GameBoy::cartridge.ramsize) { - file::write({ interface->baseName, ".sav" }, GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); + file::write(interface->base.filename("program.ram", ".sav"), GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); } GameBoy::cartridge.unload(); - interface->baseName = ""; + interface->base.name = ""; } void InterfaceGameBoy::power() { diff --git a/bsnes/ui/interface/interface.cpp b/bsnes/ui/interface/interface.cpp index 6ef11b9c..a72f73b7 100755 --- a/bsnes/ui/interface/interface.cpp +++ b/bsnes/ui/interface/interface.cpp @@ -22,6 +22,12 @@ Filter::~Filter() { delete[] data; } +string CartridgePath::filename(const string &folderName, const string &fileName) const { + if(name.empty()) return ""; + if(folder) return { name, folderName }; + return { name, fileName }; +} + void Interface::bindControllers() { switch(mode()) { case Mode::NES: @@ -79,8 +85,8 @@ void Interface::loadCartridge(Mode mode) { } bindControllers(); - cheatEditor->load({ baseName, ".cht" }); - stateManager->load({ baseName, ".bsa" }, 0u); + cheatEditor->load(base.filename("cheats.xml", ".cht")); + stateManager->load(base.filename("states.bsa", ".bsa"), 0u); dipSwitches->load(); utility->showMessage({ "Loaded ", notdir(baseName) }); } @@ -97,8 +103,8 @@ bool Interface::loadCartridge(const string &filename) { void Interface::unloadCartridge() { if(cartridgeLoaded() == false) return; cheatDatabase->setVisible(false); - cheatEditor->save({ baseName, ".cht" }); - stateManager->save({ baseName, ".bsa" }, 0u); + cheatEditor->save(base.filename("cheats.xml", ".cht")); + stateManager->save(base.filename("states.bsa", ".bsa"), 0u); setCheatCodes(); switch(mode()) { @@ -108,7 +114,6 @@ void Interface::unloadCartridge() { } interface->baseName = ""; - interface->slotName.reset(); utility->setMode(mode = Mode::None); } @@ -140,7 +145,7 @@ bool Interface::unserialize(serializer &s) { } bool Interface::saveState(unsigned slot) { - string filename = { baseName, "-", slot, ".bst" }; + string filename = base.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" }); serializer s = serialize(); bool result = file::write(filename, s.data(), s.size()); utility->showMessage(result == true ? string{ "Saved state ", slot } : "Failed to save state"); @@ -148,7 +153,7 @@ bool Interface::saveState(unsigned slot) { } bool Interface::loadState(unsigned slot) { - string filename = { baseName, "-", slot, ".bst" }; + string filename = base.filename({ "state-", slot, ".bst" }, { "-", slot, ".bst" }); uint8_t *data; unsigned size; if(file::read(filename, data, size) == false) { diff --git a/bsnes/ui/interface/interface.hpp b/bsnes/ui/interface/interface.hpp index 3e1003eb..4ceb68ca 100755 --- a/bsnes/ui/interface/interface.hpp +++ b/bsnes/ui/interface/interface.hpp @@ -9,6 +9,12 @@ struct InterfaceCore { virtual bool unserialize(serializer&) = 0; }; +struct CartridgePath { + bool folder; + string name; + string filename(const string &folderName, const string &fileName) const; +}; + #include "nes/nes.hpp" #include "snes/snes.hpp" #include "gameboy/gameboy.hpp" @@ -58,8 +64,11 @@ struct Interface : property { bool applyPatch(const string &filename, uint8_t *&data, unsigned &size); void videoRefresh(const uint32_t *input, unsigned inputPitch, unsigned width, unsigned height); + CartridgePath base; + vector slot; + + //deprecated string baseName; // = "/path/to/cartridge" (no extension) - lstring slotName; InterfaceCore *core; InterfaceNES nes; diff --git a/bsnes/ui/interface/nes/nes.cpp b/bsnes/ui/interface/nes/nes.cpp index 49fc3f84..6bfa0efd 100755 --- a/bsnes/ui/interface/nes/nes.cpp +++ b/bsnes/ui/interface/nes/nes.cpp @@ -27,38 +27,31 @@ bool InterfaceNES::loadCartridge(const string &filename) { unsigned size; if(filename.endswith("/")) { - string basename = filename; - basename.rtrim<1>("/"); - basename.append("/", notdir(nall::basename(basename))); - - if(file::exists({ basename, ".prg" }) && file::exists({ basename, ".chr" })) { - unsigned prgsize = file::size({ basename, ".prg" }); - unsigned chrsize = file::size({ basename, ".chr" }); + if(file::exists({ filename, "program.rom" }) && file::exists({ filename, "character.rom" })) { + unsigned prgsize = file::size({ filename, "program.rom" }); + unsigned chrsize = file::size({ filename, "character.rom" }); data = new uint8_t[size = prgsize + chrsize]; nall::file fp; - fp.open({ basename, ".prg" }, file::mode::read); + fp.open({ filename, "program.rom" }, file::mode::read); fp.read(data, fp.size()); fp.close(); - fp.open({ basename, ".chr" }, file::mode::read); + fp.open({ filename, "character.rom" }, file::mode::read); fp.read(data + prgsize, fp.size()); fp.close(); - } else if(file::exists({ basename, ".fc" })) { - file::read({ basename, ".fc" }, data, size); } else { return false; } - - interface->baseName = basename; + interface->base = { true, filename }; } else { file::read(filename, data, size); - interface->baseName = nall::basename(filename); + interface->base = { false, nall::basename(filename) }; } interface->unloadCartridge(); - interface->applyPatch(interface->baseName, data, size); +//interface->applyPatch(interface->base.filename("patch.bps", ".bps"), data, size); string markup; - markup.readfile({ interface->baseName, ".xml" }); + markup.readfile(interface->base.filename("manifest.xml", ".xml")); NES::cartridge.load(markup, data, size); NES::system.power(); @@ -66,7 +59,7 @@ bool InterfaceNES::loadCartridge(const string &filename) { if(NES::cartridge.ram_size()) { filemap fp; - if(fp.open(string{ interface->baseName, ".sav" }, filemap::mode::read)) { + if(fp.open(interface->base.filename("program.ram", ".sav"), filemap::mode::read)) { memcpy(NES::cartridge.ram_data(), fp.data(), min(NES::cartridge.ram_size(), fp.size())); } } @@ -78,10 +71,10 @@ bool InterfaceNES::loadCartridge(const string &filename) { void InterfaceNES::unloadCartridge() { if(NES::cartridge.ram_size()) { - file::write({ interface->baseName, ".sav" }, NES::cartridge.ram_data(), NES::cartridge.ram_size()); + file::write(interface->base.filename("program.ram", ".sav"), NES::cartridge.ram_data(), NES::cartridge.ram_size()); } NES::cartridge.unload(); - interface->baseName = ""; + interface->base.name = ""; } // diff --git a/bsnes/ui/interface/snes/snes.cpp b/bsnes/ui/interface/snes/snes.cpp index 9c9fd386..b74decc5 100755 --- a/bsnes/ui/interface/snes/snes.cpp +++ b/bsnes/ui/interface/snes/snes.cpp @@ -30,29 +30,32 @@ bool InterfaceSNES::cartridgeLoaded() { return SNES::cartridge.loaded(); } -bool InterfaceSNES::loadFile(string &filename, uint8_t *&data, unsigned &size) { +bool InterfaceSNES::loadCartridge(const string &filename, CartridgePath &cartridge, uint8_t *&data, unsigned &size) { + auto backup = cartridge; + string suffix; if(filename.endswith("/")) { - filename.rtrim<1>("/"); - filename.append("/", notdir(filename)); + cartridge = { true, filename }; + } else { + suffix = { ".", extension(filename) }; + cartridge = { false, nall::basename(filename) }; } - if(file::read(filename, data, size) == false) return false; - filename = nall::basename(filename); - interface->applyPatch(filename, data, size); + if(file::read(cartridge.filename("program.rom", suffix), data, size) == false) { + cartridge = backup; + return false; + } +//interface->applyPatch(filename, data, size); return true; } bool InterfaceSNES::loadCartridge(string basename) { uint8_t *data; unsigned size; - if(loadFile(basename, data, size) == false) return false; - + if(loadCartridge(basename, interface->base, data, size) == false) return false; interface->unloadCartridge(); - interface->baseName = basename; - interface->slotName = { basename }; string markup; - markup.readfile({ interface->baseName, ".xml" }); - if(markup == "") markup = SnesCartridge(data, size).markup; + markup.readfile(interface->base.filename("manifest.xml", ".xml")); + if(markup.empty()) markup = SnesCartridge(data, size).markup; SNES::cartridge.rom.copy(data, size); SNES::cartridge.load(SNES::Cartridge::Mode::Normal, markup); @@ -69,17 +72,13 @@ bool InterfaceSNES::loadCartridge(string basename) { bool InterfaceSNES::loadSatellaviewSlottedCartridge(string basename, string slotname) { uint8_t *data[2]; unsigned size[2]; - if(loadFile(basename, data[0], size[0]) == false) return false; - loadFile(slotname, data[1], size[1]); - + if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false; + loadCartridge(slotname, interface->slot(0), data[1], size[1]); interface->unloadCartridge(); - interface->baseName = basename; - if(data[1]) interface->baseName.append("+", notdir(slotname)); - interface->slotName = { basename, slotname }; string markup; - markup.readfile({ interface->baseName, ".xml" }); - if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; + markup.readfile(interface->base.filename("manifest.xml", ".xml")); + if(markup.empty()) markup = SnesCartridge(data[0], size[0]).markup; SNES::cartridge.rom.copy(data[0], size[0]); if(data[1]) SNES::bsxflash.memory.copy(data[1], size[1]); @@ -98,17 +97,13 @@ bool InterfaceSNES::loadSatellaviewSlottedCartridge(string basename, string slot bool InterfaceSNES::loadSatellaviewCartridge(string basename, string slotname) { uint8_t *data[2]; unsigned size[2]; - if(loadFile(basename, data[0], size[0]) == false) return false; - loadFile(slotname, data[1], size[1]); - + if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false; + loadCartridge(slotname, interface->slot(0), data[1], size[1]); interface->unloadCartridge(); - interface->baseName = basename; - if(data[1]) interface->baseName.append("+", notdir(slotname)); - interface->slotName = { basename, slotname }; string markup; - markup.readfile({ interface->baseName, ".xml" }); - if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; + markup.readfile(interface->base.filename("manifest.xml", ".xml")); + if(markup.empty()) markup = SnesCartridge(data[0], size[0]).markup; SNES::cartridge.rom.copy(data[0], size[0]); if(data[1]) SNES::bsxflash.memory.copy(data[1], size[1]); @@ -127,20 +122,14 @@ bool InterfaceSNES::loadSatellaviewCartridge(string basename, string slotname) { bool InterfaceSNES::loadSufamiTurboCartridge(string basename, string slotAname, string slotBname) { uint8_t *data[3]; unsigned size[3]; - if(loadFile(basename, data[0], size[0]) == false) return false; - loadFile(slotAname, data[1], size[1]); - loadFile(slotBname, data[2], size[2]); - + if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false; + loadCartridge(slotAname, interface->slot(0), data[1], size[1]); + loadCartridge(slotBname, interface->slot(1), data[2], size[2]); interface->unloadCartridge(); - interface->baseName = basename; - if(data[1] && data[2]) interface->baseName = { slotAname, "+", notdir(slotBname) }; - else if(data[1]) interface->baseName = slotAname; - else if(data[2]) interface->baseName = slotBname; - interface->slotName = { basename, slotAname, slotBname }; string markup; - markup.readfile({ interface->baseName, ".xml" }); - if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; + markup.readfile(interface->base.filename("manifest.xml", ".xml")); + if(markup.empty()) markup = SnesCartridge(data[0], size[0]).markup; SNES::cartridge.rom.copy(data[0], size[0]); if(data[1]) SNES::sufamiturbo.slotA.rom.copy(data[1], size[1]); @@ -161,21 +150,17 @@ bool InterfaceSNES::loadSufamiTurboCartridge(string basename, string slotAname, bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname) { uint8_t *data[2]; unsigned size[2]; - if(loadFile(basename, data[0], size[0]) == false) return false; - loadFile(slotname, data[1], size[1]); - + if(loadCartridge(basename, interface->base, data[0], size[0]) == false) return false; + loadCartridge(slotname, interface->slot(0), data[1], size[1]); interface->unloadCartridge(); - interface->baseName = basename; - if(data[1]) interface->baseName = slotname; - interface->slotName = { basename, slotname }; string markup; - markup.readfile({ interface->baseName, ".xml" }); - if(markup == "") markup = SnesCartridge(data[0], size[0]).markup; + markup.readfile(interface->base.filename("manifest.xml", ".xml")); + if(markup.empty()) markup = SnesCartridge(data[0], size[0]).markup; string gbMarkup; - gbMarkup.readfile({ nall::basename(slotname), ".xml" }); - if(gbMarkup == "") gbMarkup = GameBoyCartridge(data[1], size[1]).markup; + gbMarkup.readfile(interface->slot[0].filename("manifest.xml", ".xml")); + if(gbMarkup.empty()) gbMarkup = GameBoyCartridge(data[1], size[1]).markup; SNES::cartridge.rom.copy(data[0], size[0]); GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, gbMarkup, data[1], size[1]); @@ -194,7 +179,8 @@ bool InterfaceSNES::loadSuperGameBoyCartridge(string basename, string slotname) void InterfaceSNES::unloadCartridge() { saveMemory(); SNES::cartridge.unload(); - interface->baseName = ""; + interface->base.name = ""; + interface->slot.reset(); } void InterfaceSNES::power() { @@ -209,14 +195,29 @@ void InterfaceSNES::run() { SNES::system.run(); } -//slot[] array = Cartridge::Slot to slot# conversion: -//{ Base, Bsx, SufamiTurbo, SufamiTurboA, SufamiTurboB, GameBoy } +string InterfaceSNES::memoryName(SNES::Cartridge::NonVolatileRAM &memory) { + if(memory.slot == SNES::Cartridge::Slot::Base) { + if(memory.id == "program.ram") return interface->base.filename("program.ram", ".srm"); + if(memory.id == "upd96050.ram") return interface->base.filename("upd96050.ram", ".nec"); + if(memory.id == "bsx.ram") return interface->base.filename("bsx.ram", ".bss"); + if(memory.id == "bsx.psram") return interface->base.filename("bsx.psram", ".bsp"); + } + if(memory.slot == SNES::Cartridge::Slot::SufamiTurboA) { + if(memory.id == "program.ram") return interface->slot[0].filename("program.ram", ".sts"); + } + if(memory.slot == SNES::Cartridge::Slot::SufamiTurboB) { + if(memory.id == "program.ram") return interface->slot[1].filename("program.ram", ".sts"); + } + return ""; +} void InterfaceSNES::loadMemory() { - static unsigned slot[] = { 0, 0, 0, 1, 2, 1 }; for(auto &memory : SNES::cartridge.nvram) { if(memory.size == 0) continue; - string filename = { interface->slotName[slot[(unsigned)memory.slot]], memory.id }; + + string filename = memoryName(memory); + if(filename.empty()) continue; + uint8_t *data; unsigned size; if(file::read(filename, data, size)) { @@ -227,10 +228,12 @@ void InterfaceSNES::loadMemory() { } void InterfaceSNES::saveMemory() { - static unsigned slot[] = { 0, 0, 0, 1, 2, 1 }; for(auto &memory : SNES::cartridge.nvram) { if(memory.size == 0) continue; - string filename = { interface->slotName[slot[(unsigned)memory.slot]], memory.id }; + + string filename = memoryName(memory); + if(filename.empty()) continue; + file::write(filename, memory.data, memory.size); } } @@ -356,8 +359,17 @@ int16_t InterfaceSNES::inputPoll(bool port, SNES::Input::Device device, unsigned } string InterfaceSNES::path(SNES::Cartridge::Slot slot, const string &hint) { - static unsigned index[] = { 0, 0, 0, 1, 2, 1 }; - return { interface->slotName[index[(unsigned)slot]], hint }; + if(slot == SNES::Cartridge::Slot::Base) { + if(hint == "msu1.rom") return interface->base.filename("msu1.rom", ".msu"); + if(hint.wildcard("track-*.pcm")) { + string track = hint; + track.trim<1>("track-", ".pcm"); + return interface->base.filename(hint, { "-", decimal(track), ".pcm" }); + } + if(hint == "serial.so") return { dir(interface->base.name), "libserial.so" }; + if(hint.endswith(".rom")) return { dir(interface->base.name), hint }; + } + return { dir(interface->base.name), hint }; } void InterfaceSNES::message(const string &text) { diff --git a/bsnes/ui/interface/snes/snes.hpp b/bsnes/ui/interface/snes/snes.hpp index 981eab40..f6fc7cc2 100755 --- a/bsnes/ui/interface/snes/snes.hpp +++ b/bsnes/ui/interface/snes/snes.hpp @@ -4,7 +4,7 @@ struct InterfaceSNES : InterfaceCore, SNES::Interface { void setController(bool port, unsigned device); bool cartridgeLoaded(); - bool loadFile(string &filename, uint8_t *&data, unsigned &size); + bool loadCartridge(const string &filename, CartridgePath &cartridge, uint8_t *&data, unsigned &size); bool loadCartridge(string basename); bool loadSatellaviewSlottedCartridge(string basename, string slotname); bool loadSatellaviewCartridge(string basename, string slotname); @@ -16,6 +16,7 @@ struct InterfaceSNES : InterfaceCore, SNES::Interface { void reset(); void run(); + string memoryName(SNES::Cartridge::NonVolatileRAM &memory); void loadMemory(); void saveMemory();