void Cartridge::parse_markup_sufamiturbo(XML::Node &root) { if(root.exists() == false) return; if(mode.value != Mode::SufamiTurbo) return; for(auto &slot : root) { if(slot.name != "slot") continue; bool slotid = slot["id"].data == "A" ? 0 : slot["id"].data == "B" ? 1 : 0; for(auto &node : slot) { if(node.name == "rom") { for(auto &leaf : node) { if(leaf.name != "map") continue; Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom; Mapping m(memory); parse_markup_map(m, leaf); if(m.size == 0) m.size = memory.size(); if(m.size) mapping.append(m); } } if(node.name == "ram") { unsigned ram_size = numeral(node["size"].data); for(auto &leaf : node) { if(leaf.name != "map") continue; Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram; Mapping m(memory); parse_markup_map(m, leaf); if(m.size == 0) m.size = ram_size; if(m.size) mapping.append(m); } } } } }
void Cartridge::parse_markup_armdsp(XML::Node &root) { if(root.exists() == false) return; has_armdsp = true; string firmware = root["firmware"].data; string sha256 = root["sha256"].data; string path = interface()->path(Slot::Base, firmware); file fp; if(fp.open(path, file::mode::read) == false) { interface()->message({ "Warning: ARM DSP firmware ", firmware, " is missing." }); } else if(fp.size() != 160 * 1024) { interface()->message({ "Warning: ARM DSP firmware ", firmware, " is of the wrong file size." }); fp.close(); } else { fp.read(armdsp.firmware, fp.size()); if(!sha256.empty()) { if(sha256 != nall::sha256(armdsp.firmware, fp.size())) { interface()->message({ "Warning: ARM DSP firmware ", firmware, " SHA256 sum is incorrect." }); } } fp.close(); } for(auto &node : root) { if(node.name != "map") continue; Mapping m({ &ArmDSP::mmio_read, &armdsp }, { &ArmDSP::mmio_write, &armdsp }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_bsx(XML::Node &root) { if(root.exists() == false) return; if(mode.value != Mode::BsxSlotted && mode.value != Mode::Bsx) return; has_bsx_slot = true; for(auto &node : root["slot"]) { if(node.name != "map") continue; Mapping m(bsxflash.memory); parse_markup_map(m, node); mapping.append(m); } for(auto &node : root["mmio"]) { if(node.name != "map") continue; Mapping m({ &BSXCartridge::mmio_read, &bsxcartridge }, { &BSXCartridge::mmio_write, &bsxcartridge }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : root["mcu"]) { if(node.name != "map") continue; Mapping m({ &BSXCartridge::mcu_read, &bsxcartridge }, { &BSXCartridge::mcu_write, &bsxcartridge }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_ram(XML::Node &root) { if(root.exists() == false) return; ram_size = numeral(root["size"].data); for(auto &node : root) { Mapping m(ram); parse_markup_map(m, node); if(m.size == 0) m.size = ram_size; mapping.append(m); } }
void Cartridge::parse_markup_rom(XML::Node &root) { if(root.exists() == false) return; for(auto &node : root) { if(node.name != "map") continue; Mapping m(rom); parse_markup_map(m, node); if(m.size == 0) m.size = rom.size(); mapping.append(m); } }
void Cartridge::parse_markup_obc1(XML::Node &root) { if(root.exists() == false) return; has_obc1 = true; for(auto &node : root) { if(node.name != "map") continue; Mapping m({ &OBC1::read, &obc1 }, { &OBC1::write, &obc1 }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_hitachidsp(XML::Node &root) { if(root.exists() == false) return; has_hitachidsp = true; for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = 0x000000; hitachidsp.frequency = numeral(root["frequency"].data); if(hitachidsp.frequency == 0) hitachidsp.frequency = 20000000; string firmware = root["firmware"].data; string sha256 = root["sha256"].data; string path = interface()->path(Slot::Base, firmware); file fp; if(fp.open(path, file::mode::read) == false) { interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " is missing." }); } else if(fp.size() != 1024 * 3) { interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " is of the wrong file size." }); fp.close(); } else { for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = fp.readl(3); if(!sha256.empty()) { //XML file specified SHA256 sum for program. Verify file matches the hash. fp.seek(0); uint8 data[3072]; fp.read(data, 3072); if(sha256 != nall::sha256(data, 3072)) { interface()->message({ "Warning: Hitachi DSP firmware ", firmware, " SHA256 sum is incorrect." }); } } fp.close(); } for(auto &node : root) { if(node.name == "rom") { for(auto &leaf : node) { if(leaf.name != "map") continue; Mapping m({ &HitachiDSP::rom_read, &hitachidsp }, { &HitachiDSP::rom_write, &hitachidsp }); parse_markup_map(m, leaf); mapping.append(m); } } if(node.name == "mmio") { for(auto &leaf : node) { Mapping m({ &HitachiDSP::dsp_read, &hitachidsp }, { &HitachiDSP::dsp_write, &hitachidsp }); parse_markup_map(m, leaf); mapping.append(m); } } } }
void Cartridge::parse_markup_link(XML::Node &root) { if(root.exists() == false) return; has_link = true; link.frequency = max(1, numeral(root["frequency"].data)); link.program = root["program"].data; for(auto &node : root) { if(node.name != "map") continue; Mapping m({ &Link::read, &link }, { &Link::write, &link }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_spc7110(XML::Node &root) { if(root.exists() == false) return; has_spc7110 = true; has_spc7110rtc = root["rtc"].exists(); auto &ram = root["ram"]; auto &mmio = root["mmio"]; auto &mcu = root["mcu"]; auto &dcu = root["dcu"]; auto &rtc = root["rtc"]; ram_size = numeral(ram["size"].data); for(auto &node : ram) { if(node.name != "map") continue; Mapping m({ &SPC7110::ram_read, &spc7110 }, { &SPC7110::ram_write, &spc7110 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : mmio) { if(node.name != "map") continue; Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); parse_markup_map(m, node); mapping.append(m); } spc7110.data_rom_offset = numeral(mcu["offset"].data); if(spc7110.data_rom_offset == 0) spc7110.data_rom_offset = 0x100000; for(auto &node : mcu) { if(node.name != "map") continue; Mapping m({ &SPC7110::mcu_read, &spc7110 }, { &SPC7110::mcu_write, &spc7110 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : dcu) { if(node.name != "map") continue; Mapping m({ &SPC7110::dcu_read, &spc7110 }, { &SPC7110::dcu_write, &spc7110 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : rtc) { if(node.name != "map") continue; Mapping m({ &SPC7110::mmio_read, &spc7110 }, { &SPC7110::mmio_write, &spc7110 }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_icd2(XML::Node &root) { #if defined(GAMEBOY) if(root.exists() == false) return; if(mode.value != Mode::SuperGameBoy) return; icd2.revision = max(1, numeral(root["revision"].data)); for(auto &node : root) { if(node.name != "map") continue; Mapping m({ &ICD2::read, &icd2 }, { &ICD2::write, &icd2 }); parse_markup_map(m, node); mapping.append(m); } #endif }
void Cartridge::parse_markup_sa1(XML::Node &root) { if(root.exists() == false) return; has_sa1 = true; auto &mcurom = root["mcu"]["rom"]; auto &mcuram = root["mcu"]["ram"]; auto &iram = root["iram"]; auto &bwram = root["bwram"]; auto &mmio = root["mmio"]; for(auto &node : mcurom) { if(node.name != "map") continue; Mapping m({ &SA1::mmc_read, &sa1 }, { &SA1::mmc_write, &sa1 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : mcuram) { if(node.name != "map") continue; Mapping m({ &SA1::mmc_cpu_read, &sa1 }, { &SA1::mmc_cpu_write, &sa1 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : iram) { if(node.name != "map") continue; Mapping m(sa1.cpuiram); parse_markup_map(m, node); if(m.size == 0) m.size = 2048; mapping.append(m); } ram_size = numeral(bwram["size"].data); for(auto &node : bwram) { if(node.name != "map") continue; Mapping m(sa1.cpubwram); parse_markup_map(m, node); if(m.size == 0) m.size = ram_size; mapping.append(m); } for(auto &node : mmio) { if(node.name != "map") continue; Mapping m({ &SA1::mmio_read, &sa1 }, { &SA1::mmio_write, &sa1 }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_nss(XML::Node &root) { if(root.exists() == false) return; has_nss_dip = true; for(auto &node : root) { if(node.name != "setting") continue; unsigned number = information.nss.setting.size(); if(number >= 16) break; //more than 16 DIP switches is not physically possible information.nss.option[number].reset(); information.nss.setting.append(node["name"].data); for(auto &leaf : node) { if(leaf.name != "option") continue; string name = leaf["name"].data; unsigned value = numeral(leaf["value"].data); information.nss.option[number].append({ hex<4>(value), ":", name }); } } }
void Cartridge::parse_markup_sdd1(XML::Node &root) { if(root.exists() == false) return; has_sdd1 = true; for(auto &node : root["mmio"]) { if(node.name != "map") continue; Mapping m({ &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 }); parse_markup_map(m, node); mapping.append(m); } for(auto &node : root["mcu"]) { if(node.name != "map") continue; Mapping m({ &SDD1::mcu_read, &sdd1 }, { &SDD1::mcu_write, &sdd1 }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_msu1(XML::Node &root) { if(root.exists() == false) { has_msu1 = file::exists(interface()->path(Cartridge::Slot::Base, "msu1.rom")); if(has_msu1) { Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); m.banklo = 0x00, m.bankhi = 0x3f, m.addrlo = 0x2000, m.addrhi = 0x2007; mapping.append(m); m.banklo = 0x80, m.bankhi = 0xbf, m.addrlo = 0x2000, m.addrhi = 0x2007; mapping.append(m); } return; } has_msu1 = true; for(auto &node : root) { if(node.name != "map") continue; Mapping m({ &MSU1::mmio_read, &msu1 }, { &MSU1::mmio_write, &msu1 }); parse_markup_map(m, node); mapping.append(m); } }
void Cartridge::parse_markup_superfx(XML::Node &root) { if(root.exists() == false) return; has_superfx = true; for(auto &node : root) { if(node.name == "rom") { for(auto &leaf : node) { if(leaf.name != "map") continue; Mapping m(superfx.rom); parse_markup_map(m, leaf); mapping.append(m); } } if(node.name == "ram") { for(auto &leaf : node) { if(leaf.name == "size") { ram_size = numeral(leaf.data); continue; } if(leaf.name != "map") continue; Mapping m(superfx.ram); parse_markup_map(m, leaf); if(m.size == 0) m.size = ram_size; mapping.append(m); } } if(node.name == "mmio") { for(auto &leaf : node) { if(leaf.name != "map") continue; Mapping m({ &SuperFX::mmio_read, &superfx }, { &SuperFX::mmio_write, &superfx }); parse_markup_map(m, leaf); mapping.append(m); } } } }
void Cartridge::parse_markup_necdsp(XML::Node &root) { if(root.exists() == false) return; has_necdsp = true; for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000; for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000; necdsp.frequency = numeral(root["frequency"].data); if(necdsp.frequency == 0) necdsp.frequency = 8000000; necdsp.revision = root["model"].data == "uPD7725" ? NECDSP::Revision::uPD7725 : root["model"].data == "uPD96050" ? NECDSP::Revision::uPD96050 : NECDSP::Revision::uPD7725; string firmware = root["firmware"].data; string sha256 = root["sha256"].data; string path = interface()->path(Slot::Base, firmware); unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384); unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048); unsigned filesize = promsize * 3 + dromsize * 2; file fp; if(fp.open(path, file::mode::read) == false) { interface()->message({ "Warning: NEC DSP firmware ", firmware, " is missing." }); } else if(fp.size() != filesize) { interface()->message({ "Warning: NEC DSP firmware ", firmware, " is of the wrong file size." }); fp.close(); } else { for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readl(3); for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readl(2); if(!sha256.empty()) { //XML file specified SHA256 sum for program. Verify file matches the hash. fp.seek(0); //uint8_t data[filesize]; //test uint8_t *data = (uint8_t*)alloca(filesize); fp.read(data, filesize); if(sha256 != nall::sha256(data, filesize)) { interface()->message({ "Warning: NEC DSP firmware ", firmware, " SHA256 sum is incorrect." }); } } fp.close(); } for(auto &node : root) { if(node.name == "dr") { for(auto &leaf : node) { Mapping m({ &NECDSP::dr_read, &necdsp }, { &NECDSP::dr_write, &necdsp }); parse_markup_map(m, leaf); mapping.append(m); } } if(node.name == "sr") { for(auto &leaf : node) { Mapping m({ &NECDSP::sr_read, &necdsp }, { &NECDSP::sr_write, &necdsp }); parse_markup_map(m, leaf); mapping.append(m); } } if(node.name == "dp") { for(auto &leaf : node) { Mapping m({ &NECDSP::dp_read, &necdsp }, { &NECDSP::dp_write, &necdsp }); parse_markup_map(m, leaf); mapping.append(m); } } } }