auto Cartridge::loadCartridge(Markup::Node node) -> void { information.title.cartridge = node["information/title"].text(); auto board = node["board"]; information.region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC; if(board["mcc"] || board["bsmemory"]) { if(auto pathID = interface->load(ID::BSMemory, "BS Memory", "bs")) { bsmemory.pathID = pathID(); } } if(board["sufamiturbo"]) { if(auto pathID = interface->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { sufamiturboA.pathID = pathID(); } } 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); } 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"], File::Required, bsmemory.pathID); } auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void { information.title.sufamiTurboA = node["information/title"].text(); loadMemory(sufamiturboA.rom, node["board/rom"], File::Required, sufamiturboA.pathID); loadMemory(sufamiturboA.ram, node["board/ram"], File::Optional, sufamiturboA.pathID); if(node["board/linkable"]) { if(auto pathID = interface->load(ID::SufamiTurboB, "Sufami Turbo", "st")) { sufamiturboB.pathID = pathID(); } } } auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { information.title.sufamiTurboB = node["information/title"].text(); loadMemory(sufamiturboB.rom, node["board/rom"], File::Required, sufamiturboB.pathID); loadMemory(sufamiturboB.ram, node["board/ram"], File::Optional, sufamiturboB.pathID); } // auto Cartridge::loadROM(Markup::Node node) -> void { loadMemory(rom, node, File::Required); for(auto leaf : node.find("map")) loadMap(leaf, rom); } auto Cartridge::loadRAM(Markup::Node node) -> void { loadMemory(ram, node, File::Optional); for(auto leaf : node.find("map")) loadMap(leaf, ram); } auto Cartridge::loadICD2(Markup::Node node) -> void { has.GameBoySlot = true; has.ICD2 = true; icd2.revision = max(1, node["revision"].natural()); //Game Boy core loads data through ICD2 interface for(auto leaf : node.find("map")) loadMap(leaf, {&ICD2::read, &icd2}, {&ICD2::write, &icd2}); } 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); } } 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 leaf : node["ram"].find("map")) { auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); if(cart.ram.size() == 0) continue; loadMap(leaf, cart.ram); } } auto Cartridge::loadNSS(Markup::Node node) -> void { has.NSSDIP = true; nss.dip = interface->dipSettings(node); for(auto leaf : node.find("map")) loadMap(leaf, {&NSS::read, &nss}, {&NSS::write, &nss}); } auto Cartridge::loadEvent(Markup::Node node) -> void { auto roms = node.find("rom"); if(roms.size() != 4) return; 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; if(node.text() == "PF94") event.board = Event::Board::Powerfest94; event.timer = node["timer"].natural(); 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); } auto Cartridge::loadSA1(Markup::Node node) -> void { has.SA1 = true; loadMemory(sa1.rom, node["rom"], File::Required); loadMemory(sa1.bwram, node["bwram"], File::Optional); loadMemory(sa1.iram, node["iram"], File::Optional); for(auto leaf : node.find("map")) loadMap(leaf, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1}); for(auto leaf : node["rom"].find("map")) loadMap(leaf, {&SA1::mmcromRead, &sa1}, {&SA1::mmcromWrite, &sa1}); for(auto leaf : node["bwram"].find("map")) loadMap(leaf, {&SA1::mmcbwramRead, &sa1}, {&SA1::mmcbwramWrite, &sa1}); for(auto leaf : node["iram"].find("map")) loadMap(leaf, sa1.cpuiram); } auto Cartridge::loadSuperFX(Markup::Node node) -> void { has.SuperFX = true; loadMemory(superfx.rom, node["rom"], File::Required); loadMemory(superfx.ram, node["ram"], File::Optional); for(auto leaf : node.find("map")) loadMap(leaf, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx}); for(auto leaf : node["rom"].find("map")) loadMap(leaf, superfx.cpurom); for(auto leaf : node["ram"].find("map")) loadMap(leaf, superfx.cpuram); } auto Cartridge::loadARMDSP(Markup::Node node) -> void { has.ARMDSP = true; if(auto fp = interface->open(ID::SuperFamicom, node["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, node["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, node["ram"]["name"].text(), File::Read)) { for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read(); } for(auto leaf : node.find("map")) loadMap(leaf, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp}); } auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void { has.HitachiDSP = true; hitachidsp.Frequency = node["frequency"].natural(); if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000; hitachidsp.Roms = roms; //1 or 2 loadMemory(hitachidsp.rom, node["rom"], File::Required); loadMemory(hitachidsp.ram, node["ram"], File::Optional); for(auto& word : hitachidsp.dataROM) word = 0x000000; for(auto& word : hitachidsp.dataRAM) word = 0x00; if(auto fp = interface->open(ID::SuperFamicom, node["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, node["dram"]["name"].text(), File::Read)) { for(auto n : range(3 * 1024)) hitachidsp.dataRAM[n] = fp->readl(1); } for(auto leaf : node.find("map")) loadMap(leaf, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp}); for(auto leaf : node["rom"].find("map")) loadMap(leaf, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp}); for(auto leaf : node["ram"].find("map")) loadMap(leaf, {&HitachiDSP::ramRead, &hitachidsp}, {&HitachiDSP::ramWrite, &hitachidsp}); for(auto leaf : node["dram"].find("map")) loadMap(leaf, {&HitachiDSP::dramRead, &hitachidsp}, {&HitachiDSP::dramWrite, &hitachidsp}); } auto Cartridge::loadNECDSP(Markup::Node node) -> void { has.NECDSP = true; necdsp.frequency = node["frequency"].natural(); if(necdsp.frequency == 0) necdsp.frequency = 8000000; necdsp.revision = node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 : node["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, node["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, node["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, node["dram"]["name"].text(), File::Read)) { for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2); } 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}); } auto Cartridge::loadEpsonRTC(Markup::Node node) -> void { has.EpsonRTC = true; if(auto fp = interface->open(ID::SuperFamicom, node["ram"]["name"].text(), File::Read)) { uint8 data[16] = {0}; for(auto& byte : data) fp->read(); epsonrtc.load(data); } for(auto leaf : node.find("map")) loadMap(leaf, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc}); } auto Cartridge::loadSharpRTC(Markup::Node node) -> void { has.SharpRTC = true; if(auto fp = interface->open(ID::SuperFamicom, node["ram"]["name"].text(), File::Read)) { uint8 data[16] = {0}; for(auto& byte : data) fp->read(); sharprtc.load(data); } for(auto leaf : node.find("map")) loadMap(leaf, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc}); } auto Cartridge::loadSPC7110(Markup::Node node) -> void { has.SPC7110 = true; loadMemory(spc7110.prom, node["prom"], File::Required); loadMemory(spc7110.drom, node["drom"], File::Required); loadMemory(spc7110.ram, node["ram"], File::Optional); for(auto leaf : node.find("map")) leaf.text() == "mcu" ? loadMap(leaf, {&SPC7110::mcuromRead, &spc7110}, {&SPC7110::mcuromWrite, &spc7110}) : loadMap(leaf, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110}); for(auto leaf : node["ram"].find("map")) loadMap(leaf, {&SPC7110::mcuramRead, &spc7110}, {&SPC7110::mcuramWrite, &spc7110}); } 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 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}); } auto Cartridge::loadOBC1(Markup::Node node) -> void { has.OBC1 = true; loadMemory(obc1.ram, node["ram"], File::Optional); for(auto leaf : node.find("map")) loadMap(leaf, {&OBC1::read, &obc1}, {&OBC1::write, &obc1}); } auto Cartridge::loadMSU1(Markup::Node node) -> void { has.MSU1 = true; for(auto leaf : node.find("map")) loadMap(leaf, {&MSU1::read, &msu1}, {&MSU1::write, &msu1}); } // auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, maybe id) -> void { if(!id) id = pathID(); auto name = node["name"].text(); auto size = node["size"].natural(); ram.allocate(size); if(auto fp = interface->open(id(), name, File::Read, required)) { 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); }