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++); }