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.
This commit is contained in:
Tim Allen 2018-05-13 23:00:48 +10:00
parent b7dca2f317
commit 6847058210
12 changed files with 285 additions and 176 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; 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 Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "https://byuu.org/"; static const string Website = "https://byuu.org/";

View File

@ -68,7 +68,6 @@ private:
auto loadRAM(Markup::Node) -> void; auto loadRAM(Markup::Node) -> void;
auto loadICD(Markup::Node) -> void; auto loadICD(Markup::Node) -> void;
auto loadMCC(Markup::Node) -> void; auto loadMCC(Markup::Node) -> void;
auto loadBSMemoryPack(Markup::Node) -> void;
auto loadSufamiTurbo(Markup::Node, bool slot) -> void; auto loadSufamiTurbo(Markup::Node, bool slot) -> void;
auto loadNSS(Markup::Node) -> void; auto loadNSS(Markup::Node) -> void;
auto loadEvent(Markup::Node) -> void; auto loadEvent(Markup::Node) -> void;
@ -76,7 +75,8 @@ private:
auto loadSuperFX(Markup::Node) -> void; auto loadSuperFX(Markup::Node) -> void;
auto loadARMDSP(Markup::Node) -> void; auto loadARMDSP(Markup::Node) -> void;
auto loadHitachiDSP(Markup::Node, uint roms) -> 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 loadEpsonRTC(Markup::Node) -> void;
auto loadSharpRTC(Markup::Node) -> void; auto loadSharpRTC(Markup::Node) -> void;
auto loadSPC7110(Markup::Node) -> void; auto loadSPC7110(Markup::Node) -> void;
@ -97,16 +97,15 @@ private:
auto saveRAM(Markup::Node) -> void; auto saveRAM(Markup::Node) -> void;
auto saveMCC(Markup::Node) -> void; auto saveMCC(Markup::Node) -> void;
auto saveEvent(Markup::Node) -> void;
auto saveSA1(Markup::Node) -> void; auto saveSA1(Markup::Node) -> void;
auto saveSuperFX(Markup::Node) -> void; auto saveSuperFX(Markup::Node) -> void;
auto saveARMDSP(Markup::Node) -> void; auto saveARMDSP(Markup::Node) -> void;
auto saveHitachiDSP(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 saveEpsonRTC(Markup::Node) -> void;
auto saveSharpRTC(Markup::Node) -> void; auto saveSharpRTC(Markup::Node) -> void;
auto saveSPC7110(Markup::Node) -> void; auto saveSPC7110(Markup::Node) -> void;
auto saveSDD1(Markup::Node) -> void;
auto saveOBC1(Markup::Node) -> void; auto saveOBC1(Markup::Node) -> void;
auto saveMemory(MappedRAM&, Markup::Node, maybe<uint> = nothing) -> void; auto saveMemory(MappedRAM&, Markup::Node, maybe<uint> = nothing) -> void;

View File

@ -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")) { if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
bsmemory.pathID = loaded.pathID(); bsmemory.pathID = loaded.pathID();
loadBSMemory(); loadBSMemory();
} }
} }
if(board["sufamiturbo"]) { if(board["slot(type=SufamiTurbo)"]) {
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) { if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
sufamiturboA.pathID = loaded.pathID(); sufamiturboA.pathID = loaded.pathID();
loadSufamiTurboA(); 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=ROM,content=Program)"]) loadROM(node);
if(auto node = board["memory(type=RAM,content=Save)"]) loadRAM(node); if(auto node = board["memory(type=RAM,content=Save)"]) loadRAM(node);
if(auto node = board["icd"]) loadICD(node); if(auto node = board["processor(identifier=ICD)"]) loadICD(node);
if(auto node = board["mcc"]) loadMCC(node); if(auto node = board["processor(identifier=MCC)"]) loadMCC(node);
if(auto node = board["bsmemory"]) loadBSMemoryPack(node); if(auto node = board.find("slot(type=SufamiTurbo)")) if(node(0)) loadSufamiTurbo(node(0), 0);
if(auto node = board.find("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.find("sufamiturbo")) if(node(1)) loadSufamiTurbo(node(1), 1);
if(auto node = board["nss"]) loadNSS(node); if(auto node = board["nss"]) loadNSS(node);
if(auto node = board["event"]) loadEvent(node); if(auto node = board["event"]) loadEvent(node);
if(auto node = board["processor(architecture=W65C816S)"]) loadSA1(node); if(auto node = board["processor(architecture=W65C816S)"]) loadSA1(node);
if(auto node = board["processor(architecture=GSU)"]) loadSuperFX(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["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=Epson)"]) loadEpsonRTC(node);
if(auto node = board["rtc(manufacturer=Sharp)"]) loadSharpRTC(node); if(auto node = board["rtc(manufacturer=Sharp)"]) loadSharpRTC(node);
if(auto node = board["processor(identifier=SPC7110)"]) loadSPC7110(node); if(auto node = board["processor(identifier=SPC7110)"]) loadSPC7110(node);
if(auto node = board["sdd1"]) loadSDD1(node); if(auto node = board["processor(identifier=SDD1)"]) loadSDD1(node);
if(auto node = board["obc1"]) loadOBC1(node); if(auto node = board["processor(identifier=OBC1)"]) loadOBC1(node);
if(auto node = board["msu1"]) loadMSU1(node); if(auto node = board["processor(identifier=MSU1)"]) loadMSU1(node);
} }
auto Cartridge::loadGameBoy(Markup::Node node) -> void { auto Cartridge::loadGameBoy(Markup::Node node) -> void {
} }
auto Cartridge::loadBSMemory(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; bsmemory.readonly = true;
loadMemory(bsmemory.memory, node["game/board/memory(type=ROM)"], File::Required, bsmemory.pathID); loadMemory(bsmemory.memory, memory, File::Required, bsmemory.pathID);
} else { } else if(auto memory = node["game/board/memory(type=Flash)"]) {
bsmemory.readonly = false; 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 { auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
loadMemory(sufamiturboA.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboA.pathID); if(auto memory = node["game/board/memory(type=ROM)"]) {
loadMemory(sufamiturboA.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboA.pathID); 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")) { if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
sufamiturboB.pathID = loaded.pathID(); sufamiturboB.pathID = loaded.pathID();
@ -105,67 +121,86 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
} }
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void { auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
loadMemory(sufamiturboB.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboB.pathID); if(auto memory = node["game/board/memory(type=ROM)"]) {
loadMemory(sufamiturboB.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboB.pathID); 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 { auto Cartridge::loadROM(Markup::Node node) -> void {
loadMemory(rom, node, File::Required); loadMemory(rom, node, File::Required);
for(auto leaf : node.find("map")) loadMap(leaf, rom); for(auto leaf : node.find("map")) loadMap(leaf, rom);
} }
//memory(type=RAM,content=Save)
auto Cartridge::loadRAM(Markup::Node node) -> void { auto Cartridge::loadRAM(Markup::Node node) -> void {
loadMemory(ram, node, File::Optional); loadMemory(ram, node, File::Optional);
for(auto leaf : node.find("map")) loadMap(leaf, ram); for(auto leaf : node.find("map")) loadMap(leaf, ram);
} }
//processor(identifier=ICD)
auto Cartridge::loadICD(Markup::Node node) -> void { auto Cartridge::loadICD(Markup::Node node) -> void {
has.GameBoySlot = true; has.GameBoySlot = true;
has.ICD = true; has.ICD = true;
icd.Revision = node["revision"].natural(); 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 //Game Boy core loads data through ICD interface
for(auto leaf : node.find("map")) loadMap(leaf, {&ICD::readIO, &icd}, {&ICD::writeIO, &icd}); for(auto map : node.find("map")) {
loadMap(map, {&ICD::readIO, &icd}, {&ICD::writeIO, &icd});
}
} }
//processor(identifier=MCC)
auto Cartridge::loadMCC(Markup::Node node) -> void { auto Cartridge::loadMCC(Markup::Node node) -> void {
has.BSMemorySlot = true;
has.MCC = true; has.MCC = true;
loadMemory(mcc.rom, node["rom"], File::Required); for(auto map : node.find("map")) {
loadMemory(mcc.ram, node["ram"], File::Optional); loadMap(map, {&MCC::read, &mcc}, {&MCC::write, &mcc});
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 { if(auto mcu = node["mcu"]) {
has.BSMemorySlot = true; for(auto map : mcu.find("map")) {
loadMap(map, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc});
for(auto leaf : node.find("map")) { }
if(bsmemory.memory.size() == 0) continue; if(auto memory = mcu["memory(type=ROM,content=Program)"]) {
loadMap(leaf, bsmemory); 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 { auto Cartridge::loadSufamiTurbo(Markup::Node node, bool slot) -> void {
has.SufamiTurboSlots = true; has.SufamiTurboSlots = true;
for(auto leaf : node["rom"].find("map")) { for(auto map : node.find("rom/map")) {
auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB;
if(cart.rom.size() == 0) continue; if(cartridge.rom.size() == 0) continue;
loadMap(leaf, cart.rom); loadMap(map, cartridge.rom);
} }
for(auto leaf : node["ram"].find("map")) { for(auto map : node.find("ram/map")) {
auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB); auto& cartridge = slot == 0 ? sufamiturboA : sufamiturboB;
if(cart.ram.size() == 0) continue; if(cartridge.ram.size() == 0) continue;
loadMap(leaf, cart.ram); loadMap(map, cartridge.ram);
} }
} }
@ -183,7 +218,6 @@ auto Cartridge::loadEvent(Markup::Node node) -> void {
has.Event = true; has.Event = true;
for(uint n : range(4)) loadMemory(event.rom[n], roms[n], File::Required); 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; event.board = Event::Board::CampusChallenge92;
if(node.text() == "CC92") 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" for(auto leaf : node.find("map")) leaf.text() == "mcu"
? loadMap(leaf, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event}) ? loadMap(leaf, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event})
: loadMap(leaf, {&Event::read, &event}, {&Event::write, &event}); : loadMap(leaf, {&Event::read, &event}, {&Event::write, &event});
for(auto leaf : node["ram"].find("map")) loadMap(leaf, event.ram);
} }
//processor(architecture=W65C816S) //processor(architecture=W65C816S)
@ -251,32 +284,47 @@ auto Cartridge::loadSuperFX(Markup::Node node) -> void {
} }
} }
//processor(architecture=ARM6)
auto Cartridge::loadARMDSP(Markup::Node node) -> void { auto Cartridge::loadARMDSP(Markup::Node node) -> void {
has.ARMDSP = true; 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()) { if(auto oscillator = game.oscillator()) {
armdsp.Frequency = oscillator->frequency; armdsp.Frequency = oscillator->frequency;
} else { } else {
armdsp.Frequency = 21'440'000; armdsp.Frequency = 21'440'000;
} }
if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) { for(auto map : node.find("map")) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { loadMap(map, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp});
}
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 n : range(128 * 1024)) armdsp.programROM[n] = fp->read();
} }
} }
if(auto memory = game.memory(node["memory(type=ROM,content=Data)"])) { }
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
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(); 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)) {
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(); 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});
} }
//processor(architecture=HG51BS169) //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; 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()) { if(auto oscillator = game.oscillator()) {
necdsp.Frequency = oscillator->frequency; necdsp.Frequency = oscillator->frequency;
@ -340,37 +394,83 @@ auto Cartridge::loadNECDSP(Markup::Node node) -> void {
necdsp.Frequency = 7'600'000; necdsp.Frequency = 7'600'000;
} }
necdsp.revision for(auto map : node.find("map")) {
= node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 loadMap(map, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
: node["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 }
: NECDSP::Revision::uPD7725;
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.programROM) word = 0x000000;
for(auto& word : necdsp.dataROM) word = 0x0000; for(auto& word : necdsp.dataROM) word = 0x0000;
for(auto& word : necdsp.dataRAM) word = 0x0000; for(auto& word : necdsp.dataRAM) word = 0x0000;
uint size[3] = {0}; if(auto oscillator = game.oscillator()) {
if(necdsp.revision == NECDSP::Revision::uPD7725 ) memory::assign(size, 2048, 1024, 256); necdsp.Frequency = oscillator->frequency;
if(necdsp.revision == NECDSP::Revision::uPD96050) memory::assign(size, 16384, 2048, 2048); } else {
necdsp.Frequency = 11'000'000;
}
if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) { for(auto map : node.find("map")) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { loadMap(map, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
for(auto n : range(size[0])) necdsp.programROM[n] = fp->readl(3);
} }
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);
} }
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);
} }
} }
for(auto leaf : node.find("map")) loadMap(leaf, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp}); if(auto memory = node["memory(type=ROM,content=Data,architecture=uPD96050)"]) {
for(auto leaf : node["dram"].find("map")) loadMap(leaf, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp}); 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) //rtc(manufacturer=Epson)
@ -443,29 +543,44 @@ auto Cartridge::loadSPC7110(Markup::Node node) -> void {
} }
} }
//processor(identifier=SDD1)
auto Cartridge::loadSDD1(Markup::Node node) -> void { auto Cartridge::loadSDD1(Markup::Node node) -> void {
has.SDD1 = true; has.SDD1 = true;
loadMemory(sdd1.rom, node["rom"], File::Required); for(auto map : node.find("map")) {
loadMemory(sdd1.ram, node["ram"], File::Optional); 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 { auto Cartridge::loadOBC1(Markup::Node node) -> void {
has.OBC1 = true; 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 { auto Cartridge::loadMSU1(Markup::Node node) -> void {
has.MSU1 = true; 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});
}
} }
// //

View File

@ -1,17 +1,16 @@
auto Cartridge::saveCartridge(Markup::Node node) -> void { auto Cartridge::saveCartridge(Markup::Node node) -> void {
if(auto node = board["memory(type=RAM,content=Save)"]) saveRAM(node); if(auto node = board["memory(type=RAM,content=Save)"]) saveRAM(node);
if(auto node = board["mcc"]) saveMCC(node); if(auto node = board["processor(identifier=MCC)"]) saveMCC(node);
if(auto node = board["event"]) saveEvent(node);
if(auto node = board["processor(architecture=W65C816S)"]) saveSA1(node); if(auto node = board["processor(architecture=W65C816S)"]) saveSA1(node);
if(auto node = board["processor(architecture=GSU)"]) saveSuperFX(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["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=Epson)"]) saveEpsonRTC(node);
if(auto node = board["rtc(manufacturer=Sharp)"]) saveSharpRTC(node); if(auto node = board["rtc(manufacturer=Sharp)"]) saveSharpRTC(node);
if(auto node = board["processor(identifier=SPC7110)"]) saveSPC7110(node); if(auto node = board["processor(identifier=SPC7110)"]) saveSPC7110(node);
if(auto node = board["sdd1"]) saveSDD1(node); if(auto node = board["processor(identifier=OBC1)"]) saveOBC1(node);
if(auto node = board["obc1"]) saveOBC1(node);
} }
auto Cartridge::saveGameBoy(Markup::Node node) -> void { 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 { auto Cartridge::saveRAM(Markup::Node node) -> void {
saveMemory(ram, node); saveMemory(ram, node);
} }
//processor(identifier=MCC)
auto Cartridge::saveMCC(Markup::Node node) -> void { auto Cartridge::saveMCC(Markup::Node node) -> void {
saveMemory(mcc.ram, node["ram"]); if(auto memory = node["memory(type=RAM,content=Download)"]) {
saveMemory(mcc.ram, memory);
} }
auto Cartridge::saveEvent(Markup::Node node) -> void {
saveMemory(event.ram, node["ram"]);
} }
//processor(architecture=W65C816S) //processor(architecture=W65C816S)
@ -60,15 +59,18 @@ auto Cartridge::saveSuperFX(Markup::Node node) -> void {
} }
} }
//processor(architecture=ARM6)
auto Cartridge::saveARMDSP(Markup::Node node) -> void { auto Cartridge::saveARMDSP(Markup::Node node) -> void {
if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) { if(auto memory = node["memory(type=RAM,content=Data,architecture=ARM6)"]) {
if(memory->nonVolatile) { if(auto file = game.memory(memory)) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) { 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]); for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]);
} }
} }
} }
} }
}
//processor(architecture=HG51BS169) //processor(architecture=HG51BS169)
auto Cartridge::saveHitachiDSP(Markup::Node node) -> void { auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
@ -89,12 +91,27 @@ auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
} }
} }
auto Cartridge::saveNECDSP(Markup::Node node) -> void { //processor(architecture=uPD7725)
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048; auto Cartridge::saveuPD7725(Markup::Node node) -> void {
if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) { if(auto memory = node["memory(type=RAM,content=Data,architecture=uPD7725)"]) {
if(memory.nonVolatile) { if(auto file = game.memory(memory)) {
if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Write)) { if(file->nonVolatile) {
for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2); 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 { //processor(identifier=OBC1)
saveMemory(sdd1.ram, node["ram"]);
}
auto Cartridge::saveOBC1(Markup::Node node) -> void { 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);
}
} }
// //

View File

@ -2,6 +2,7 @@
namespace SuperFamicom { namespace SuperFamicom {
#include "serialization.cpp"
Event event; Event event;
auto Event::Enter() -> void { auto Event::Enter() -> void {
@ -33,7 +34,6 @@ auto Event::unload() -> void {
rom[1].reset(); rom[1].reset();
rom[2].reset(); rom[2].reset();
rom[3].reset(); rom[3].reset();
ram.reset();
} }
auto Event::power() -> void { auto Event::power() -> void {
@ -43,9 +43,7 @@ auto Event::power() -> void {
rom[1].writeProtect(true); rom[1].writeProtect(true);
rom[2].writeProtect(true); rom[2].writeProtect(true);
rom[3].writeProtect(true); rom[3].writeProtect(true);
ram.writeProtect(false);
for(auto n : range(ram.size())) ram.write(n, 0x00);
status = 0x00; status = 0x00;
select = 0x00; select = 0x00;
timerActive = false; 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);
}
} }

View File

@ -3,6 +3,7 @@
//* Powerfest '94 //* Powerfest '94
struct Event : Thread { struct Event : Thread {
//event.cpp
static auto Enter() -> void; static auto Enter() -> void;
auto main() -> void; auto main() -> void;
auto unload() -> void; auto unload() -> void;
@ -14,10 +15,10 @@ struct Event : Thread {
auto read(uint24 addr, uint8 data) -> uint8; auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void; auto write(uint24 addr, uint8 data) -> void;
//serialization.cpp
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
MappedRAM rom[4]; MappedRAM rom[4];
MappedRAM ram;
enum class Board : uint { CampusChallenge92, Powerfest94 } board; enum class Board : uint { CampusChallenge92, Powerfest94 } board;
uint timer; uint timer;

View File

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

View File

@ -9,12 +9,10 @@ SDD1 sdd1;
auto SDD1::unload() -> void { auto SDD1::unload() -> void {
rom.reset(); rom.reset();
ram.reset();
} }
auto SDD1::power() -> void { auto SDD1::power() -> void {
rom.writeProtect(true); rom.writeProtect(true);
ram.writeProtect(false);
//hook S-CPU DMA MMIO registers to gather information for struct dma[]; //hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::mcu_read() //buffer address and transfer size information for use in SDD1::mcu_read()
@ -34,7 +32,7 @@ auto SDD1::power() -> void {
dmaReady = false; dmaReady = false;
} }
auto SDD1::read(uint24 addr, uint8 data) -> uint8 { auto SDD1::ioRead(uint24 addr, uint8 data) -> uint8 {
addr = 0x4800 | addr.bits(0,3); addr = 0x4800 | addr.bits(0,3);
switch(addr) { switch(addr) {
@ -50,7 +48,7 @@ auto SDD1::read(uint24 addr, uint8 data) -> uint8 {
return rom.read(addr); 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); addr = 0x4800 | addr.bits(0,3);
switch(addr) { switch(addr) {
@ -91,7 +89,7 @@ auto SDD1::mmcRead(uint24 addr) -> uint8 {
//map address=00-3f,80-bf:8000-ffff //map address=00-3f,80-bf:8000-ffff
//map address=c0-ff:0000-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 //map address=00-3f,80-bf:8000-ffff
if(!addr.bit(22)) { if(!addr.bit(22)) {
if(!addr.bit(23) && addr.bit(21) && r4805.bit(7)) addr.bit(21) = 0; //20-3f:8000-ffff 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); return mmcRead(addr);
} }
auto SDD1::mcuromWrite(uint24 addr, uint8 data) -> void { auto SDD1::mcuWrite(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);
} }
} }

View File

@ -2,24 +2,20 @@ struct SDD1 {
auto unload() -> void; auto unload() -> void;
auto power() -> void; auto power() -> void;
auto read(uint24 addr, uint8 data) -> uint8; auto ioRead(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void; auto ioWrite(uint24 addr, uint8 data) -> void;
auto dmaRead(uint24 addr, uint8 data) -> uint8; auto dmaRead(uint24 addr, uint8 data) -> uint8;
auto dmaWrite(uint24 addr, uint8 data) -> void; auto dmaWrite(uint24 addr, uint8 data) -> void;
auto mmcRead(uint24 addr) -> uint8; auto mmcRead(uint24 addr) -> uint8;
auto mcuromRead(uint24 addr, uint8 data) -> uint8; auto mcuRead(uint24 addr, uint8 data) -> uint8;
auto mcuromWrite(uint24 addr, uint8 data) -> void; auto mcuWrite(uint24 addr, uint8 data) -> void;
auto mcuramRead(uint24 addr, uint8 data) -> uint8;
auto mcuramWrite(uint24 addr, uint8 data) -> void;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
MappedRAM rom; MappedRAM rom;
MappedRAM ram;
private: private:
uint8 r4800; //hard enable uint8 r4800; //hard enable

View File

@ -1,6 +1,4 @@
auto SDD1::serialize(serializer& s) -> void { auto SDD1::serialize(serializer& s) -> void {
s.array(ram.data(), ram.size());
s.integer(r4800); s.integer(r4800);
s.integer(r4801); s.integer(r4801);
s.integer(r4804); s.integer(r4804);

View File

@ -1,5 +1,5 @@
database database
revision: 2018-05-08 revision: 2018-05-12
//Boards (Production) //Boards (Production)
@ -552,7 +552,7 @@ board: SHVC-YJ0N-01
//Boards (Generic) //Boards (Generic)
database database
revision: 2018-05-08 revision: 2018-05-12
board: ARM-LOROM-RAM board: ARM-LOROM-RAM
memory type=ROM content=Program memory type=ROM content=Program
@ -797,15 +797,15 @@ board: SDD1
memory type=ROM content=Program memory type=ROM content=Program
board: SDD1-RAM 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 processor identifier=SDD1
map address=00-3f,80-bf:4800-480f map address=00-3f,80-bf:4800-480f
mcu mcu
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
memory type=ROM content=Program 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 board: SPC7110-RAM
processor identifier=SPC7110 processor identifier=SPC7110

View File

@ -43,10 +43,10 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, string location) -> str
auto document = BML::unserialize(manifest); auto document = BML::unserialize(manifest);
for(auto rom : document.find("game/board/memory")) { for(auto rom : document.find("game/board/memory")) {
if(rom["type"].text() != "ROM") continue; 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(); auto size = rom["size"].natural();
if(size > buffer.size() - offset) { 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}); auto location = locate({"firmware/", name});
if(location && file::size(location) == size) { if(location && file::size(location) == size) {
write({target, name}, file::read(location)); write({target, name}, file::read(location));