From 875f031182d392aab09a086f5fa47a2f950ac65b Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 21 Jun 2016 15:22:52 +1000 Subject: [PATCH] Update to v099r06 release. byuu says: Changelog: - Super Famicom core converted to use nall/vfs - excludes Super Game Boy; since that's invoked from inside the GB core This was definitely the major obstacle to test nall/vfs' applicability. Things worked out pretty great in the end. We went from 22.0KiB (cartridge) + 18.6KiB (interface) to 24.5KiB (cartridge) + 11.4KiB (interface). Or 40.7KiB to 36.0KiB. This removes a very large source of indirection. Before it was: "coprocessor <=> cartridge <=> interface" for loading and saving data, and now it's just "coprocessor <=> cartridge". And it may make sense to eventually turn this into just "cartridge -> coprocessor" by making each coprocessor class handle its own markup parsing. It's nice to have all the manifest parsing in one location (well, sans MSU1); but it's also nice for loading/unloading to be handled by each coprocessor itself. So I'll have to think longer about that one. I've also started handling Interface::save() differently. Instead of keeping track of memory IDs and filenames, and iterating through that vector of objects ... instead I now have a system that mirrors the markup parsing on loading, but handles saving instead. This was actually the reason the code size savings weren't more significant, but I like this style more. As before, it removes an extra level of indirection. So ... next up, I need to port over the GB, then GBA, then WS cores. These shouldn't take too long since they're all very simple with just ROM+RAM(+RTC) right now. Then get the SGB callbacks using vfs. Then after that, gut all the old stream stuff from nall and higan. Kill the (load,save)Request stuff, rename the load(Gamepak)Request to something simpler, and then we should be good. Anyway ... these are some huge changes. --- higan/emulator/emulator.hpp | 2 +- higan/emulator/interface.hpp | 4 +- higan/fc/cartridge/cartridge.cpp | 2 +- higan/fc/system/system.cpp | 2 +- higan/sfc/cartridge/cartridge.cpp | 183 +++------ higan/sfc/cartridge/cartridge.hpp | 138 ++++--- higan/sfc/cartridge/load.cpp | 334 +++++++++++++++ higan/sfc/cartridge/markup.cpp | 385 ------------------ higan/sfc/cartridge/save.cpp | 123 ++++++ .../sfc/coprocessor/armdsp/serialization.cpp | 2 +- .../coprocessor/hitachidsp/serialization.cpp | 2 +- higan/sfc/coprocessor/msu1/msu1.cpp | 4 +- .../sfc/coprocessor/necdsp/serialization.cpp | 2 +- higan/sfc/interface/interface.cpp | 217 +--------- higan/sfc/interface/interface.hpp | 72 +--- higan/sfc/memory/memory-inline.hpp | 6 + higan/sfc/memory/memory.hpp | 1 + higan/sfc/sfc.hpp | 6 + higan/sfc/system/serialization.cpp | 30 +- higan/sfc/system/system.cpp | 172 ++++---- higan/sfc/system/system.hpp | 3 +- nall/vfs/vfs.hpp | 10 +- 22 files changed, 740 insertions(+), 960 deletions(-) create mode 100644 higan/sfc/cartridge/load.cpp delete mode 100644 higan/sfc/cartridge/markup.cpp create mode 100644 higan/sfc/cartridge/save.cpp diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 5fb50a6e..f5c5ab6f 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -10,7 +10,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "099.05"; + static const string Version = "099.06"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/higan/emulator/interface.hpp b/higan/emulator/interface.hpp index e6d94db1..14fea131 100644 --- a/higan/emulator/interface.hpp +++ b/higan/emulator/interface.hpp @@ -79,8 +79,8 @@ struct Interface { //video information virtual auto videoFrequency() -> double = 0; - virtual auto videoColors() -> uint32 { return 1 << 19; } - virtual auto videoColor(uint32 color) -> uint64 { return 0; } + virtual auto videoColors() -> uint32 = 0; + virtual auto videoColor(uint32 color) -> uint64 = 0; //audio information virtual auto audioFrequency() -> double = 0; diff --git a/higan/fc/cartridge/cartridge.cpp b/higan/fc/cartridge/cartridge.cpp index 660e8522..6faa3932 100644 --- a/higan/fc/cartridge/cartridge.cpp +++ b/higan/fc/cartridge/cartridge.cpp @@ -28,7 +28,7 @@ auto Cartridge::main() -> void { auto Cartridge::load() -> bool { if(auto fp = interface->open(ID::Famicom, "manifest.bml", vfs::file::mode::read, true)) { - fp->reads(information.markup); + information.markup = fp->reads(); } else { return false; } diff --git a/higan/fc/system/system.cpp b/higan/fc/system/system.cpp index 5d08d836..1c574fe9 100644 --- a/higan/fc/system/system.cpp +++ b/higan/fc/system/system.cpp @@ -23,7 +23,7 @@ auto System::runToSave() -> void { auto System::load() -> bool { if(auto fp = interface->open(ID::System, "manifest.bml", vfs::file::mode::read, true)) { - fp->reads(information.manifest); + information.manifest = fp->reads(); } else { return false; } diff --git a/higan/sfc/cartridge/cartridge.cpp b/higan/sfc/cartridge/cartridge.cpp index 90bf521a..8fd22ced 100644 --- a/higan/sfc/cartridge/cartridge.cpp +++ b/higan/sfc/cartridge/cartridge.cpp @@ -2,108 +2,53 @@ namespace SuperFamicom { -#include "markup.cpp" +#include "load.cpp" +#include "save.cpp" #include "serialization.cpp" Cartridge cartridge; -auto Cartridge::manifest() -> string { - string manifest = information.markup.cartridge; - - if(information.markup.gameBoy) { - manifest.append("\n[[Game Boy]]\n\n"); - manifest.append(information.markup.gameBoy); - } - - if(information.markup.bsMemory) { - manifest.append("\n[[BS Memory]]\n\n"); - manifest.append(information.markup.bsMemory); - } - - if(information.markup.sufamiTurboA) { - manifest.append("\n[[Sufami Turbo - Slot A]]\n\n"); - manifest.append(information.markup.sufamiTurboA); - } - - if(information.markup.sufamiTurboB) { - manifest.append("\n[[Sufami Turbo - Slot B]]\n\n"); - manifest.append(information.markup.sufamiTurboB); - } - +auto Cartridge::manifest() const -> string { + string manifest = information.manifest.cartridge; + if(information.manifest.gameBoy) manifest.append("\n[[Game Boy]]\n\n", information.manifest.gameBoy); + if(information.manifest.bsMemory) manifest.append("\n[[BS Memory]]\n\n", information.manifest.bsMemory); + if(information.manifest.sufamiTurboA) manifest.append("\n[[Sufami Turbo - Slot A]]\n\n", information.manifest.sufamiTurboA); + if(information.manifest.sufamiTurboB) manifest.append("\n[[Sufami Turbo - Slot B]]\n\n", information.manifest.sufamiTurboB); return manifest; } -auto Cartridge::title() -> string { +auto Cartridge::title() const -> string { string title = information.title.cartridge; - - if(information.title.gameBoy) { - title.append(" + ", information.title.gameBoy); - } - - if(information.title.bsMemory) { - title.append(" + ", information.title.bsMemory); - } - - if(information.title.sufamiTurboA) { - title.append(" + ", information.title.sufamiTurboA); - } - - if(information.title.sufamiTurboB) { - title.append(" + ", information.title.sufamiTurboB); - } - + if(information.title.gameBoy) title.append(" + ", information.title.gameBoy); + if(information.title.bsMemory) title.append(" + ", information.title.bsMemory); + if(information.title.sufamiTurboA) title.append(" + ", information.title.sufamiTurboA); + if(information.title.sufamiTurboB) title.append(" + ", information.title.sufamiTurboB); return title; } -auto Cartridge::load() -> void { +auto Cartridge::load() -> bool { + information = Information(); + has = Has(); + _sha256 = ""; _region = Region::NTSC; - hasICD2 = false; - hasMCC = false; - hasNSSDIP = false; - hasEvent = false; - hasSA1 = false; - hasSuperFX = false; - hasARMDSP = false; - hasHitachiDSP = false; - hasNECDSP = false; - hasEpsonRTC = false; - hasSharpRTC = false; - hasSPC7110 = false; - hasSDD1 = false; - hasOBC1 = false; - hasMSU1 = false; - - hasGameBoySlot = false; - hasBSMemorySlot = false; - hasSufamiTurboSlots = false; - - information.markup.cartridge = ""; - information.markup.gameBoy = ""; - information.markup.bsMemory = ""; - information.markup.sufamiTurboA = ""; - information.markup.sufamiTurboB = ""; - - information.title.cartridge = ""; - information.title.gameBoy = ""; - information.title.bsMemory = ""; - information.title.sufamiTurboA = ""; - information.title.sufamiTurboB = ""; - - interface->loadRequest(ID::Manifest, "manifest.bml", true); - parseMarkup(information.markup.cartridge); + if(auto fp = interface->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) { + information.manifest.cartridge = fp->reads(); + } else return false; + auto document = BML::unserialize(information.manifest.cartridge); + loadCartridge(document); //Game Boy - if(cartridge.hasICD2) { + if(cartridge.has.ICD2) { _sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy() } //BS Memory - else if(cartridge.hasMCC && cartridge.hasBSMemorySlot) { + else if(cartridge.has.MCC && cartridge.has.BSMemorySlot) { _sha256 = Hash::SHA256(bsmemory.memory.data(), bsmemory.memory.size()).digest(); } //Sufami Turbo - else if(cartridge.hasSufamiTurboSlots) { + else if(cartridge.has.SufamiTurboSlots) { Hash::SHA256 sha; sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size()); sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size()); @@ -136,85 +81,51 @@ auto Cartridge::load() -> void { rom.writeProtect(true); ram.writeProtect(false); + return true; } auto Cartridge::loadGameBoy() -> void { #if defined(SFC_SUPERGAMEBOY) //invoked from ICD2::load() _sha256 = GameBoy::interface->sha256(); - information.markup.gameBoy = GameBoy::interface->manifest(); + information.manifest.gameBoy = GameBoy::interface->manifest(); information.title.gameBoy = GameBoy::interface->title(); #endif + loadGameBoy(BML::unserialize(information.manifest.gameBoy)); } auto Cartridge::loadBSMemory() -> void { - interface->loadRequest(ID::BSMemoryManifest, "manifest.bml", true); - auto document = BML::unserialize(information.markup.bsMemory); - information.title.bsMemory = document["information/title"].text(); - - auto rom = document["board/rom"]; - - if(rom["name"]) { - uint size = rom["size"].natural(); - bsmemory.memory.map(allocate(size, 0xff), size); - interface->loadRequest(ID::BSMemoryROM, rom["name"].text(), true); - - bsmemory.readonly = (rom["type"].text() == "mrom"); - } + if(auto fp = interface->open(ID::BSMemory, "manifest.bml", File::Read, File::Required)) { + information.manifest.bsMemory = fp->reads(); + } else return; + loadBSMemory(BML::unserialize(information.manifest.bsMemory)); } auto Cartridge::loadSufamiTurboA() -> void { - interface->loadRequest(ID::SufamiTurboSlotAManifest, "manifest.bml", true); - auto document = BML::unserialize(information.markup.sufamiTurboA); - information.title.sufamiTurboA = document["information/title"].text(); - - auto rom = document["board/rom"]; - auto ram = document["board/ram"]; - - if(rom["name"]) { - uint size = rom["size"].natural(); - sufamiturboA.rom.map(allocate(size, 0xff), size); - interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].text(), true); - } - - if(ram["name"]) { - uint size = ram["size"].natural(); - sufamiturboA.ram.map(allocate(size, 0xff), size); - interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].text(), false); - memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()}); - } - - if(document["board/linkable"]) { - interface->loadRequest(ID::SufamiTurboSlotB, "Sufami Turbo", "st", false); - } + if(auto fp = interface->open(ID::SufamiTurboA, "manifest.bml", File::Read, File::Required)) { + information.manifest.sufamiTurboA = fp->reads(); + } else return; + loadSufamiTurboA(BML::unserialize(information.manifest.sufamiTurboA)); } auto Cartridge::loadSufamiTurboB() -> void { - interface->loadRequest(ID::SufamiTurboSlotBManifest, "manifest.bml", true); - auto document = BML::unserialize(information.markup.sufamiTurboB); - information.title.sufamiTurboB = document["information/title"].text(); + if(auto fp = interface->open(ID::SufamiTurboB, "manifest.bml", File::Read, File::Required)) { + information.manifest.sufamiTurboB = fp->reads(); + } else return; + loadSufamiTurboB(BML::unserialize(information.manifest.sufamiTurboB)); +} - auto rom = document["board/rom"]; - auto ram = document["board/ram"]; - - if(rom["name"]) { - uint size = rom["size"].natural(); - sufamiturboB.rom.map(allocate(size, 0xff), size); - interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].text(), true); - } - - if(ram["name"]) { - uint size = ram["size"].natural(); - sufamiturboB.ram.map(allocate(size, 0xff), size); - interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].text(), false); - memory.append({ID::SufamiTurboSlotBRAM, ram["name"].text()}); - } +auto Cartridge::save() -> void { + saveCartridge(BML::unserialize(information.manifest.cartridge)); + saveGameBoy(BML::unserialize(information.manifest.gameBoy)); + saveBSMemory(BML::unserialize(information.manifest.bsMemory)); + saveSufamiTurboA(BML::unserialize(information.manifest.sufamiTurboA)); + saveSufamiTurboB(BML::unserialize(information.manifest.sufamiTurboB)); } auto Cartridge::unload() -> void { rom.reset(); ram.reset(); - memory.reset(); } } diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 82a79bfd..141e536e 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -3,11 +3,11 @@ struct Cartridge { auto sha256() const -> string { return _sha256; } auto region() const -> Region { return _region; } + auto manifest() const -> string; + auto title() const -> string; - auto manifest() -> string; - auto title() -> string; - - auto load() -> void; + auto load() -> bool; + auto save() -> void; auto unload() -> void; auto serialize(serializer&) -> void; @@ -15,20 +15,14 @@ struct Cartridge { MappedRAM rom; MappedRAM ram; - struct Memory { - unsigned id; - string name; - }; - vector memory; - struct Information { - struct Markup { + struct Manifest { string cartridge; string gameBoy; string bsMemory; string sufamiTurboA; string sufamiTurboB; - } markup; + } manifest; struct Title { string cartridge; @@ -39,62 +33,94 @@ struct Cartridge { } title; } information; - bool hasICD2; - bool hasMCC; - bool hasNSSDIP; - bool hasEvent; - bool hasSA1; - bool hasSuperFX; - bool hasARMDSP; - bool hasHitachiDSP; - bool hasNECDSP; - bool hasEpsonRTC; - bool hasSharpRTC; - bool hasSPC7110; - bool hasSDD1; - bool hasOBC1; - bool hasMSU1; + struct Has { + boolean ICD2; + boolean MCC; + boolean NSSDIP; + boolean Event; + boolean SA1; + boolean SuperFX; + boolean ARMDSP; + boolean HitachiDSP; + boolean NECDSP; + boolean EpsonRTC; + boolean SharpRTC; + boolean SPC7110; + boolean SDD1; + boolean OBC1; + boolean MSU1; - bool hasGameBoySlot; - bool hasBSMemorySlot; - bool hasSufamiTurboSlots; + boolean GameBoySlot; + boolean BSMemorySlot; + boolean SufamiTurboSlots; + } has; private: + //cartridge.cpp auto loadGameBoy() -> void; auto loadBSMemory() -> void; auto loadSufamiTurboA() -> void; auto loadSufamiTurboB() -> void; - friend class Interface; - friend class ICD2; - //markup.cpp - auto parseMarkup(const string&) -> void; - auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void; - auto parseMarkupMap(Markup::Node, const function&, const function&) -> void; - auto parseMarkupMemory(MappedRAM&, Markup::Node, uint id, bool writable) -> void; + //load.cpp + auto loadCartridge(Markup::Node) -> void; + auto loadGameBoy(Markup::Node) -> void; + auto loadBSMemory(Markup::Node) -> void; + auto loadSufamiTurboA(Markup::Node) -> void; + auto loadSufamiTurboB(Markup::Node) -> void; - auto parseMarkupROM(Markup::Node) -> void; - auto parseMarkupRAM(Markup::Node) -> void; - auto parseMarkupICD2(Markup::Node) -> void; - auto parseMarkupMCC(Markup::Node) -> void; - auto parseMarkupBSMemory(Markup::Node) -> void; - auto parseMarkupSufamiTurbo(Markup::Node, bool slot) -> void; - auto parseMarkupNSS(Markup::Node) -> void; - auto parseMarkupEvent(Markup::Node) -> void; - auto parseMarkupSA1(Markup::Node) -> void; - auto parseMarkupSuperFX(Markup::Node) -> void; - auto parseMarkupARMDSP(Markup::Node) -> void; - auto parseMarkupHitachiDSP(Markup::Node, unsigned roms) -> void; - auto parseMarkupNECDSP(Markup::Node) -> void; - auto parseMarkupEpsonRTC(Markup::Node) -> void; - auto parseMarkupSharpRTC(Markup::Node) -> void; - auto parseMarkupSPC7110(Markup::Node) -> void; - auto parseMarkupSDD1(Markup::Node) -> void; - auto parseMarkupOBC1(Markup::Node) -> void; - auto parseMarkupMSU1(Markup::Node) -> void; + auto loadROM(Markup::Node) -> void; + auto loadRAM(Markup::Node) -> void; + auto loadICD2(Markup::Node) -> void; + auto loadMCC(Markup::Node) -> void; + auto loadBSMemoryPack(Markup::Node) -> void; + auto loadSufamiTurbo(Markup::Node, bool slot) -> void; + auto loadNSS(Markup::Node) -> void; + auto loadEvent(Markup::Node) -> void; + auto loadSA1(Markup::Node) -> void; + auto loadSuperFX(Markup::Node) -> void; + auto loadARMDSP(Markup::Node) -> void; + auto loadHitachiDSP(Markup::Node, uint roms) -> void; + auto loadNECDSP(Markup::Node) -> void; + auto loadEpsonRTC(Markup::Node) -> void; + auto loadSharpRTC(Markup::Node) -> void; + auto loadSPC7110(Markup::Node) -> void; + auto loadSDD1(Markup::Node) -> void; + auto loadOBC1(Markup::Node) -> void; + auto loadMSU1(Markup::Node) -> void; + + auto loadMemory(MappedRAM&, Markup::Node, bool writable, uint id = 1) -> void; + auto loadMap(Markup::Node, SuperFamicom::Memory&) -> void; + auto loadMap(Markup::Node, const function&, const function&) -> void; + + //save.cpp + auto saveCartridge(Markup::Node) -> void; + auto saveGameBoy(Markup::Node) -> void; + auto saveBSMemory(Markup::Node) -> void; + auto saveSufamiTurboA(Markup::Node) -> void; + auto saveSufamiTurboB(Markup::Node) -> void; + + auto saveRAM(Markup::Node) -> void; + auto saveMCC(Markup::Node) -> void; + auto saveEvent(Markup::Node) -> void; + auto saveSA1(Markup::Node) -> void; + auto saveSuperFX(Markup::Node) -> void; + auto saveARMDSP(Markup::Node) -> void; + auto saveHitachiDSP(Markup::Node) -> void; + auto saveNECDSP(Markup::Node) -> void; + auto saveEpsonRTC(Markup::Node) -> void; + auto saveSharpRTC(Markup::Node) -> void; + auto saveSPC7110(Markup::Node) -> void; + auto saveSDD1(Markup::Node) -> void; + auto saveOBC1(Markup::Node) -> void; + + auto saveMemory(MappedRAM&, Markup::Node, uint = 1) -> void; string _sha256; Region _region = Region::NTSC; + + friend class Interface; + friend class ICD2; }; extern Cartridge cartridge; diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp new file mode 100644 index 00000000..14f97b44 --- /dev/null +++ b/higan/sfc/cartridge/load.cpp @@ -0,0 +1,334 @@ +auto Cartridge::loadCartridge(Markup::Node node) -> void { + information.title.cartridge = node["information/title"].text(); + auto board = node["board"]; + _region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; + + if(auto node = board["rom"]) loadROM(node); + if(auto node = board["ram"]) loadRAM(node); + if(auto node = board["icd2"]) loadICD2(node); + if(auto node = board["mcc"]) loadMCC(node); + if(auto node = board["bsmemory"]) loadBSMemoryPack(node); + if(auto node = board.find("sufamiturbo")) if(node(0)) loadSufamiTurbo(node(0), 0); + if(auto node = board.find("sufamiturbo")) if(node(1)) loadSufamiTurbo(node(1), 1); + if(auto node = board["nss"]) loadNSS(node); + if(auto node = board["event"]) loadEvent(node); + if(auto node = board["sa1"]) loadSA1(node); + if(auto node = board["superfx"]) loadSuperFX(node); + if(auto node = board["armdsp"]) loadARMDSP(node); + if(auto node = board["hitachidsp"]) loadHitachiDSP(node, node["information/board"].text().match("2DC*") ? 2 : 1); + if(auto node = board["necdsp"]) loadNECDSP(node); + if(auto node = board["epsonrtc"]) loadEpsonRTC(node); + if(auto node = board["sharprtc"]) loadSharpRTC(node); + if(auto node = board["spc7110"]) loadSPC7110(node); + if(auto node = board["sdd1"]) loadSDD1(node); + if(auto node = board["obc1"]) loadOBC1(node); + if(auto node = board["msu1"]) loadMSU1(node); + + if(board["mcc"] || board["bsmemory"]) interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false); + if(board["sufamiturbo"]) interface->loadRequest(ID::SufamiTurboA, "Sufami Turbo", "st", false); +} + +auto Cartridge::loadGameBoy(Markup::Node node) -> void { +} + +auto Cartridge::loadBSMemory(Markup::Node node) -> void { + information.title.bsMemory = node["information/title"].text(); + bsmemory.readonly = (node["board/rom/type"].text() == "mrom"); + + loadMemory(bsmemory.memory, node["board/rom"], false); +} + +auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { + information.title.sufamiTurboA = node["information/title"].text(); + + loadMemory(sufamiturboA.rom, node["rom"], ID::SufamiTurboA); + loadMemory(sufamiturboA.ram, node["ram"], ID::SufamiTurboA); + + if(node["board/linkable"]) interface->loadRequest(ID::SufamiTurboB, "Sufami Turbo", "st", false); +} + +auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { + information.title.sufamiTurboB = node["information/title"].text(); + + loadMemory(sufamiturboB.rom, node["rom"], ID::SufamiTurboB); + loadMemory(sufamiturboB.ram, node["ram"], ID::SufamiTurboB); +} + +// + +auto Cartridge::loadROM(Markup::Node root) -> void { + loadMemory(rom, root, false); + for(auto node : root.find("map")) loadMap(node, rom); +} + +auto Cartridge::loadRAM(Markup::Node root) -> void { + loadMemory(ram, root, true); + for(auto node : root.find("map")) loadMap(node, ram); +} + +auto Cartridge::loadICD2(Markup::Node root) -> void { + has.GameBoySlot = true; + has.ICD2 = true; + icd2.revision = max(1, root["revision"].natural()); + + //Game Boy core loads data through ICD2 interface + for(auto node : root.find("map")) loadMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2}); +} + +auto Cartridge::loadMCC(Markup::Node root) -> void { + has.BSMemorySlot = true; + has.MCC = true; + + loadMemory(mcc.rom, root["rom"], false); + loadMemory(mcc.ram, root["ram"], true); + + for(auto node : root.find("map")) node.text() == "mcu" + ? loadMap(node, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc}) + : loadMap(node, {&MCC::read, &mcc}, {&MCC::write, &mcc}); + for(auto node : root["ram"].find("map")) loadMap(node, mcc.ram); +} + +auto Cartridge::loadBSMemoryPack(Markup::Node root) -> void { + has.BSMemorySlot = true; + + for(auto node : root.find("map")) { + if(bsmemory.memory.size() == 0) continue; + loadMap(node, bsmemory); + } +} + +auto Cartridge::loadSufamiTurbo(Markup::Node root, bool slot) -> void { + has.SufamiTurboSlots = true; + + for(auto node : root["rom"].find("map")) { + auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); + if(cart.rom.size() == 0) continue; + loadMap(node, cart.rom); + } + + for(auto node : root["ram"].find("map")) { + auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); + if(cart.ram.size() == 0) continue; + loadMap(node, cart.ram); + } +} + +auto Cartridge::loadNSS(Markup::Node root) -> void { + has.NSSDIP = true; + nss.dip = interface->dipSettings(root); + + for(auto node : root.find("map")) loadMap(node, {&NSS::read, &nss}, {&NSS::write, &nss}); +} + +auto Cartridge::loadEvent(Markup::Node root) -> void { + auto roms = root.find("rom"); + if(roms.size() != 4) return; + + has.Event = true; + + for(uint n : range(4)) loadMemory(event.rom[n], roms[n], false); + loadMemory(event.ram, root["ram"], true); + + event.board = Event::Board::CampusChallenge92; + if(root.text() == "CC92") event.board = Event::Board::CampusChallenge92; + if(root.text() == "PF94") event.board = Event::Board::Powerfest94; + event.timer = root["timer"].natural(); + + for(auto node : root.find("map")) node.text() == "mcu" + ? loadMap(node, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}) + : loadMap(node, {&Event::read, &event}, {&Event::write, &event}); + for(auto node : root["ram"].find("map")) loadMap(node, event.ram); +} + +auto Cartridge::loadSA1(Markup::Node root) -> void { + has.SA1 = true; + + loadMemory(sa1.rom, root["rom"], false); + loadMemory(sa1.bwram, root["bwram"], true); + loadMemory(sa1.iram, root["iram"], true); + + for(auto node : root.find("map")) loadMap(node, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1}); + for(auto node : root["rom"].find("map")) loadMap(node, {&SA1::mmcromRead, &sa1}, {&SA1::mmcromWrite, &sa1}); + for(auto node : root["bwram"].find("map")) loadMap(node, {&SA1::mmcbwramRead, &sa1}, {&SA1::mmcbwramWrite, &sa1}); + for(auto node : root["iram"].find("map")) loadMap(node, sa1.cpuiram); +} + +auto Cartridge::loadSuperFX(Markup::Node root) -> void { + has.SuperFX = true; + + loadMemory(superfx.rom, root["rom"], false); + loadMemory(superfx.ram, root["ram"], true); + + for(auto node : root.find("map")) loadMap(node, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx}); + for(auto node : root["rom"].find("map")) loadMap(node, superfx.cpurom); + for(auto node : root["ram"].find("map")) loadMap(node, superfx.cpuram); +} + +auto Cartridge::loadARMDSP(Markup::Node root) -> void { + has.ARMDSP = true; + + if(auto fp = interface->open(ID::SuperFamicom, root["prom"]["name"].text(), File::Read, File::Required)) { + for(auto n : range(128 * 1024)) armdsp.programROM[n] = fp->read(); + } + if(auto fp = interface->open(ID::SuperFamicom, root["drom"]["name"].text(), File::Read, File::Required)) { + for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = fp->read(); + } + if(auto fp = interface->open(ID::SuperFamicom, root["ram"]["name"].text(), File::Read)) { + for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read(); + } + + for(auto node : root.find("map")) loadMap(node, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp}); +} + +auto Cartridge::loadHitachiDSP(Markup::Node root, uint roms) -> void { + has.HitachiDSP = true; + + hitachidsp.Frequency = root["frequency"].natural(); + if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000; + hitachidsp.Roms = roms; //1 or 2 + + loadMemory(hitachidsp.rom, root["rom"], false); + loadMemory(hitachidsp.ram, root["ram"], true); + + for(auto& word : hitachidsp.dataROM) word = 0x000000; + for(auto& word : hitachidsp.dataRAM) word = 0x00; + + if(auto fp = interface->open(ID::SuperFamicom, root["drom"]["name"].text(), File::Read, File::Required)) { + for(auto n : range(1 * 1024)) hitachidsp.dataROM[n] = fp->readl(3); + } + if(auto fp = interface->open(ID::SuperFamicom, root["dram"]["name"].text(), File::Read)) { + for(auto n : range(3 * 1024)) hitachidsp.dataRAM[n] = fp->readl(1); + } + + for(auto node : root.find("map")) loadMap(node, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp}); + for(auto node : root["rom"].find("map")) loadMap(node, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp}); + for(auto node : root["ram"].find("map")) loadMap(node, {&HitachiDSP::ramRead, &hitachidsp}, {&HitachiDSP::ramWrite, &hitachidsp}); + for(auto node : root["dram"].find("map")) loadMap(node, {&HitachiDSP::dramRead, &hitachidsp}, {&HitachiDSP::dramWrite, &hitachidsp}); +} + +auto Cartridge::loadNECDSP(Markup::Node root) -> void { + has.NECDSP = true; + + necdsp.frequency = root["frequency"].natural(); + if(necdsp.frequency == 0) necdsp.frequency = 8000000; + necdsp.revision + = root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 + : root["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 + : NECDSP::Revision::uPD7725; + + for(auto& word : necdsp.programROM) word = 0x000000; + for(auto& word : necdsp.dataROM) word = 0x0000; + for(auto& word : necdsp.dataRAM) word = 0x0000; + + uint size[3] = {0}; + if(necdsp.revision == NECDSP::Revision::uPD7725 ) memory::assign(size, 2048, 1024, 256); + if(necdsp.revision == NECDSP::Revision::uPD96050) memory::assign(size, 16384, 2048, 2048); + + if(auto fp = interface->open(ID::SuperFamicom, root["prom"]["name"].text(), File::Read, File::Required)) { + for(auto n : range(size[0])) necdsp.programROM[n] = fp->readl(3); + } + if(auto fp = interface->open(ID::SuperFamicom, root["drom"]["name"].text(), File::Read, File::Required)) { + for(auto n : range(size[1])) necdsp.dataROM[n] = fp->readl(2); + } + if(auto fp = interface->open(ID::SuperFamicom, root["dram"]["name"].text(), File::Read)) { + for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2); + } + + for(auto node : root.find("map")) loadMap(node, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); + for(auto node : root["dram"].find("map")) loadMap(node, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); +} + +auto Cartridge::loadEpsonRTC(Markup::Node root) -> void { + has.EpsonRTC = true; + + if(auto fp = interface->open(ID::SuperFamicom, root["ram"]["name"].text(), File::Read)) { + uint8 data[16] = {0}; + for(auto& byte : data) fp->read(); + epsonrtc.load(data); + } + + for(auto node : root.find("map")) loadMap(node, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc}); +} + +auto Cartridge::loadSharpRTC(Markup::Node root) -> void { + has.SharpRTC = true; + + if(auto fp = interface->open(ID::SuperFamicom, root["ram"]["name"].text(), File::Read)) { + uint8 data[16] = {0}; + for(auto& byte : data) fp->read(); + sharprtc.load(data); + } + + for(auto node : root.find("map")) loadMap(node, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc}); +} + +auto Cartridge::loadSPC7110(Markup::Node root) -> void { + has.SPC7110 = true; + + loadMemory(spc7110.prom, root["prom"], false); + loadMemory(spc7110.drom, root["drom"], false); + loadMemory(spc7110.ram, root["ram"], true); + + for(auto node : root.find("map")) node.text() == "mcu" + ? loadMap(node, {&SPC7110::mcuromRead, &spc7110}, {&SPC7110::mcuromWrite, &spc7110}) + : loadMap(node, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110}); + for(auto node : root["ram"].find("map")) loadMap(node, {&SPC7110::mcuramRead, &spc7110}, {&SPC7110::mcuramWrite, &spc7110}); +} + +auto Cartridge::loadSDD1(Markup::Node root) -> void { + has.SDD1 = true; + + loadMemory(sdd1.rom, root["rom"], false); + loadMemory(sdd1.ram, root["ram"], true); + + for(auto node : root.find("map")) loadMap(node, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}); + for(auto node : root["rom"].find("map")) loadMap(node, {&SDD1::mcuromRead, &sdd1}, {&SDD1::mcuromWrite, &sdd1}); + for(auto node : root["ram"].find("map")) loadMap(node, {&SDD1::mcuramRead, &sdd1}, {&SDD1::mcuramWrite, &sdd1}); +} + +auto Cartridge::loadOBC1(Markup::Node root) -> void { + has.OBC1 = true; + + loadMemory(obc1.ram, root["ram"], true); + + for(auto node : root.find("map")) loadMap(node, {&OBC1::read, &obc1}, {&OBC1::write, &obc1}); +} + +auto Cartridge::loadMSU1(Markup::Node root) -> void { + has.MSU1 = true; + + for(auto node : root.find("map")) loadMap(node, {&MSU1::read, &msu1}, {&MSU1::write, &msu1}); +} + +// + +auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool writable, uint id) -> void { + auto name = node["name"].text(); + auto size = node["size"].natural(); + ram.allocate(size); + if(auto fp = interface->open(id, name, File::Read, !writable)) { //treat ROM as required; RAM as optional + fp->read(ram.data(), ram.size()); + } +} + +auto Cartridge::loadMap(Markup::Node map, SuperFamicom::Memory& memory) -> void { + auto addr = map["address"].text(); + auto size = map["size"].natural(); + auto base = map["base"].natural(); + auto mask = map["mask"].natural(); + if(size == 0) size = memory.size(); + if(size == 0) return; + bus.map({&SuperFamicom::Memory::read, &memory}, {&SuperFamicom::Memory::write, &memory}, addr, size, base, mask); +} + +auto Cartridge::loadMap( + Markup::Node map, + const function& reader, + const function& writer +) -> void { + auto addr = map["address"].text(); + auto size = map["size"].natural(); + auto base = map["base"].natural(); + auto mask = map["mask"].natural(); + bus.map(reader, writer, addr, size, base, mask); +} diff --git a/higan/sfc/cartridge/markup.cpp b/higan/sfc/cartridge/markup.cpp deleted file mode 100644 index 05ea9a9c..00000000 --- a/higan/sfc/cartridge/markup.cpp +++ /dev/null @@ -1,385 +0,0 @@ -auto Cartridge::parseMarkup(const string& markup) -> void { - auto document = BML::unserialize(markup); - auto information = document["information"]; - auto board = document["board"]; - - this->information.title.cartridge = information["title"].text(); - _region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; - - if(auto node = board["rom"]) parseMarkupROM(node); - if(auto node = board["ram"]) parseMarkupRAM(node); - if(auto node = board["icd2"]) parseMarkupICD2(node); - if(auto node = board["mcc"]) parseMarkupMCC(node); - if(auto node = board["bsmemory"]) parseMarkupBSMemory(node); - if(auto node = board.find("sufamiturbo")) if(node(0)) parseMarkupSufamiTurbo(node(0), 0); - if(auto node = board.find("sufamiturbo")) if(node(1)) parseMarkupSufamiTurbo(node(1), 1); - if(auto node = board["nss"]) parseMarkupNSS(node); - if(auto node = board["event"]) parseMarkupEvent(node); - if(auto node = board["sa1"]) parseMarkupSA1(node); - if(auto node = board["superfx"]) parseMarkupSuperFX(node); - if(auto node = board["armdsp"]) parseMarkupARMDSP(node); - if(auto node = board["hitachidsp"]) parseMarkupHitachiDSP(node, document["information/board"].text().match("2DC*") ? 2 : 1); - if(auto node = board["necdsp"]) parseMarkupNECDSP(node); - if(auto node = board["epsonrtc"]) parseMarkupEpsonRTC(node); - if(auto node = board["sharprtc"]) parseMarkupSharpRTC(node); - if(auto node = board["spc7110"]) parseMarkupSPC7110(node); - if(auto node = board["sdd1"]) parseMarkupSDD1(node); - if(auto node = board["obc1"]) parseMarkupOBC1(node); - if(auto node = board["msu1"]) parseMarkupMSU1(node); -} - -auto Cartridge::parseMarkupMap(Markup::Node map, SuperFamicom::Memory& memory) -> void { - auto addr = map["address"].text(); - auto size = map["size"].natural(); - auto base = map["base"].natural(); - auto mask = map["mask"].natural(); - if(size == 0) size = memory.size(); - if(size == 0) return; - bus.map({&SuperFamicom::Memory::read, &memory}, {&SuperFamicom::Memory::write, &memory}, addr, size, base, mask); -} - -auto Cartridge::parseMarkupMap( - Markup::Node map, - const function& reader, - const function& writer -) -> void { - auto addr = map["address"].text(); - auto size = map["size"].natural(); - auto base = map["base"].natural(); - auto mask = map["mask"].natural(); - bus.map(reader, writer, addr, size, base, mask); -} - -auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, uint id, bool writable) -> void { - string name = node["name"].text(); - uint size = node["size"].natural(); - bool save = !(bool)node["volatile"]; - ram.map(allocate(size, 0xff), size); - if(name) { - interface->loadRequest(id, name, !writable); //treat ROM as required; RAM as optional - if(writable && save) memory.append({id, name}); - } -} - -auto Cartridge::parseMarkupROM(Markup::Node root) -> void { - parseMarkupMemory(rom, root, ID::ROM, false); - for(auto node : root.find("map")) { - parseMarkupMap(node, rom); - } -} - -auto Cartridge::parseMarkupRAM(Markup::Node root) -> void { - parseMarkupMemory(ram, root, ID::RAM, true); - for(auto node : root.find("map")) { - parseMarkupMap(node, ram); - } -} - -auto Cartridge::parseMarkupICD2(Markup::Node root) -> void { - hasGameBoySlot = true; - hasICD2 = true; - icd2.revision = max(1, root["revision"].natural()); - - //Game Boy core loads data through ICD2 interface - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2}); - } -} - -auto Cartridge::parseMarkupMCC(Markup::Node root) -> void { - hasBSMemorySlot = true; - hasMCC = true; - - interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false); - - parseMarkupMemory(mcc.rom, root["rom"], ID::MCCROM, false); - parseMarkupMemory(mcc.ram, root["ram"], ID::MCCRAM, true); - - for(auto node : root.find("map")) { - if(node.text() == "mcu") { - parseMarkupMap(node, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc}); - } else { - parseMarkupMap(node, {&MCC::read, &mcc}, {&MCC::write, &mcc}); - } - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, mcc.ram); - } -} - -auto Cartridge::parseMarkupBSMemory(Markup::Node root) -> void { - hasBSMemorySlot = true; - - interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false); - - for(auto node : root.find("map")) { - if(bsmemory.memory.size() == 0) continue; - parseMarkupMap(node, bsmemory); - } -} - -auto Cartridge::parseMarkupSufamiTurbo(Markup::Node root, bool slot) -> void { - hasSufamiTurboSlots = true; - - if(slot == 0) { - //load required slot A (will request slot B if slot A cartridge is linkable) - interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo", "st", false); - } - - for(auto node : root["rom"].find("map")) { - SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB); - if(cart.rom.size() == 0) continue; - parseMarkupMap(node, cart.rom); - } - - for(auto node : root["ram"].find("map")) { - SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB); - if(cart.ram.size() == 0) continue; - parseMarkupMap(node, cart.ram); - } -} - -auto Cartridge::parseMarkupNSS(Markup::Node root) -> void { - hasNSSDIP = true; - nss.dip = interface->dipSettings(root); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&NSS::read, &nss}, {&NSS::write, &nss}); - } -} - -auto Cartridge::parseMarkupEvent(Markup::Node root) -> void { - auto roms = root.find("rom"); - if(roms.size() != 4) return; - - hasEvent = true; - - for(uint n : range(4)) { - parseMarkupMemory(event.rom[n], roms[n], ID::EventROM0 + n, false); - } - parseMarkupMemory(event.ram, root["ram"], ID::EventRAM, true); - - event.board = Event::Board::CampusChallenge92; - if(root.text() == "CC92") event.board = Event::Board::CampusChallenge92; - if(root.text() == "PF94") event.board = Event::Board::Powerfest94; - event.timer = root["timer"].natural(); - - for(auto node : root.find("map")) { - if(node.text() == "mcu") { - parseMarkupMap(node, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}); - } else { - parseMarkupMap(node, {&Event::read, &event}, {&Event::write, &event}); - } - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, event.ram); - } -} - -auto Cartridge::parseMarkupSA1(Markup::Node root) -> void { - hasSA1 = true; - - parseMarkupMemory(sa1.rom, root["rom"], ID::SA1ROM, false); - parseMarkupMemory(sa1.bwram, root["bwram"], ID::SA1BWRAM, true); - parseMarkupMemory(sa1.iram, root["iram"], ID::SA1IRAM, true); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1}); - } - - for(auto node : root["rom"].find("map")) { - parseMarkupMap(node, {&SA1::mmcromRead, &sa1}, {&SA1::mmcromWrite, &sa1}); - } - - for(auto node : root["bwram"].find("map")) { - parseMarkupMap(node, {&SA1::mmcbwramRead, &sa1}, {&SA1::mmcbwramWrite, &sa1}); - } - - for(auto node : root["iram"].find("map")) { - parseMarkupMap(node, sa1.cpuiram); - } -} - -auto Cartridge::parseMarkupSuperFX(Markup::Node root) -> void { - hasSuperFX = true; - - parseMarkupMemory(superfx.rom, root["rom"], ID::SuperFXROM, false); - parseMarkupMemory(superfx.ram, root["ram"], ID::SuperFXRAM, true); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx}); - } - - for(auto node : root["rom"].find("map")) { - parseMarkupMap(node, superfx.cpurom); - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, superfx.cpuram); - } -} - -auto Cartridge::parseMarkupARMDSP(Markup::Node root) -> void { - hasARMDSP = true; - - interface->loadRequest(ID::ArmDSPPROM, root["prom"]["name"].text(), true); - interface->loadRequest(ID::ArmDSPDROM, root["drom"]["name"].text(), true); - interface->loadRequest(ID::ArmDSPRAM, root["dram"]["name"].text(), false); - memory.append({ID::ArmDSPRAM, root["dram"]["name"].text()}); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp}); - } -} - -auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, uint roms) -> void { - hasHitachiDSP = true; - - hitachidsp.Frequency = root["frequency"].natural(); - if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000; - hitachidsp.Roms = roms; //1 or 2 - - for(auto& word : hitachidsp.dataROM) word = 0x000000; - for(auto& word : hitachidsp.dataRAM) word = 0x00; - - interface->loadRequest(ID::HitachiDSPDROM, root["drom"]["name"].text(), true); - interface->loadRequest(ID::HitachiDSPDRAM, root["dram"]["name"].text(), false); - - parseMarkupMemory(hitachidsp.rom, root["rom"], ID::HitachiDSPROM, false); - parseMarkupMemory(hitachidsp.ram, root["ram"], ID::HitachiDSPRAM, true); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp}); - } - - for(auto node : root["rom"].find("map")) { - parseMarkupMap(node, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp}); - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, {&HitachiDSP::ramRead, &hitachidsp}, {&HitachiDSP::ramWrite, &hitachidsp}); - } - - for(auto node : root["dram"].find("map")) { - parseMarkupMap(node, {&HitachiDSP::dramRead, &hitachidsp}, {&HitachiDSP::dramWrite, &hitachidsp}); - } -} - -auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void { - hasNECDSP = true; - - necdsp.frequency = root["frequency"].natural(); - if(necdsp.frequency == 0) necdsp.frequency = 8000000; - necdsp.revision - = root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 - : root["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 - : NECDSP::Revision::uPD7725; - - for(auto& word : necdsp.programROM) word = 0x000000; - for(auto& word : necdsp.dataROM) word = 0x0000; - for(auto& word : necdsp.dataRAM) word = 0x0000; - - if(necdsp.revision == NECDSP::Revision::uPD7725) { - interface->loadRequest(ID::Nec7725DSPPROM, root["prom"]["name"].text(), true); - interface->loadRequest(ID::Nec7725DSPDROM, root["drom"]["name"].text(), true); - interface->loadRequest(ID::Nec7725DSPRAM, root["dram"]["name"].text(), false); - memory.append({ID::Nec7725DSPRAM, root["dram"]["name"].text()}); - } - - if(necdsp.revision == NECDSP::Revision::uPD96050) { - interface->loadRequest(ID::Nec96050DSPPROM, root["prom"]["name"].text(), true); - interface->loadRequest(ID::Nec96050DSPDROM, root["drom"]["name"].text(), true); - interface->loadRequest(ID::Nec96050DSPRAM, root["dram"]["name"].text(), false); - memory.append({ID::Nec96050DSPRAM, root["dram"]["name"].text()}); - } - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); - } - - for(auto node : root["dram"].find("map")) { - parseMarkupMap(node, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); - } -} - -auto Cartridge::parseMarkupEpsonRTC(Markup::Node root) -> void { - hasEpsonRTC = true; - - interface->loadRequest(ID::EpsonRTC, root["ram"]["name"].text(), false); - memory.append({ID::EpsonRTC, root["ram"]["name"].text()}); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc}); - } -} - -auto Cartridge::parseMarkupSharpRTC(Markup::Node root) -> void { - hasSharpRTC = true; - - interface->loadRequest(ID::SharpRTC, root["ram"]["name"].text(), false); - memory.append({ID::SharpRTC, root["ram"]["name"].text()}); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc}); - } -} - -auto Cartridge::parseMarkupSPC7110(Markup::Node root) -> void { - hasSPC7110 = true; - - parseMarkupMemory(spc7110.prom, root["prom"], ID::SPC7110PROM, false); - parseMarkupMemory(spc7110.drom, root["drom"], ID::SPC7110DROM, false); - parseMarkupMemory(spc7110.ram, root["ram"], ID::SPC7110RAM, true); - - for(auto node : root.find("map")) { - if(node.text() == "mcu") { - parseMarkupMap(node, {&SPC7110::mcuromRead, &spc7110}, {&SPC7110::mcuromWrite, &spc7110}); - } else { - parseMarkupMap(node, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110}); - } - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, {&SPC7110::mcuramRead, &spc7110}, {&SPC7110::mcuramWrite, &spc7110}); - } -} - -auto Cartridge::parseMarkupSDD1(Markup::Node root) -> void { - hasSDD1 = true; - - parseMarkupMemory(sdd1.rom, root["rom"], ID::SDD1ROM, false); - parseMarkupMemory(sdd1.ram, root["ram"], ID::SDD1RAM, true); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}); - } - - for(auto node : root["rom"].find("map")) { - parseMarkupMap(node, {&SDD1::mcuromRead, &sdd1}, {&SDD1::mcuromWrite, &sdd1}); - } - - for(auto node : root["ram"].find("map")) { - parseMarkupMap(node, {&SDD1::mcuramRead, &sdd1}, {&SDD1::mcuramWrite, &sdd1}); - } -} - -auto Cartridge::parseMarkupOBC1(Markup::Node root) -> void { - hasOBC1 = true; - - parseMarkupMemory(obc1.ram, root["ram"], ID::OBC1RAM, true); - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&OBC1::read, &obc1}, {&OBC1::write, &obc1}); - } -} - -auto Cartridge::parseMarkupMSU1(Markup::Node root) -> void { - hasMSU1 = true; - - for(auto node : root.find("map")) { - parseMarkupMap(node, {&MSU1::read, &msu1}, {&MSU1::write, &msu1}); - } -} diff --git a/higan/sfc/cartridge/save.cpp b/higan/sfc/cartridge/save.cpp new file mode 100644 index 00000000..a61d7ff6 --- /dev/null +++ b/higan/sfc/cartridge/save.cpp @@ -0,0 +1,123 @@ +auto Cartridge::saveCartridge(Markup::Node node) -> void { + auto board = node["board"]; + + if(auto node = board["ram"]) saveRAM(node); + if(auto node = board["mcc"]) saveMCC(node); + if(auto node = board["event"]) saveEvent(node); + if(auto node = board["sa1"]) saveSA1(node); + if(auto node = board["superfx"]) saveSuperFX(node); + if(auto node = board["armdsp"]) saveARMDSP(node); + if(auto node = board["hitachidsp"]) saveHitachiDSP(node); + if(auto node = board["necdsp"]) saveNECDSP(node); + if(auto node = board["epsonrtc"]) saveEpsonRTC(node); + if(auto node = board["sharprtc"]) saveSharpRTC(node); + if(auto node = board["spc7110"]) saveSPC7110(node); + if(auto node = board["sdd1"]) saveSDD1(node); + if(auto node = board["obc1"]) saveOBC1(node); +} + +auto Cartridge::saveGameBoy(Markup::Node node) -> void { +} + +auto Cartridge::saveBSMemory(Markup::Node node) -> void { +} + +auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void { + saveMemory(sufamiturboA.ram, node["board/ram"], ID::SufamiTurboA); +} + +auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void { + saveMemory(sufamiturboB.ram, node["board/ram"], ID::SufamiTurboB); +} + +// + +auto Cartridge::saveRAM(Markup::Node node) -> void { + saveMemory(ram, node); +} + +auto Cartridge::saveMCC(Markup::Node node) -> void { + saveMemory(mcc.ram, node["ram"]); +} + +auto Cartridge::saveEvent(Markup::Node node) -> void { + saveMemory(event.ram, node["ram"]); +} + +auto Cartridge::saveSA1(Markup::Node node) -> void { + saveMemory(sa1.bwram, node["bwram"]); + saveMemory(sa1.iram, node["iram"]); +} + +auto Cartridge::saveSuperFX(Markup::Node node) -> void { + saveMemory(superfx.ram, node["ram"]); +} + +auto Cartridge::saveARMDSP(Markup::Node node) -> void { + if(auto name = node["ram"]["name"].text()) { + if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) { + for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]); + } + } +} + +auto Cartridge::saveHitachiDSP(Markup::Node node) -> void { + saveMemory(hitachidsp.ram, node["ram"]); + if(auto name = node["dram"]["name"].text()) { + if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) { + for(auto n : range(3 * 1024)) fp->write(hitachidsp.dataRAM[n]); + } + } +} + +auto Cartridge::saveNECDSP(Markup::Node node) -> void { + uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048; + if(auto name = node["dram"]["name"].text()) { + if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) { + for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2); + } + } +} + +auto Cartridge::saveEpsonRTC(Markup::Node node) -> void { + if(auto name = node["ram"]["name"].text()) { + if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) { + uint8 data[16] = {0}; + epsonrtc.save(data); + fp->write(data, 16); + } + } +} + +auto Cartridge::saveSharpRTC(Markup::Node node) -> void { + if(auto name = node["ram"]["name"].text()) { + if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) { + uint8 data[16] = {0}; + sharprtc.save(data); + fp->write(data, 16); + } + } +} + +auto Cartridge::saveSPC7110(Markup::Node node) -> void { + saveMemory(spc7110.ram, node["ram"]); +} + +auto Cartridge::saveSDD1(Markup::Node node) -> void { + saveMemory(sdd1.ram, node["ram"]); +} + +auto Cartridge::saveOBC1(Markup::Node node) -> void { + saveMemory(obc1.ram, node["ram"]); +} + +// + +auto Cartridge::saveMemory(MappedRAM& memory, Markup::Node node, uint id) -> void { + if(!node || node["volatile"]) return; + auto name = node["name"].text(); + auto size = node["size"].natural(); + if(auto fp = interface->open(id, name, File::Write)) { + fp->write(memory.data(), memory.size()); + } +} diff --git a/higan/sfc/coprocessor/armdsp/serialization.cpp b/higan/sfc/coprocessor/armdsp/serialization.cpp index 2b42bef6..fbfba453 100644 --- a/higan/sfc/coprocessor/armdsp/serialization.cpp +++ b/higan/sfc/coprocessor/armdsp/serialization.cpp @@ -1,6 +1,6 @@ auto ArmDSP::firmware() const -> nall::vector { nall::vector buffer; - if(!cartridge.hasARMDSP) return buffer; + if(!cartridge.has.ARMDSP) return buffer; buffer.reserve(128 * 1024 + 32 * 1024); for(auto n : range(128 * 1024)) buffer.append(programROM[n]); for(auto n : range( 32 * 1024)) buffer.append(dataROM[n]); diff --git a/higan/sfc/coprocessor/hitachidsp/serialization.cpp b/higan/sfc/coprocessor/hitachidsp/serialization.cpp index ed0a785b..6ac657ba 100644 --- a/higan/sfc/coprocessor/hitachidsp/serialization.cpp +++ b/higan/sfc/coprocessor/hitachidsp/serialization.cpp @@ -1,6 +1,6 @@ auto HitachiDSP::firmware() const -> vector { vector buffer; - if(!cartridge.hasHitachiDSP) return buffer; + if(!cartridge.has.HitachiDSP) return buffer; buffer.reserve(1024 * 3); for(auto n : range(1024)) { buffer.append(dataROM[n] >> 0); diff --git a/higan/sfc/coprocessor/msu1/msu1.cpp b/higan/sfc/coprocessor/msu1/msu1.cpp index 6d8b4622..7c5b58d6 100644 --- a/higan/sfc/coprocessor/msu1/msu1.cpp +++ b/higan/sfc/coprocessor/msu1/msu1.cpp @@ -85,7 +85,7 @@ auto MSU1::reset() -> void { auto MSU1::dataOpen() -> void { if(dataFile.open()) dataFile.close(); - auto document = BML::unserialize(cartridge.information.markup.cartridge); + auto document = BML::unserialize(cartridge.information.manifest.cartridge); string name = document["board/msu1/rom/name"].text(); if(!name) name = "msu1.rom"; if(dataFile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) { @@ -95,7 +95,7 @@ auto MSU1::dataOpen() -> void { auto MSU1::audioOpen() -> void { if(audioFile.open()) audioFile.close(); - auto document = BML::unserialize(cartridge.information.markup.cartridge); + auto document = BML::unserialize(cartridge.information.manifest.cartridge); string name = {"track-", mmio.audioTrack, ".pcm"}; for(auto track : document.find("board/msu1/track")) { if(track["number"].natural() != mmio.audioTrack) continue; diff --git a/higan/sfc/coprocessor/necdsp/serialization.cpp b/higan/sfc/coprocessor/necdsp/serialization.cpp index 7b291474..87084713 100644 --- a/higan/sfc/coprocessor/necdsp/serialization.cpp +++ b/higan/sfc/coprocessor/necdsp/serialization.cpp @@ -1,6 +1,6 @@ auto NECDSP::firmware() const -> vector { vector buffer; - if(!cartridge.hasNECDSP) return buffer; + if(!cartridge.has.NECDSP) return buffer; uint plength = 2048, dlength = 1024; if(revision == Revision::uPD96050) plength = 16384, dlength = 2048; buffer.reserve(plength * 3 + dlength * 2); diff --git a/higan/sfc/interface/interface.cpp b/higan/sfc/interface/interface.cpp index 69a2aa33..68339d7b 100644 --- a/higan/sfc/interface/interface.cpp +++ b/higan/sfc/interface/interface.cpp @@ -183,175 +183,33 @@ auto Interface::sha256() -> string { return cartridge.sha256(); } +//deprecated auto Interface::group(uint id) -> uint { switch(id) { - case ID::SystemManifest: - case ID::IPLROM: - return 0; - case ID::Manifest: - case ID::ROM: - case ID::RAM: - case ID::EventROM0: - case ID::EventROM1: - case ID::EventROM2: - case ID::EventROM3: - case ID::EventRAM: - case ID::SA1ROM: - case ID::SA1IRAM: - case ID::SA1BWRAM: - case ID::SuperFXROM: - case ID::SuperFXRAM: - case ID::ArmDSPPROM: - case ID::ArmDSPDROM: - case ID::ArmDSPRAM: - case ID::HitachiDSPROM: - case ID::HitachiDSPRAM: - case ID::HitachiDSPDROM: - case ID::HitachiDSPDRAM: - case ID::Nec7725DSPPROM: - case ID::Nec7725DSPDROM: - case ID::Nec7725DSPRAM: - case ID::Nec96050DSPPROM: - case ID::Nec96050DSPDROM: - case ID::Nec96050DSPRAM: - case ID::EpsonRTC: - case ID::SharpRTC: - case ID::SPC7110PROM: - case ID::SPC7110DROM: - case ID::SPC7110RAM: - case ID::SDD1ROM: - case ID::SDD1RAM: - case ID::OBC1RAM: case ID::SuperGameBoyManifest: case ID::SuperGameBoyBootROM: - case ID::MCCROM: - case ID::MCCRAM: return 1; - case ID::GameBoy: case ID::GameBoyManifest: case ID::GameBoyROM: case ID::GameBoyRAM: return 2; - case ID::BSMemory: - case ID::BSMemoryManifest: - case ID::BSMemoryROM: - return 3; - case ID::SufamiTurboSlotA: - case ID::SufamiTurboSlotAManifest: - case ID::SufamiTurboSlotAROM: - case ID::SufamiTurboSlotARAM: - return 4; - case ID::SufamiTurboSlotB: - case ID::SufamiTurboSlotBManifest: - case ID::SufamiTurboSlotBROM: - case ID::SufamiTurboSlotBRAM: - return 5; } - throw; } auto Interface::load(uint id) -> void { if(id == ID::SuperFamicom) system.load(); if(id == ID::BSMemory) cartridge.loadBSMemory(); - if(id == ID::SufamiTurboSlotA) cartridge.loadSufamiTurboA(); - if(id == ID::SufamiTurboSlotB) cartridge.loadSufamiTurboB(); + if(id == ID::SufamiTurboA) cartridge.loadSufamiTurboA(); + if(id == ID::SufamiTurboB) cartridge.loadSufamiTurboB(); } auto Interface::save() -> void { - for(auto& memory : cartridge.memory) { - saveRequest(memory.id, memory.name); - } + system.save(); } +//deprecated auto Interface::load(uint id, const stream& stream) -> void { - if(id == ID::SystemManifest) { - system.information.manifest = stream.text(); - } - - if(id == ID::IPLROM) { - stream.read((uint8_t*)smp.iplrom, min(64u, stream.size())); - } - - if(id == ID::Manifest) cartridge.information.markup.cartridge = stream.text(); - if(id == ID::ROM) cartridge.rom.read(stream); - if(id == ID::RAM) cartridge.ram.read(stream); - - if(id == ID::EventROM0) event.rom[0].read(stream); - if(id == ID::EventROM1) event.rom[1].read(stream); - if(id == ID::EventROM2) event.rom[2].read(stream); - if(id == ID::EventROM3) event.rom[3].read(stream); - if(id == ID::EventRAM) event.ram.read(stream); - - if(id == ID::SA1ROM) sa1.rom.read(stream); - if(id == ID::SA1IRAM) sa1.iram.read(stream); - if(id == ID::SA1BWRAM) sa1.bwram.read(stream); - - if(id == ID::SuperFXROM) superfx.rom.read(stream); - if(id == ID::SuperFXRAM) superfx.ram.read(stream); - - if(id == ID::ArmDSPPROM) { - for(auto n : range(128 * 1024)) armdsp.programROM[n] = stream.read(); - } - if(id == ID::ArmDSPDROM) { - for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = stream.read(); - } - if(id == ID::ArmDSPRAM) { - for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = stream.read(); - } - - if(id == ID::HitachiDSPROM) hitachidsp.rom.read(stream); - if(id == ID::HitachiDSPRAM) hitachidsp.ram.read(stream); - if(id == ID::HitachiDSPDROM) { - for(auto n : range(1024)) hitachidsp.dataROM[n] = stream.readl(3); - } - if(id == ID::HitachiDSPDRAM) { - for(auto n : range(3072)) hitachidsp.dataRAM[n] = stream.readl(1); - } - - if(id == ID::Nec7725DSPPROM) { - for(auto n : range( 2048)) necdsp.programROM[n] = stream.readl(3); - } - if(id == ID::Nec7725DSPDROM) { - for(auto n : range( 1024)) necdsp.dataROM[n] = stream.readl(2); - } - if(id == ID::Nec7725DSPRAM) { - for(auto n : range( 256)) necdsp.dataRAM[n] = stream.readl(2); - } - if(id == ID::Nec96050DSPPROM) { - for(auto n : range(16384)) necdsp.programROM[n] = stream.readl(3); - } - if(id == ID::Nec96050DSPDROM) { - for(auto n : range( 2048)) necdsp.dataROM[n] = stream.readl(2); - } - if(id == ID::Nec96050DSPRAM) { - for(auto n : range( 2048)) necdsp.dataRAM[n] = stream.readl(2); - } - - if(id == ID::EpsonRTC) { - uint8 data[16] = {0}; - stream.read((uint8_t*)data, min(stream.size(), sizeof data)); - epsonrtc.load(data); - } - - if(id == ID::SharpRTC) { - uint8 data[16] = {0}; - stream.read((uint8_t*)data, min(stream.size(), sizeof data)); - sharprtc.load(data); - } - - if(id == ID::SPC7110PROM) spc7110.prom.read(stream); - if(id == ID::SPC7110DROM) spc7110.drom.read(stream); - if(id == ID::SPC7110RAM) spc7110.ram.read(stream); - - if(id == ID::SDD1ROM) sdd1.rom.read(stream); - if(id == ID::SDD1RAM) sdd1.ram.read(stream); - - if(id == ID::OBC1RAM) obc1.ram.read(stream); - - if(id == ID::MCCROM) mcc.rom.read(stream); - if(id == ID::MCCRAM) mcc.ram.read(stream); - #if defined(SFC_SUPERGAMEBOY) if(id == ID::SuperGameBoyManifest) { GameBoy::interface->load(GameBoy::ID::SystemManifest, stream); @@ -373,68 +231,15 @@ auto Interface::load(uint id, const stream& stream) -> void { GameBoy::interface->load(GameBoy::ID::RAM, stream); } #endif - - if(id == ID::BSMemoryManifest) cartridge.information.markup.bsMemory = stream.text(); - if(id == ID::BSMemoryROM) bsmemory.memory.read(stream); - - if(id == ID::SufamiTurboSlotAManifest) cartridge.information.markup.sufamiTurboA = stream.text(); - if(id == ID::SufamiTurboSlotAROM) sufamiturboA.rom.read(stream); - if(id == ID::SufamiTurboSlotBROM) sufamiturboB.rom.read(stream); - - if(id == ID::SufamiTurboSlotBManifest) cartridge.information.markup.sufamiTurboB = stream.text(); - if(id == ID::SufamiTurboSlotARAM) sufamiturboA.ram.read(stream); - if(id == ID::SufamiTurboSlotBRAM) sufamiturboB.ram.read(stream); } +//deprecated auto Interface::save(uint id, const stream& stream) -> void { - if(id == ID::RAM) stream.write((uint8_t*)cartridge.ram.data(), cartridge.ram.size()); - if(id == ID::EventRAM) stream.write((uint8_t*)event.ram.data(), event.ram.size()); - if(id == ID::SA1IRAM) stream.write((uint8_t*)sa1.iram.data(), sa1.iram.size()); - if(id == ID::SA1BWRAM) stream.write((uint8_t*)sa1.bwram.data(), sa1.bwram.size()); - if(id == ID::SuperFXRAM) stream.write((uint8_t*)superfx.ram.data(), superfx.ram.size()); - - if(id == ID::ArmDSPRAM) { - for(auto n : range(16 * 1024)) stream.write(armdsp.programRAM[n]); - } - - if(id == ID::HitachiDSPRAM) stream.write((uint8_t*)hitachidsp.ram.data(), hitachidsp.ram.size()); - if(id == ID::HitachiDSPDRAM) { - for(auto n : range(3072)) stream.writel(hitachidsp.dataRAM[n], 1); - } - - if(id == ID::Nec7725DSPRAM) { - for(auto n : range( 256)) stream.writel(necdsp.dataRAM[n], 2); - } - if(id == ID::Nec96050DSPRAM) { - for(auto n : range(2048)) stream.writel(necdsp.dataRAM[n], 2); - } - - if(id == ID::EpsonRTC) { - uint8 data[16] = {0}; - epsonrtc.save(data); - stream.write((uint8_t*)data, sizeof data); - } - - if(id == ID::SharpRTC) { - uint8 data[16] = {0}; - sharprtc.save(data); - stream.write((uint8_t*)data, sizeof data); - } - - if(id == ID::SPC7110RAM) stream.write((uint8_t*)spc7110.ram.data(), spc7110.ram.size()); - if(id == ID::SDD1RAM) stream.write((uint8_t*)sdd1.ram.data(), sdd1.ram.size()); - if(id == ID::OBC1RAM) stream.write((uint8_t*)obc1.ram.data(), obc1.ram.size()); - #if defined(SFC_SUPERGAMEBOY) if(id == ID::GameBoyRAM) { GameBoy::interface->save(GameBoy::ID::RAM, stream); } #endif - - if(id == ID::MCCRAM) stream.write((uint8_t*)mcc.ram.data(), mcc.ram.size()); - - if(id == ID::SufamiTurboSlotARAM) stream.write((uint8_t*)sufamiturboA.ram.data(), sufamiturboA.ram.size()); - if(id == ID::SufamiTurboSlotBRAM) stream.write((uint8_t*)sufamiturboB.ram.data(), sufamiturboB.ram.size()); } auto Interface::unload() -> void { @@ -459,14 +264,14 @@ auto Interface::run() -> void { } auto Interface::rtc() -> bool { - if(cartridge.hasEpsonRTC) return true; - if(cartridge.hasSharpRTC) return true; + if(cartridge.has.EpsonRTC) return true; + if(cartridge.has.SharpRTC) return true; return false; } auto Interface::rtcsync() -> void { - if(cartridge.hasEpsonRTC) epsonrtc.sync(); - if(cartridge.hasSharpRTC) sharprtc.sync(); + if(cartridge.has.EpsonRTC) epsonrtc.sync(); + if(cartridge.has.SharpRTC) sharprtc.sync(); } auto Interface::serialize() -> serializer { @@ -482,7 +287,7 @@ auto Interface::cheatSet(const lstring& list) -> void { cheat.reset(); #if defined(SFC_SUPERGAMEBOY) - if(cartridge.hasICD2) { + if(cartridge.has.ICD2) { GameBoy::cheat.reset(); for(auto& codeset : list) { lstring codes = codeset.split("+"); diff --git a/higan/sfc/interface/interface.hpp b/higan/sfc/interface/interface.hpp index 62a08990..6f06303e 100644 --- a/higan/sfc/interface/interface.hpp +++ b/higan/sfc/interface/interface.hpp @@ -2,85 +2,23 @@ namespace SuperFamicom { struct ID { enum : uint { - //cartridges (folders) System, SuperFamicom, GameBoy, BSMemory, - SufamiTurboSlotA, - SufamiTurboSlotB, - - //memory (files) - SystemManifest, - IPLROM, - - Manifest, - ROM, - RAM, - - EventROM0, - EventROM1, - EventROM2, - EventROM3, - EventRAM, - - SA1ROM, - SA1IRAM, - SA1BWRAM, - - SuperFXROM, - SuperFXRAM, - - ArmDSPPROM, - ArmDSPDROM, - ArmDSPRAM, - - HitachiDSPROM, - HitachiDSPRAM, - HitachiDSPDROM, - HitachiDSPDRAM, - - Nec7725DSPPROM, - Nec7725DSPDROM, - Nec7725DSPRAM, - - Nec96050DSPPROM, - Nec96050DSPDROM, - Nec96050DSPRAM, - - EpsonRTC, - SharpRTC, - - SPC7110PROM, - SPC7110DROM, - SPC7110RAM, - - SDD1ROM, - SDD1RAM, - - OBC1RAM, - - MCCROM, - MCCRAM, + SufamiTurboA, + SufamiTurboB, + //deprecated SuperGameBoyManifest, SuperGameBoyBootROM, GameBoyManifest, GameBoyROM, GameBoyRAM, + }; - BSMemoryManifest, - BSMemoryROM, - - SufamiTurboSlotAManifest, - SufamiTurboSlotAROM, - SufamiTurboSlotARAM, - - SufamiTurboSlotBManifest, - SufamiTurboSlotBROM, - SufamiTurboSlotBRAM, - + enum : uint { //device ports (bitmask) ControllerPort1 = 1, ControllerPort2 = 2, diff --git a/higan/sfc/memory/memory-inline.hpp b/higan/sfc/memory/memory-inline.hpp index 9a4b16d9..25e41c46 100644 --- a/higan/sfc/memory/memory-inline.hpp +++ b/higan/sfc/memory/memory-inline.hpp @@ -24,6 +24,12 @@ auto MappedRAM::reset() -> void { _writeProtect = false; } +auto MappedRAM::allocate(uint size) -> void { + reset(); + _data = new uint8[_size = size]; + memory::fill(_data, _size, 0xff); +} + auto MappedRAM::map(uint8* source, uint length) -> void { reset(); _data = source; diff --git a/higan/sfc/memory/memory.hpp b/higan/sfc/memory/memory.hpp index aa623009..bdd37b34 100644 --- a/higan/sfc/memory/memory.hpp +++ b/higan/sfc/memory/memory.hpp @@ -23,6 +23,7 @@ private: struct MappedRAM : Memory { inline auto reset() -> void; + inline auto allocate(uint) -> void; inline auto map(uint8*, uint) -> void; inline auto copy(const stream& memory) -> void; inline auto read(const stream& memory) -> void; diff --git a/higan/sfc/sfc.hpp b/higan/sfc/sfc.hpp index 0afc409b..0e0489a0 100644 --- a/higan/sfc/sfc.hpp +++ b/higan/sfc/sfc.hpp @@ -24,6 +24,12 @@ namespace SuperFamicom { #endif namespace SuperFamicom { + struct File { + static const vfs::file::mode Read = vfs::file::mode::read; + static const vfs::file::mode Write = vfs::file::mode::write; + static const bool Required = true; + }; + struct Thread { virtual ~Thread() { if(thread) co_delete(thread); diff --git a/higan/sfc/system/serialization.cpp b/higan/sfc/system/serialization.cpp index b33a0c7e..22239e49 100644 --- a/higan/sfc/system/serialization.cpp +++ b/higan/sfc/system/serialization.cpp @@ -50,22 +50,22 @@ auto System::serializeAll(serializer& s) -> void { ppu.serialize(s); dsp.serialize(s); - if(cartridge.hasICD2) icd2.serialize(s); - if(cartridge.hasMCC) mcc.serialize(s); - if(cartridge.hasEvent) event.serialize(s); - if(cartridge.hasSA1) sa1.serialize(s); - if(cartridge.hasSuperFX) superfx.serialize(s); - if(cartridge.hasARMDSP) armdsp.serialize(s); - if(cartridge.hasHitachiDSP) hitachidsp.serialize(s); - if(cartridge.hasNECDSP) necdsp.serialize(s); - if(cartridge.hasEpsonRTC) epsonrtc.serialize(s); - if(cartridge.hasSharpRTC) sharprtc.serialize(s); - if(cartridge.hasSPC7110) spc7110.serialize(s); - if(cartridge.hasSDD1) sdd1.serialize(s); - if(cartridge.hasOBC1) obc1.serialize(s); - if(cartridge.hasMSU1) msu1.serialize(s); + if(cartridge.has.ICD2) icd2.serialize(s); + if(cartridge.has.MCC) mcc.serialize(s); + if(cartridge.has.Event) event.serialize(s); + if(cartridge.has.SA1) sa1.serialize(s); + if(cartridge.has.SuperFX) superfx.serialize(s); + if(cartridge.has.ARMDSP) armdsp.serialize(s); + if(cartridge.has.HitachiDSP) hitachidsp.serialize(s); + if(cartridge.has.NECDSP) necdsp.serialize(s); + if(cartridge.has.EpsonRTC) epsonrtc.serialize(s); + if(cartridge.has.SharpRTC) sharprtc.serialize(s); + if(cartridge.has.SPC7110) spc7110.serialize(s); + if(cartridge.has.SDD1) sdd1.serialize(s); + if(cartridge.has.OBC1) obc1.serialize(s); + if(cartridge.has.MSU1) msu1.serialize(s); - if(cartridge.hasSufamiTurboSlots) sufamiturboA.serialize(s), sufamiturboB.serialize(s); + if(cartridge.has.SufamiTurboSlots) sufamiturboA.serialize(s), sufamiturboB.serialize(s); } //perform dry-run state save: diff --git a/higan/sfc/system/system.cpp b/higan/sfc/system/system.cpp index fdc155ba..476ff7c1 100644 --- a/higan/sfc/system/system.cpp +++ b/higan/sfc/system/system.cpp @@ -51,14 +51,19 @@ auto System::init() -> void { auto System::term() -> void { } -auto System::load() -> void { +auto System::load() -> bool { bus.reset(); - interface->loadRequest(ID::SystemManifest, "manifest.bml", true); + if(auto fp = interface->open(ID::System, "manifest.bml", File::Read, File::Required)) { + information.manifest = fp->reads(); + } else return false; + auto document = BML::unserialize(information.manifest); if(auto iplrom = document["system/smp/rom/name"].text()) { - interface->loadRequest(ID::IPLROM, iplrom, true); + if(auto fp = interface->open(ID::System, iplrom, File::Read, File::Required)) { + fp->read(smp.iplrom, 64); + } else return false; } cartridge.load(); @@ -66,51 +71,56 @@ auto System::load() -> void { _cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370; _apuFrequency = 24'606'720; - if(cartridge.hasICD2) icd2.load(); - if(cartridge.hasMCC) mcc.load(); - if(cartridge.hasNSSDIP) nss.load(); - if(cartridge.hasEvent) event.load(); - if(cartridge.hasSA1) sa1.load(); - if(cartridge.hasSuperFX) superfx.load(); - if(cartridge.hasARMDSP) armdsp.load(); - if(cartridge.hasHitachiDSP) hitachidsp.load(); - if(cartridge.hasNECDSP) necdsp.load(); - if(cartridge.hasEpsonRTC) epsonrtc.load(); - if(cartridge.hasSharpRTC) sharprtc.load(); - if(cartridge.hasSPC7110) spc7110.load(); - if(cartridge.hasSDD1) sdd1.load(); - if(cartridge.hasOBC1) obc1.load(); - if(cartridge.hasMSU1) msu1.load(); + if(cartridge.has.ICD2) icd2.load(); + if(cartridge.has.MCC) mcc.load(); + if(cartridge.has.NSSDIP) nss.load(); + if(cartridge.has.Event) event.load(); + if(cartridge.has.SA1) sa1.load(); + if(cartridge.has.SuperFX) superfx.load(); + if(cartridge.has.ARMDSP) armdsp.load(); + if(cartridge.has.HitachiDSP) hitachidsp.load(); + if(cartridge.has.NECDSP) necdsp.load(); + if(cartridge.has.EpsonRTC) epsonrtc.load(); + if(cartridge.has.SharpRTC) sharprtc.load(); + if(cartridge.has.SPC7110) spc7110.load(); + if(cartridge.has.SDD1) sdd1.load(); + if(cartridge.has.OBC1) obc1.load(); + if(cartridge.has.MSU1) msu1.load(); - if(cartridge.hasBSMemorySlot) bsmemory.load(); - if(cartridge.hasSufamiTurboSlots) sufamiturboA.load(), sufamiturboB.load(); + if(cartridge.has.BSMemorySlot) bsmemory.load(); + if(cartridge.has.SufamiTurboSlots) sufamiturboA.load(), sufamiturboB.load(); serializeInit(); - _loaded = true; + return _loaded = true; +} + +auto System::save() -> void { + if(!loaded()) return; + cartridge.save(); } auto System::unload() -> void { if(!loaded()) return; peripherals.unload(); - if(cartridge.hasICD2) icd2.unload(); - if(cartridge.hasMCC) mcc.unload(); - if(cartridge.hasNSSDIP) nss.unload(); - if(cartridge.hasEvent) event.unload(); - if(cartridge.hasSA1) sa1.unload(); - if(cartridge.hasSuperFX) superfx.unload(); - if(cartridge.hasARMDSP) armdsp.unload(); - if(cartridge.hasHitachiDSP) hitachidsp.unload(); - if(cartridge.hasNECDSP) necdsp.unload(); - if(cartridge.hasEpsonRTC) epsonrtc.unload(); - if(cartridge.hasSharpRTC) sharprtc.unload(); - if(cartridge.hasSPC7110) spc7110.unload(); - if(cartridge.hasSDD1) sdd1.unload(); - if(cartridge.hasOBC1) obc1.unload(); - if(cartridge.hasMSU1) msu1.unload(); + if(cartridge.has.ICD2) icd2.unload(); + if(cartridge.has.MCC) mcc.unload(); + if(cartridge.has.NSSDIP) nss.unload(); + if(cartridge.has.Event) event.unload(); + if(cartridge.has.SA1) sa1.unload(); + if(cartridge.has.SuperFX) superfx.unload(); + if(cartridge.has.ARMDSP) armdsp.unload(); + if(cartridge.has.HitachiDSP) hitachidsp.unload(); + if(cartridge.has.NECDSP) necdsp.unload(); + if(cartridge.has.EpsonRTC) epsonrtc.unload(); + if(cartridge.has.SharpRTC) sharprtc.unload(); + if(cartridge.has.SPC7110) spc7110.unload(); + if(cartridge.has.SDD1) sdd1.unload(); + if(cartridge.has.OBC1) obc1.unload(); + if(cartridge.has.MSU1) msu1.unload(); - if(cartridge.hasBSMemorySlot) bsmemory.unload(); - if(cartridge.hasSufamiTurboSlots) sufamiturboA.unload(), sufamiturboB.unload(); + if(cartridge.has.BSMemorySlot) bsmemory.unload(); + if(cartridge.has.SufamiTurboSlots) sufamiturboA.unload(), sufamiturboB.unload(); cartridge.unload(); _loaded = false; @@ -124,23 +134,23 @@ auto System::power() -> void { dsp.power(); ppu.power(); - if(cartridge.hasICD2) icd2.power(); - if(cartridge.hasMCC) mcc.power(); - if(cartridge.hasNSSDIP) nss.power(); - if(cartridge.hasEvent) event.power(); - if(cartridge.hasSA1) sa1.power(); - if(cartridge.hasSuperFX) superfx.power(); - if(cartridge.hasARMDSP) armdsp.power(); - if(cartridge.hasHitachiDSP) hitachidsp.power(); - if(cartridge.hasNECDSP) necdsp.power(); - if(cartridge.hasEpsonRTC) epsonrtc.power(); - if(cartridge.hasSharpRTC) sharprtc.power(); - if(cartridge.hasSPC7110) spc7110.power(); - if(cartridge.hasSDD1) sdd1.power(); - if(cartridge.hasOBC1) obc1.power(); - if(cartridge.hasMSU1) msu1.power(); + if(cartridge.has.ICD2) icd2.power(); + if(cartridge.has.MCC) mcc.power(); + if(cartridge.has.NSSDIP) nss.power(); + if(cartridge.has.Event) event.power(); + if(cartridge.has.SA1) sa1.power(); + if(cartridge.has.SuperFX) superfx.power(); + if(cartridge.has.ARMDSP) armdsp.power(); + if(cartridge.has.HitachiDSP) hitachidsp.power(); + if(cartridge.has.NECDSP) necdsp.power(); + if(cartridge.has.EpsonRTC) epsonrtc.power(); + if(cartridge.has.SharpRTC) sharprtc.power(); + if(cartridge.has.SPC7110) spc7110.power(); + if(cartridge.has.SDD1) sdd1.power(); + if(cartridge.has.OBC1) obc1.power(); + if(cartridge.has.MSU1) msu1.power(); - if(cartridge.hasBSMemorySlot) bsmemory.power(); + if(cartridge.has.BSMemorySlot) bsmemory.power(); reset(); } @@ -159,35 +169,35 @@ auto System::reset() -> void { dsp.reset(); ppu.reset(); - if(cartridge.hasICD2) icd2.reset(); - if(cartridge.hasMCC) mcc.reset(); - if(cartridge.hasNSSDIP) nss.reset(); - if(cartridge.hasEvent) event.reset(); - if(cartridge.hasSA1) sa1.reset(); - if(cartridge.hasSuperFX) superfx.reset(); - if(cartridge.hasARMDSP) armdsp.reset(); - if(cartridge.hasHitachiDSP) hitachidsp.reset(); - if(cartridge.hasNECDSP) necdsp.reset(); - if(cartridge.hasEpsonRTC) epsonrtc.reset(); - if(cartridge.hasSharpRTC) sharprtc.reset(); - if(cartridge.hasSPC7110) spc7110.reset(); - if(cartridge.hasSDD1) sdd1.reset(); - if(cartridge.hasOBC1) obc1.reset(); - if(cartridge.hasMSU1) msu1.reset(); + if(cartridge.has.ICD2) icd2.reset(); + if(cartridge.has.MCC) mcc.reset(); + if(cartridge.has.NSSDIP) nss.reset(); + if(cartridge.has.Event) event.reset(); + if(cartridge.has.SA1) sa1.reset(); + if(cartridge.has.SuperFX) superfx.reset(); + if(cartridge.has.ARMDSP) armdsp.reset(); + if(cartridge.has.HitachiDSP) hitachidsp.reset(); + if(cartridge.has.NECDSP) necdsp.reset(); + if(cartridge.has.EpsonRTC) epsonrtc.reset(); + if(cartridge.has.SharpRTC) sharprtc.reset(); + if(cartridge.has.SPC7110) spc7110.reset(); + if(cartridge.has.SDD1) sdd1.reset(); + if(cartridge.has.OBC1) obc1.reset(); + if(cartridge.has.MSU1) msu1.reset(); - if(cartridge.hasBSMemorySlot) bsmemory.reset(); + if(cartridge.has.BSMemorySlot) bsmemory.reset(); - if(cartridge.hasICD2) cpu.coprocessors.append(&icd2); - if(cartridge.hasEvent) cpu.coprocessors.append(&event); - if(cartridge.hasSA1) cpu.coprocessors.append(&sa1); - if(cartridge.hasSuperFX) cpu.coprocessors.append(&superfx); - if(cartridge.hasARMDSP) cpu.coprocessors.append(&armdsp); - if(cartridge.hasHitachiDSP) cpu.coprocessors.append(&hitachidsp); - if(cartridge.hasNECDSP) cpu.coprocessors.append(&necdsp); - if(cartridge.hasEpsonRTC) cpu.coprocessors.append(&epsonrtc); - if(cartridge.hasSharpRTC) cpu.coprocessors.append(&sharprtc); - if(cartridge.hasSPC7110) cpu.coprocessors.append(&spc7110); - if(cartridge.hasMSU1) cpu.coprocessors.append(&msu1); + if(cartridge.has.ICD2) cpu.coprocessors.append(&icd2); + if(cartridge.has.Event) cpu.coprocessors.append(&event); + if(cartridge.has.SA1) cpu.coprocessors.append(&sa1); + if(cartridge.has.SuperFX) cpu.coprocessors.append(&superfx); + if(cartridge.has.ARMDSP) cpu.coprocessors.append(&armdsp); + if(cartridge.has.HitachiDSP) cpu.coprocessors.append(&hitachidsp); + if(cartridge.has.NECDSP) cpu.coprocessors.append(&necdsp); + if(cartridge.has.EpsonRTC) cpu.coprocessors.append(&epsonrtc); + if(cartridge.has.SharpRTC) cpu.coprocessors.append(&sharprtc); + if(cartridge.has.SPC7110) cpu.coprocessors.append(&spc7110); + if(cartridge.has.MSU1) cpu.coprocessors.append(&msu1); scheduler.reset(); peripherals.reset(); diff --git a/higan/sfc/system/system.hpp b/higan/sfc/system/system.hpp index bc9ce36c..6c12dfa9 100644 --- a/higan/sfc/system/system.hpp +++ b/higan/sfc/system/system.hpp @@ -15,7 +15,8 @@ struct System { auto init() -> void; auto term() -> void; - auto load() -> void; + auto load() -> bool; + auto save() -> void; auto unload() -> void; auto power() -> void; auto reset() -> void; diff --git a/nall/vfs/vfs.hpp b/nall/vfs/vfs.hpp index 41208806..b1589bbf 100644 --- a/nall/vfs/vfs.hpp +++ b/nall/vfs/vfs.hpp @@ -23,7 +23,8 @@ struct file { return offset() >= size(); } - auto read(uint8_t* data, uintmax bytes) -> void { + auto read(void* vdata, uintmax bytes) -> void { + auto data = (uint8_t*)vdata; while(bytes--) *data++ = read(); } @@ -39,12 +40,15 @@ struct file { return data; } - auto reads(string& s) -> void { + auto reads() -> string { + string s; s.resize(size()); read(s.get(), s.size()); + return s; } - auto write(const uint8_t* data, uintmax bytes) -> void { + auto write(const void* vdata, uintmax bytes) -> void { + auto data = (const uint8_t*)vdata; while(bytes--) write(*data++); }