From 6847058210c6ca5677126ad365801eafa159be13 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Sun, 13 May 2018 23:00:48 +1000 Subject: [PATCH] Update to v106r19 release. byuu says: Changelog: - Super Famicom: everything outside of Nintendo Super System, Campus Challenge '92 and Powerfest '94 should play - Super Famicom: removed RAM from coprocessor/event (should use global RAM) - Super Famicom: removed RAM from SDD1 (should use global RAM) - icarus: fixed Super Famicom game importing [hex_usr] Also worth reminding that you'll need to disable database lookup in order to run the BS-X Town cartridge right now. Plus, Star Ocean's database entry still has the RAM in the wrong spot. The MSU1 code is not looking at the right locations for data, so it's not going to work in this release either. I need to figure out what to call coprocessor/event and coprocessor/nss, as neither are slots or processors like everything else. Outside of those issues, all games for all systems should be playable, at least to the extent they were in v106. --- higan/emulator/emulator.hpp | 2 +- higan/sfc/cartridge/cartridge.hpp | 9 +- higan/sfc/cartridge/load.cpp | 307 ++++++++++++------ higan/sfc/cartridge/save.cpp | 68 ++-- higan/sfc/coprocessor/event/event.cpp | 15 +- higan/sfc/coprocessor/event/event.hpp | 3 +- higan/sfc/coprocessor/event/serialization.cpp | 9 + higan/sfc/coprocessor/sdd1/sdd1.cpp | 20 +- higan/sfc/coprocessor/sdd1/sdd1.hpp | 12 +- higan/sfc/coprocessor/sdd1/serialization.cpp | 2 - higan/systems/Super Famicom.sys/boards.bml | 10 +- icarus/core/super-famicom.cpp | 4 +- 12 files changed, 285 insertions(+), 176 deletions(-) create mode 100644 higan/sfc/coprocessor/event/serialization.cpp 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));