diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 9798a558..5efb8e70 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -12,7 +12,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "106.18"; + static const string Version = "106.19"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "https://byuu.org/"; diff --git a/higan/sfc/cartridge/cartridge.hpp b/higan/sfc/cartridge/cartridge.hpp index 1eeeaa05..f0d547d5 100644 --- a/higan/sfc/cartridge/cartridge.hpp +++ b/higan/sfc/cartridge/cartridge.hpp @@ -68,7 +68,6 @@ private: auto loadRAM(Markup::Node) -> void; auto loadICD(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; @@ -76,7 +75,8 @@ private: auto loadSuperFX(Markup::Node) -> void; auto loadARMDSP(Markup::Node) -> void; auto loadHitachiDSP(Markup::Node, uint roms) -> void; - auto loadNECDSP(Markup::Node) -> void; + auto loaduPD7725(Markup::Node) -> void; + auto loaduPD96050(Markup::Node) -> void; auto loadEpsonRTC(Markup::Node) -> void; auto loadSharpRTC(Markup::Node) -> void; auto loadSPC7110(Markup::Node) -> void; @@ -97,16 +97,15 @@ private: 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 saveuPD7725(Markup::Node) -> void; + auto saveuPD96050(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, maybe = nothing) -> void; diff --git a/higan/sfc/cartridge/load.cpp b/higan/sfc/cartridge/load.cpp index 1f3944ed..370d6026 100644 --- a/higan/sfc/cartridge/load.cpp +++ b/higan/sfc/cartridge/load.cpp @@ -45,14 +45,17 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void { } } - if(board["bsmemory"] || board["mcc/bsmemory"] || board["sa1/bsmemory"]) { + if(board["slot(type=BSMemory)"] + || board["processor(identifier=MCC)/mcu/slot(type=BSMemory)"] + || board["processor(architecture=W65C816S)/mcu/slot(type=BSMemory)"] + ) { if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) { bsmemory.pathID = loaded.pathID(); loadBSMemory(); } } - if(board["sufamiturbo"]) { + if(board["slot(type=SufamiTurbo)"]) { if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { sufamiturboA.pathID = loaded.pathID(); loadSufamiTurboA(); @@ -61,42 +64,55 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void { if(auto node = board["memory(type=ROM,content=Program)"]) loadROM(node); if(auto node = board["memory(type=RAM,content=Save)"]) loadRAM(node); - if(auto node = board["icd"]) loadICD(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["processor(identifier=ICD)"]) loadICD(node); + if(auto node = board["processor(identifier=MCC)"]) loadMCC(node); + if(auto node = board.find("slot(type=SufamiTurbo)")) if(node(0)) loadSufamiTurbo(node(0), 0); + if(auto node = board.find("slot(type=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["processor(architecture=W65C816S)"]) loadSA1(node); if(auto node = board["processor(architecture=GSU)"]) loadSuperFX(node); - if(auto node = board["armdsp"]) loadARMDSP(node); + if(auto node = board["processor(architecture=ARM6)"]) loadARMDSP(node); if(auto node = board["processor(architecture=HG51BS169)"]) loadHitachiDSP(node, game.board.match("2DC*") ? 2 : 1); - if(auto node = board["necdsp"]) loadNECDSP(node); + if(auto node = board["processor(architecture=uPD7725)"]) loaduPD7725(node); + if(auto node = board["processor(architecture=uPD96050)"]) loaduPD96050(node); if(auto node = board["rtc(manufacturer=Epson)"]) loadEpsonRTC(node); if(auto node = board["rtc(manufacturer=Sharp)"]) loadSharpRTC(node); if(auto node = board["processor(identifier=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(auto node = board["processor(identifier=SDD1)"]) loadSDD1(node); + if(auto node = board["processor(identifier=OBC1)"]) loadOBC1(node); + if(auto node = board["processor(identifier=MSU1)"]) loadMSU1(node); } auto Cartridge::loadGameBoy(Markup::Node node) -> void { } auto Cartridge::loadBSMemory(Markup::Node node) -> void { - if(node["game/board/memory/type"].text() == "ROM") { + has.BSMemorySlot = true; + + if(auto memory = node["game/board/memory(type=ROM)"]) { bsmemory.readonly = true; - loadMemory(bsmemory.memory, node["game/board/memory(type=ROM)"], File::Required, bsmemory.pathID); - } else { + loadMemory(bsmemory.memory, memory, File::Required, bsmemory.pathID); + } else if(auto memory = node["game/board/memory(type=Flash)"]) { bsmemory.readonly = false; - loadMemory(bsmemory.memory, node["game/board/memory(type=Flash)"], File::Required, bsmemory.pathID); + loadMemory(bsmemory.memory, memory, File::Required, bsmemory.pathID); + } + + for(auto map : node.find("map")) { + if(bsmemory.memory.size()) { + loadMap(map, bsmemory); + } } } auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { - loadMemory(sufamiturboA.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboA.pathID); - loadMemory(sufamiturboA.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboA.pathID); + if(auto memory = node["game/board/memory(type=ROM)"]) { + loadMemory(sufamiturboA.rom, memory, File::Required, sufamiturboA.pathID); + } + + if(auto memory = node["game/board/memory(type=RAM)"]) { + loadMemory(sufamiturboA.ram, memory, File::Optional, sufamiturboA.pathID); + } if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) { sufamiturboB.pathID = loaded.pathID(); @@ -105,67 +121,86 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { } auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { - loadMemory(sufamiturboB.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboB.pathID); - loadMemory(sufamiturboB.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboB.pathID); + if(auto memory = node["game/board/memory(type=ROM)"]) { + loadMemory(sufamiturboB.rom, memory, File::Required, sufamiturboB.pathID); + } + + if(auto memory = node["game/board/memory(type=RAM)"]) { + loadMemory(sufamiturboB.ram, memory, File::Optional, sufamiturboB.pathID); + } } // +//memory(type=ROM,content=Program) auto Cartridge::loadROM(Markup::Node node) -> void { loadMemory(rom, node, File::Required); for(auto leaf : node.find("map")) loadMap(leaf, rom); } +//memory(type=RAM,content=Save) auto Cartridge::loadRAM(Markup::Node node) -> void { loadMemory(ram, node, File::Optional); for(auto leaf : node.find("map")) loadMap(leaf, ram); } +//processor(identifier=ICD) auto Cartridge::loadICD(Markup::Node node) -> void { has.GameBoySlot = true; has.ICD = true; + icd.Revision = node["revision"].natural(); - icd.Frequency = node["frequency"].natural(); + if(auto oscillator = game.oscillator()) { + icd.Frequency = oscillator->frequency; + } else { + icd.Frequency = 0; + } //Game Boy core loads data through ICD interface - for(auto leaf : node.find("map")) loadMap(leaf, {&ICD::readIO, &icd}, {&ICD::writeIO, &icd}); -} - -auto Cartridge::loadMCC(Markup::Node node) -> void { - has.BSMemorySlot = true; - has.MCC = true; - - loadMemory(mcc.rom, node["rom"], File::Required); - loadMemory(mcc.ram, node["ram"], File::Optional); - - for(auto leaf : node.find("map")) leaf.text() == "mcu" - ? loadMap(leaf, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc}) - : loadMap(leaf, {&MCC::read, &mcc}, {&MCC::write, &mcc}); - for(auto leaf : node["ram"].find("map")) loadMap(leaf, mcc.ram); -} - -auto Cartridge::loadBSMemoryPack(Markup::Node node) -> void { - has.BSMemorySlot = true; - - for(auto leaf : node.find("map")) { - if(bsmemory.memory.size() == 0) continue; - loadMap(leaf, bsmemory); + for(auto map : node.find("map")) { + loadMap(map, {&ICD::readIO, &icd}, {&ICD::writeIO, &icd}); } } +//processor(identifier=MCC) +auto Cartridge::loadMCC(Markup::Node node) -> void { + has.MCC = true; + + for(auto map : node.find("map")) { + loadMap(map, {&MCC::read, &mcc}, {&MCC::write, &mcc}); + } + + if(auto mcu = node["mcu"]) { + for(auto map : mcu.find("map")) { + loadMap(map, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc}); + } + if(auto memory = mcu["memory(type=ROM,content=Program)"]) { + loadMemory(mcc.rom, memory, File::Required); + } + } + + if(auto memory = node["memory(type=RAM,content=Download)"]) { + loadMemory(mcc.ram, memory, File::Optional); + for(auto map : memory.find("map")) { + loadMap(map, mcc.ram); + } + } +} + +//slot(type=SufamiTurbo)[0,1] auto Cartridge::loadSufamiTurbo(Markup::Node node, bool slot) -> void { has.SufamiTurboSlots = true; - for(auto leaf : node["rom"].find("map")) { - auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); - if(cart.rom.size() == 0) continue; - loadMap(leaf, cart.rom); + for(auto map : node.find("rom/map")) { + auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB; + if(cartridge.rom.size() == 0) continue; + loadMap(map, cartridge.rom); } - for(auto leaf : node["ram"].find("map")) { - auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); - if(cart.ram.size() == 0) continue; - loadMap(leaf, cart.ram); + for(auto map : node.find("ram/map")) { + auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB; + if(cartridge.ram.size() == 0) continue; + loadMap(map, cartridge.ram); } } @@ -183,7 +218,6 @@ auto Cartridge::loadEvent(Markup::Node node) -> void { has.Event = true; for(uint n : range(4)) loadMemory(event.rom[n], roms[n], File::Required); - loadMemory(event.ram, node["ram"], File::Optional); event.board = Event::Board::CampusChallenge92; if(node.text() == "CC92") event.board = Event::Board::CampusChallenge92; @@ -193,7 +227,6 @@ auto Cartridge::loadEvent(Markup::Node node) -> void { for(auto leaf : node.find("map")) leaf.text() == "mcu" ? loadMap(leaf, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}) : loadMap(leaf, {&Event::read, &event}, {&Event::write, &event}); - for(auto leaf : node["ram"].find("map")) loadMap(leaf, event.ram); } //processor(architecture=W65C816S) @@ -251,32 +284,47 @@ auto Cartridge::loadSuperFX(Markup::Node node) -> void { } } +//processor(architecture=ARM6) auto Cartridge::loadARMDSP(Markup::Node node) -> void { has.ARMDSP = true; + for(auto& word : armdsp.programROM) word = 0x00; + for(auto& word : armdsp.dataROM) word = 0x00; + for(auto& word : armdsp.programRAM) word = 0x00; + if(auto oscillator = game.oscillator()) { armdsp.Frequency = oscillator->frequency; } else { armdsp.Frequency = 21'440'000; } - if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) { - if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { - for(auto n : range(128 * 1024)) armdsp.programROM[n] = fp->read(); - } + for(auto map : node.find("map")) { + loadMap(map, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp}); } - if(auto memory = game.memory(node["memory(type=ROM,content=Data)"])) { - if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { - for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = fp->read(); - } - } - if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) { - if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { - for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read(); + + if(auto memory = node["memory(type=ROM,content=Program,architecture=ARM6)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(128 * 1024)) armdsp.programROM[n] = fp->read(); + } } } - for(auto leaf : node.find("map")) loadMap(leaf, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp}); + if(auto memory = node["memory(type=ROM,content=Data,architecture=ARM6)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(32 * 1024)) armdsp.dataROM[n] = fp->read(); + } + } + } + + if(auto memory = node["memory(type=RAM,content=Data,architecture=ARM6)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read)) { + for(auto n : range(16 * 1024)) armdsp.programRAM[n] = fp->read(); + } + } + } } //processor(architecture=HG51BS169) @@ -331,8 +379,14 @@ auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void { } } -auto Cartridge::loadNECDSP(Markup::Node node) -> void { +//processor(architecture=uPD7725) +auto Cartridge::loaduPD7725(Markup::Node node) -> void { has.NECDSP = true; + necdsp.revision = 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(auto oscillator = game.oscillator()) { necdsp.Frequency = oscillator->frequency; @@ -340,37 +394,83 @@ auto Cartridge::loadNECDSP(Markup::Node node) -> void { necdsp.Frequency = 7'600'000; } - necdsp.revision - = node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 - : node["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 - : NECDSP::Revision::uPD7725; + for(auto map : node.find("map")) { + loadMap(map, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); + } + + if(auto memory = node["memory(type=ROM,content=Program,architecture=uPD7725)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(2048)) necdsp.programROM[n] = fp->readl(3); + } + } + } + + if(auto memory = node["memory(type=ROM,content=Data,architecture=uPD7725)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(1024)) necdsp.dataROM[n] = fp->readl(2); + } + } + } + + if(auto memory = node["memory(type=RAM,content=Data,architecture=uPD7725)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read)) { + for(auto n : range(256)) necdsp.dataRAM[n] = fp->readl(2); + } + } + for(auto map : memory.find("map")) { + loadMap(map, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); + } + } +} + +//processor(architecture=uPD96050) +auto Cartridge::loaduPD96050(Markup::Node node) -> void { + has.NECDSP = true; + necdsp.revision = NECDSP::Revision::uPD96050; 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 oscillator = game.oscillator()) { + necdsp.Frequency = oscillator->frequency; + } else { + necdsp.Frequency = 11'000'000; + } - if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) { - if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { - for(auto n : range(size[0])) necdsp.programROM[n] = fp->readl(3); - } + for(auto map : node.find("map")) { + loadMap(map, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); } - if(auto memory = Emulator::Game::Memory{node["memory(type=ROM,content=Data)"]}) { - if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Read, File::Required)) { - for(auto n : range(size[1])) necdsp.dataROM[n] = fp->readl(2); - } - } - if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) { - if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Read)) { - for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2); + + if(auto memory = node["memory(type=ROM,content=Program,architecture=uPD96050)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(16384)) necdsp.programROM[n] = fp->readl(3); + } } } - for(auto leaf : node.find("map")) loadMap(leaf, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); - for(auto leaf : node["dram"].find("map")) loadMap(leaf, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); + if(auto memory = node["memory(type=ROM,content=Data,architecture=uPD96050)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read, File::Required)) { + for(auto n : range(2048)) necdsp.dataROM[n] = fp->readl(2); + } + } + } + + if(auto memory = node["memory(type=RAM,content=Data,architecture=uPD96050)"]) { + if(auto file = game.memory(memory)) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Read)) { + for(auto n : range(2048)) necdsp.dataRAM[n] = fp->readl(2); + } + } + for(auto map : memory.find("map")) { + loadMap(map, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); + } + } } //rtc(manufacturer=Epson) @@ -443,29 +543,44 @@ auto Cartridge::loadSPC7110(Markup::Node node) -> void { } } +//processor(identifier=SDD1) auto Cartridge::loadSDD1(Markup::Node node) -> void { has.SDD1 = true; - loadMemory(sdd1.rom, node["rom"], File::Required); - loadMemory(sdd1.ram, node["ram"], File::Optional); + for(auto map : node.find("map")) { + loadMap(map, {&SDD1::ioRead, &sdd1}, {&SDD1::ioWrite, &sdd1}); + } - for(auto leaf : node.find("map")) loadMap(leaf, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1}); - for(auto leaf : node["rom"].find("map")) loadMap(leaf, {&SDD1::mcuromRead, &sdd1}, {&SDD1::mcuromWrite, &sdd1}); - for(auto leaf : node["ram"].find("map")) loadMap(leaf, {&SDD1::mcuramRead, &sdd1}, {&SDD1::mcuramWrite, &sdd1}); + if(auto mcu = node["mcu"]) { + for(auto map : mcu.find("map")) { + loadMap(map, {&SDD1::mcuRead, &sdd1}, {&SDD1::mcuWrite, &sdd1}); + } + if(auto memory = mcu["memory(type=ROM,content=Program)"]) { + loadMemory(sdd1.rom, memory, File::Required); + } + } } +//processor(identifier=OBC1) auto Cartridge::loadOBC1(Markup::Node node) -> void { has.OBC1 = true; - loadMemory(obc1.ram, node["ram"], File::Optional); + for(auto map : node.find("map")) { + loadMap(map, {&OBC1::read, &obc1}, {&OBC1::write, &obc1}); + } - for(auto leaf : node.find("map")) loadMap(leaf, {&OBC1::read, &obc1}, {&OBC1::write, &obc1}); + if(auto memory = node["memory(type=RAM,content=Save)"]) { + loadMemory(obc1.ram, memory, File::Optional); + } } +//processor(identifier=MSU1) auto Cartridge::loadMSU1(Markup::Node node) -> void { has.MSU1 = true; - for(auto leaf : node.find("map")) loadMap(leaf, {&MSU1::readIO, &msu1}, {&MSU1::writeIO, &msu1}); + for(auto map : node.find("map")) { + loadMap(map, {&MSU1::readIO, &msu1}, {&MSU1::writeIO, &msu1}); + } } // diff --git a/higan/sfc/cartridge/save.cpp b/higan/sfc/cartridge/save.cpp index 020f3f89..b9752872 100644 --- a/higan/sfc/cartridge/save.cpp +++ b/higan/sfc/cartridge/save.cpp @@ -1,17 +1,16 @@ auto Cartridge::saveCartridge(Markup::Node node) -> void { if(auto node = board["memory(type=RAM,content=Save)"]) saveRAM(node); - if(auto node = board["mcc"]) saveMCC(node); - if(auto node = board["event"]) saveEvent(node); + if(auto node = board["processor(identifier=MCC)"]) saveMCC(node); if(auto node = board["processor(architecture=W65C816S)"]) saveSA1(node); if(auto node = board["processor(architecture=GSU)"]) saveSuperFX(node); - if(auto node = board["armdsp"]) saveARMDSP(node); + if(auto node = board["processor(architecture=ARM6)"]) saveARMDSP(node); if(auto node = board["processor(architecture=HG51BS169)"]) saveHitachiDSP(node); - if(auto node = board["necdsp"]) saveNECDSP(node); + if(auto node = board["processor(architecture=uPD7725)"]) saveuPD7725(node); + if(auto node = board["processor(architecture=uPD96050)"]) saveuPD96050(node); if(auto node = board["rtc(manufacturer=Epson)"]) saveEpsonRTC(node); if(auto node = board["rtc(manufacturer=Sharp)"]) saveSharpRTC(node); if(auto node = board["processor(identifier=SPC7110)"]) saveSPC7110(node); - if(auto node = board["sdd1"]) saveSDD1(node); - if(auto node = board["obc1"]) saveOBC1(node); + if(auto node = board["processor(identifier=OBC1)"]) saveOBC1(node); } auto Cartridge::saveGameBoy(Markup::Node node) -> void { @@ -30,16 +29,16 @@ auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void { // +//memory(type=RAM,content=Save) auto Cartridge::saveRAM(Markup::Node node) -> void { saveMemory(ram, node); } +//processor(identifier=MCC) auto Cartridge::saveMCC(Markup::Node node) -> void { - saveMemory(mcc.ram, node["ram"]); -} - -auto Cartridge::saveEvent(Markup::Node node) -> void { - saveMemory(event.ram, node["ram"]); + if(auto memory = node["memory(type=RAM,content=Download)"]) { + saveMemory(mcc.ram, memory); + } } //processor(architecture=W65C816S) @@ -60,11 +59,14 @@ auto Cartridge::saveSuperFX(Markup::Node node) -> void { } } +//processor(architecture=ARM6) auto Cartridge::saveARMDSP(Markup::Node node) -> void { - if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) { - if(memory->nonVolatile) { - if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) { - for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]); + if(auto memory = node["memory(type=RAM,content=Data,architecture=ARM6)"]) { + if(auto file = game.memory(memory)) { + if(file->nonVolatile) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Write)) { + for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]); + } } } } @@ -89,12 +91,27 @@ auto Cartridge::saveHitachiDSP(Markup::Node node) -> void { } } -auto Cartridge::saveNECDSP(Markup::Node node) -> void { - uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048; - if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) { - if(memory.nonVolatile) { - if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Write)) { - for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2); +//processor(architecture=uPD7725) +auto Cartridge::saveuPD7725(Markup::Node node) -> void { + if(auto memory = node["memory(type=RAM,content=Data,architecture=uPD7725)"]) { + if(auto file = game.memory(memory)) { + if(file->nonVolatile) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Write)) { + for(auto n : range(256)) fp->writel(necdsp.dataRAM[n], 2); + } + } + } + } +} + +//processor(architecture=uPD96050) +auto Cartridge::saveuPD96050(Markup::Node node) -> void { + if(auto memory = node["memory(type=RAM,content=Data,architecture=uPD96050)"]) { + if(auto file = game.memory(memory)) { + if(file->nonVolatile) { + if(auto fp = platform->open(ID::SuperFamicom, file->name(), File::Write)) { + for(auto n : range(2 * 1024)) fp->writel(necdsp.dataRAM[n], 2); + } } } } @@ -137,12 +154,11 @@ auto Cartridge::saveSPC7110(Markup::Node node) -> void { } } -auto Cartridge::saveSDD1(Markup::Node node) -> void { - saveMemory(sdd1.ram, node["ram"]); -} - +//processor(identifier=OBC1) auto Cartridge::saveOBC1(Markup::Node node) -> void { - saveMemory(obc1.ram, node["ram"]); + if(auto memory = node["memory(type=RAM,content=Save)"]) { + saveMemory(obc1.ram, memory); + } } // diff --git a/higan/sfc/coprocessor/event/event.cpp b/higan/sfc/coprocessor/event/event.cpp index 5bcb7cb4..3de01a65 100644 --- a/higan/sfc/coprocessor/event/event.cpp +++ b/higan/sfc/coprocessor/event/event.cpp @@ -2,6 +2,7 @@ namespace SuperFamicom { +#include "serialization.cpp" Event event; auto Event::Enter() -> void { @@ -33,7 +34,6 @@ auto Event::unload() -> void { rom[1].reset(); rom[2].reset(); rom[3].reset(); - ram.reset(); } auto Event::power() -> void { @@ -43,9 +43,7 @@ auto Event::power() -> void { rom[1].writeProtect(true); rom[2].writeProtect(true); rom[3].writeProtect(true); - ram.writeProtect(false); - for(auto n : range(ram.size())) ram.write(n, 0x00); status = 0x00; select = 0x00; timerActive = false; @@ -110,15 +108,4 @@ auto Event::write(uint24 addr, uint8 data) -> void { } } -auto Event::serialize(serializer& s) -> void { - Thread::serialize(s); - s.array(ram.data(), ram.size()); - s.integer(status); - s.integer(select); - s.integer(timerActive); - s.integer(scoreActive); - s.integer(timerSecondsRemaining); - s.integer(scoreSecondsRemaining); -} - } diff --git a/higan/sfc/coprocessor/event/event.hpp b/higan/sfc/coprocessor/event/event.hpp index 01a61579..776f5c42 100644 --- a/higan/sfc/coprocessor/event/event.hpp +++ b/higan/sfc/coprocessor/event/event.hpp @@ -3,6 +3,7 @@ //* Powerfest '94 struct Event : Thread { + //event.cpp static auto Enter() -> void; auto main() -> void; auto unload() -> void; @@ -14,10 +15,10 @@ struct Event : Thread { auto read(uint24 addr, uint8 data) -> uint8; auto write(uint24 addr, uint8 data) -> void; + //serialization.cpp auto serialize(serializer&) -> void; MappedRAM rom[4]; - MappedRAM ram; enum class Board : uint { CampusChallenge92, Powerfest94 } board; uint timer; diff --git a/higan/sfc/coprocessor/event/serialization.cpp b/higan/sfc/coprocessor/event/serialization.cpp new file mode 100644 index 00000000..b315cdc9 --- /dev/null +++ b/higan/sfc/coprocessor/event/serialization.cpp @@ -0,0 +1,9 @@ +auto Event::serialize(serializer& s) -> void { + Thread::serialize(s); + s.integer(status); + s.integer(select); + s.integer(timerActive); + s.integer(scoreActive); + s.integer(timerSecondsRemaining); + s.integer(scoreSecondsRemaining); +} diff --git a/higan/sfc/coprocessor/sdd1/sdd1.cpp b/higan/sfc/coprocessor/sdd1/sdd1.cpp index ea05ab23..45efc151 100644 --- a/higan/sfc/coprocessor/sdd1/sdd1.cpp +++ b/higan/sfc/coprocessor/sdd1/sdd1.cpp @@ -9,12 +9,10 @@ SDD1 sdd1; auto SDD1::unload() -> void { rom.reset(); - ram.reset(); } auto SDD1::power() -> void { rom.writeProtect(true); - ram.writeProtect(false); //hook S-CPU DMA MMIO registers to gather information for struct dma[]; //buffer address and transfer size information for use in SDD1::mcu_read() @@ -34,7 +32,7 @@ auto SDD1::power() -> void { dmaReady = false; } -auto SDD1::read(uint24 addr, uint8 data) -> uint8 { +auto SDD1::ioRead(uint24 addr, uint8 data) -> uint8 { addr = 0x4800 | addr.bits(0,3); switch(addr) { @@ -50,7 +48,7 @@ auto SDD1::read(uint24 addr, uint8 data) -> uint8 { return rom.read(addr); } -auto SDD1::write(uint24 addr, uint8 data) -> void { +auto SDD1::ioWrite(uint24 addr, uint8 data) -> void { addr = 0x4800 | addr.bits(0,3); switch(addr) { @@ -91,7 +89,7 @@ auto SDD1::mmcRead(uint24 addr) -> uint8 { //map address=00-3f,80-bf:8000-ffff //map address=c0-ff:0000-ffff -auto SDD1::mcuromRead(uint24 addr, uint8 data) -> uint8 { +auto SDD1::mcuRead(uint24 addr, uint8 data) -> uint8 { //map address=00-3f,80-bf:8000-ffff if(!addr.bit(22)) { if(!addr.bit(23) && addr.bit(21) && r4805.bit(7)) addr.bit(21) = 0; //20-3f:8000-ffff @@ -130,17 +128,7 @@ auto SDD1::mcuromRead(uint24 addr, uint8 data) -> uint8 { return mmcRead(addr); } -auto SDD1::mcuromWrite(uint24 addr, uint8 data) -> void { -} - -//map address=00-3f,80-bf:6000-7fff mask=0xe000 -//map address=70-73:0000-ffff mask=0x8000 -auto SDD1::mcuramRead(uint24 addr, uint8 data) -> uint8 { - return ram.read(addr.bits(0,12), data); -} - -auto SDD1::mcuramWrite(uint24 addr, uint8 data) -> void { - return ram.write(addr.bits(0,12), data); +auto SDD1::mcuWrite(uint24 addr, uint8 data) -> void { } } diff --git a/higan/sfc/coprocessor/sdd1/sdd1.hpp b/higan/sfc/coprocessor/sdd1/sdd1.hpp index 45ffb406..4b23f9d7 100644 --- a/higan/sfc/coprocessor/sdd1/sdd1.hpp +++ b/higan/sfc/coprocessor/sdd1/sdd1.hpp @@ -2,24 +2,20 @@ struct SDD1 { auto unload() -> void; auto power() -> void; - auto read(uint24 addr, uint8 data) -> uint8; - auto write(uint24 addr, uint8 data) -> void; + auto ioRead(uint24 addr, uint8 data) -> uint8; + auto ioWrite(uint24 addr, uint8 data) -> void; auto dmaRead(uint24 addr, uint8 data) -> uint8; auto dmaWrite(uint24 addr, uint8 data) -> void; auto mmcRead(uint24 addr) -> uint8; - auto mcuromRead(uint24 addr, uint8 data) -> uint8; - auto mcuromWrite(uint24 addr, uint8 data) -> void; - - auto mcuramRead(uint24 addr, uint8 data) -> uint8; - auto mcuramWrite(uint24 addr, uint8 data) -> void; + auto mcuRead(uint24 addr, uint8 data) -> uint8; + auto mcuWrite(uint24 addr, uint8 data) -> void; auto serialize(serializer&) -> void; MappedRAM rom; - MappedRAM ram; private: uint8 r4800; //hard enable diff --git a/higan/sfc/coprocessor/sdd1/serialization.cpp b/higan/sfc/coprocessor/sdd1/serialization.cpp index 618b5dcf..216b056e 100644 --- a/higan/sfc/coprocessor/sdd1/serialization.cpp +++ b/higan/sfc/coprocessor/sdd1/serialization.cpp @@ -1,6 +1,4 @@ auto SDD1::serialize(serializer& s) -> void { - s.array(ram.data(), ram.size()); - s.integer(r4800); s.integer(r4801); s.integer(r4804); diff --git a/higan/systems/Super Famicom.sys/boards.bml b/higan/systems/Super Famicom.sys/boards.bml index cd41e0d7..400a5979 100644 --- a/higan/systems/Super Famicom.sys/boards.bml +++ b/higan/systems/Super Famicom.sys/boards.bml @@ -1,5 +1,5 @@ database - revision: 2018-05-08 + revision: 2018-05-12 //Boards (Production) @@ -552,7 +552,7 @@ board: SHVC-YJ0N-01 //Boards (Generic) database - revision: 2018-05-08 + revision: 2018-05-12 board: ARM-LOROM-RAM memory type=ROM content=Program @@ -797,15 +797,15 @@ board: SDD1 memory type=ROM content=Program board: SDD1-RAM + memory type=RAM content=Save + map address=00-3f,80-bf:6000-7fff mask=0xe000 + map address=70-73:0000-ffff mask=0x8000 processor identifier=SDD1 map address=00-3f,80-bf:4800-480f mcu map address=00-3f,80-bf:8000-ffff map address=c0-ff:0000-ffff memory type=ROM content=Program - memory type=RAM content=Save - map address=00-3f,80-bf:6000-7fff mask=0xe000 - map address=70-73:0000-ffff mask=0x8000 board: SPC7110-RAM processor identifier=SPC7110 diff --git a/icarus/core/super-famicom.cpp b/icarus/core/super-famicom.cpp index 39977571..3ab403a7 100644 --- a/icarus/core/super-famicom.cpp +++ b/icarus/core/super-famicom.cpp @@ -43,10 +43,10 @@ auto Icarus::superFamicomImport(vector& buffer, string location) -> str auto document = BML::unserialize(manifest); for(auto rom : document.find("game/board/memory")) { if(rom["type"].text() != "ROM") continue; - auto name = string{rom["part"].text(), ".", rom["category"].text(), ".rom"}.trimLeft(".", 1L).downcase(); + auto name = string{rom["architecture"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase(); auto size = rom["size"].natural(); if(size > buffer.size() - offset) { - auto name = string{rom["note"].text(), ".", rom["category"].text(), ".rom"}.trimLeft(".", 1L).downcase(); + auto name = string{rom["identifier"].text(), ".", rom["content"].text(), ".rom"}.trimLeft(".", 1L).downcase(); auto location = locate({"firmware/", name}); if(location && file::size(location) == size) { write({target, name}, file::read(location));