mirror of https://github.com/bsnes-emu/bsnes.git
Update to v099r06 release.
byuu says: Changelog: - Super Famicom core converted to use nall/vfs - excludes Super Game Boy; since that's invoked from inside the GB core This was definitely the major obstacle to test nall/vfs' applicability. Things worked out pretty great in the end. We went from 22.0KiB (cartridge) + 18.6KiB (interface) to 24.5KiB (cartridge) + 11.4KiB (interface). Or 40.7KiB to 36.0KiB. This removes a very large source of indirection. Before it was: "coprocessor <=> cartridge <=> interface" for loading and saving data, and now it's just "coprocessor <=> cartridge". And it may make sense to eventually turn this into just "cartridge -> coprocessor" by making each coprocessor class handle its own markup parsing. It's nice to have all the manifest parsing in one location (well, sans MSU1); but it's also nice for loading/unloading to be handled by each coprocessor itself. So I'll have to think longer about that one. I've also started handling Interface::save() differently. Instead of keeping track of memory IDs and filenames, and iterating through that vector of objects ... instead I now have a system that mirrors the markup parsing on loading, but handles saving instead. This was actually the reason the code size savings weren't more significant, but I like this style more. As before, it removes an extra level of indirection. So ... next up, I need to port over the GB, then GBA, then WS cores. These shouldn't take too long since they're all very simple with just ROM+RAM(+RTC) right now. Then get the SGB callbacks using vfs. Then after that, gut all the old stream stuff from nall and higan. Kill the (load,save)Request stuff, rename the load(Gamepak)Request to something simpler, and then we should be good. Anyway ... these are some huge changes.
This commit is contained in:
parent
f04d9d58f5
commit
875f031182
|
@ -10,7 +10,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "099.05";
|
static const string Version = "099.06";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "http://byuu.org/";
|
static const string Website = "http://byuu.org/";
|
||||||
|
|
|
@ -79,8 +79,8 @@ struct Interface {
|
||||||
|
|
||||||
//video information
|
//video information
|
||||||
virtual auto videoFrequency() -> double = 0;
|
virtual auto videoFrequency() -> double = 0;
|
||||||
virtual auto videoColors() -> uint32 { return 1 << 19; }
|
virtual auto videoColors() -> uint32 = 0;
|
||||||
virtual auto videoColor(uint32 color) -> uint64 { return 0; }
|
virtual auto videoColor(uint32 color) -> uint64 = 0;
|
||||||
|
|
||||||
//audio information
|
//audio information
|
||||||
virtual auto audioFrequency() -> double = 0;
|
virtual auto audioFrequency() -> double = 0;
|
||||||
|
|
|
@ -28,7 +28,7 @@ auto Cartridge::main() -> void {
|
||||||
|
|
||||||
auto Cartridge::load() -> bool {
|
auto Cartridge::load() -> bool {
|
||||||
if(auto fp = interface->open(ID::Famicom, "manifest.bml", vfs::file::mode::read, true)) {
|
if(auto fp = interface->open(ID::Famicom, "manifest.bml", vfs::file::mode::read, true)) {
|
||||||
fp->reads(information.markup);
|
information.markup = fp->reads();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ auto System::runToSave() -> void {
|
||||||
|
|
||||||
auto System::load() -> bool {
|
auto System::load() -> bool {
|
||||||
if(auto fp = interface->open(ID::System, "manifest.bml", vfs::file::mode::read, true)) {
|
if(auto fp = interface->open(ID::System, "manifest.bml", vfs::file::mode::read, true)) {
|
||||||
fp->reads(information.manifest);
|
information.manifest = fp->reads();
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,108 +2,53 @@
|
||||||
|
|
||||||
namespace SuperFamicom {
|
namespace SuperFamicom {
|
||||||
|
|
||||||
#include "markup.cpp"
|
#include "load.cpp"
|
||||||
|
#include "save.cpp"
|
||||||
#include "serialization.cpp"
|
#include "serialization.cpp"
|
||||||
Cartridge cartridge;
|
Cartridge cartridge;
|
||||||
|
|
||||||
auto Cartridge::manifest() -> string {
|
auto Cartridge::manifest() const -> string {
|
||||||
string manifest = information.markup.cartridge;
|
string manifest = information.manifest.cartridge;
|
||||||
|
if(information.manifest.gameBoy) manifest.append("\n[[Game Boy]]\n\n", information.manifest.gameBoy);
|
||||||
if(information.markup.gameBoy) {
|
if(information.manifest.bsMemory) manifest.append("\n[[BS Memory]]\n\n", information.manifest.bsMemory);
|
||||||
manifest.append("\n[[Game Boy]]\n\n");
|
if(information.manifest.sufamiTurboA) manifest.append("\n[[Sufami Turbo - Slot A]]\n\n", information.manifest.sufamiTurboA);
|
||||||
manifest.append(information.markup.gameBoy);
|
if(information.manifest.sufamiTurboB) manifest.append("\n[[Sufami Turbo - Slot B]]\n\n", information.manifest.sufamiTurboB);
|
||||||
}
|
|
||||||
|
|
||||||
if(information.markup.bsMemory) {
|
|
||||||
manifest.append("\n[[BS Memory]]\n\n");
|
|
||||||
manifest.append(information.markup.bsMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(information.markup.sufamiTurboA) {
|
|
||||||
manifest.append("\n[[Sufami Turbo - Slot A]]\n\n");
|
|
||||||
manifest.append(information.markup.sufamiTurboA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(information.markup.sufamiTurboB) {
|
|
||||||
manifest.append("\n[[Sufami Turbo - Slot B]]\n\n");
|
|
||||||
manifest.append(information.markup.sufamiTurboB);
|
|
||||||
}
|
|
||||||
|
|
||||||
return manifest;
|
return manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::title() -> string {
|
auto Cartridge::title() const -> string {
|
||||||
string title = information.title.cartridge;
|
string title = information.title.cartridge;
|
||||||
|
if(information.title.gameBoy) title.append(" + ", information.title.gameBoy);
|
||||||
if(information.title.gameBoy) {
|
if(information.title.bsMemory) title.append(" + ", information.title.bsMemory);
|
||||||
title.append(" + ", information.title.gameBoy);
|
if(information.title.sufamiTurboA) title.append(" + ", information.title.sufamiTurboA);
|
||||||
}
|
if(information.title.sufamiTurboB) title.append(" + ", information.title.sufamiTurboB);
|
||||||
|
|
||||||
if(information.title.bsMemory) {
|
|
||||||
title.append(" + ", information.title.bsMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(information.title.sufamiTurboA) {
|
|
||||||
title.append(" + ", information.title.sufamiTurboA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(information.title.sufamiTurboB) {
|
|
||||||
title.append(" + ", information.title.sufamiTurboB);
|
|
||||||
}
|
|
||||||
|
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::load() -> void {
|
auto Cartridge::load() -> bool {
|
||||||
|
information = Information();
|
||||||
|
has = Has();
|
||||||
|
_sha256 = "";
|
||||||
_region = Region::NTSC;
|
_region = Region::NTSC;
|
||||||
|
|
||||||
hasICD2 = false;
|
if(auto fp = interface->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) {
|
||||||
hasMCC = false;
|
information.manifest.cartridge = fp->reads();
|
||||||
hasNSSDIP = false;
|
} else return false;
|
||||||
hasEvent = false;
|
auto document = BML::unserialize(information.manifest.cartridge);
|
||||||
hasSA1 = false;
|
loadCartridge(document);
|
||||||
hasSuperFX = false;
|
|
||||||
hasARMDSP = false;
|
|
||||||
hasHitachiDSP = false;
|
|
||||||
hasNECDSP = false;
|
|
||||||
hasEpsonRTC = false;
|
|
||||||
hasSharpRTC = false;
|
|
||||||
hasSPC7110 = false;
|
|
||||||
hasSDD1 = false;
|
|
||||||
hasOBC1 = false;
|
|
||||||
hasMSU1 = false;
|
|
||||||
|
|
||||||
hasGameBoySlot = false;
|
|
||||||
hasBSMemorySlot = false;
|
|
||||||
hasSufamiTurboSlots = false;
|
|
||||||
|
|
||||||
information.markup.cartridge = "";
|
|
||||||
information.markup.gameBoy = "";
|
|
||||||
information.markup.bsMemory = "";
|
|
||||||
information.markup.sufamiTurboA = "";
|
|
||||||
information.markup.sufamiTurboB = "";
|
|
||||||
|
|
||||||
information.title.cartridge = "";
|
|
||||||
information.title.gameBoy = "";
|
|
||||||
information.title.bsMemory = "";
|
|
||||||
information.title.sufamiTurboA = "";
|
|
||||||
information.title.sufamiTurboB = "";
|
|
||||||
|
|
||||||
interface->loadRequest(ID::Manifest, "manifest.bml", true);
|
|
||||||
parseMarkup(information.markup.cartridge);
|
|
||||||
|
|
||||||
//Game Boy
|
//Game Boy
|
||||||
if(cartridge.hasICD2) {
|
if(cartridge.has.ICD2) {
|
||||||
_sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy()
|
_sha256 = ""; //Game Boy cartridge not loaded yet: set later via loadGameBoy()
|
||||||
}
|
}
|
||||||
|
|
||||||
//BS Memory
|
//BS Memory
|
||||||
else if(cartridge.hasMCC && cartridge.hasBSMemorySlot) {
|
else if(cartridge.has.MCC && cartridge.has.BSMemorySlot) {
|
||||||
_sha256 = Hash::SHA256(bsmemory.memory.data(), bsmemory.memory.size()).digest();
|
_sha256 = Hash::SHA256(bsmemory.memory.data(), bsmemory.memory.size()).digest();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Sufami Turbo
|
//Sufami Turbo
|
||||||
else if(cartridge.hasSufamiTurboSlots) {
|
else if(cartridge.has.SufamiTurboSlots) {
|
||||||
Hash::SHA256 sha;
|
Hash::SHA256 sha;
|
||||||
sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size());
|
sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size());
|
||||||
sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size());
|
sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size());
|
||||||
|
@ -136,85 +81,51 @@ auto Cartridge::load() -> void {
|
||||||
|
|
||||||
rom.writeProtect(true);
|
rom.writeProtect(true);
|
||||||
ram.writeProtect(false);
|
ram.writeProtect(false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadGameBoy() -> void {
|
auto Cartridge::loadGameBoy() -> void {
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
//invoked from ICD2::load()
|
//invoked from ICD2::load()
|
||||||
_sha256 = GameBoy::interface->sha256();
|
_sha256 = GameBoy::interface->sha256();
|
||||||
information.markup.gameBoy = GameBoy::interface->manifest();
|
information.manifest.gameBoy = GameBoy::interface->manifest();
|
||||||
information.title.gameBoy = GameBoy::interface->title();
|
information.title.gameBoy = GameBoy::interface->title();
|
||||||
#endif
|
#endif
|
||||||
|
loadGameBoy(BML::unserialize(information.manifest.gameBoy));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadBSMemory() -> void {
|
auto Cartridge::loadBSMemory() -> void {
|
||||||
interface->loadRequest(ID::BSMemoryManifest, "manifest.bml", true);
|
if(auto fp = interface->open(ID::BSMemory, "manifest.bml", File::Read, File::Required)) {
|
||||||
auto document = BML::unserialize(information.markup.bsMemory);
|
information.manifest.bsMemory = fp->reads();
|
||||||
information.title.bsMemory = document["information/title"].text();
|
} else return;
|
||||||
|
loadBSMemory(BML::unserialize(information.manifest.bsMemory));
|
||||||
auto rom = document["board/rom"];
|
|
||||||
|
|
||||||
if(rom["name"]) {
|
|
||||||
uint size = rom["size"].natural();
|
|
||||||
bsmemory.memory.map(allocate<uint8>(size, 0xff), size);
|
|
||||||
interface->loadRequest(ID::BSMemoryROM, rom["name"].text(), true);
|
|
||||||
|
|
||||||
bsmemory.readonly = (rom["type"].text() == "mrom");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboA() -> void {
|
auto Cartridge::loadSufamiTurboA() -> void {
|
||||||
interface->loadRequest(ID::SufamiTurboSlotAManifest, "manifest.bml", true);
|
if(auto fp = interface->open(ID::SufamiTurboA, "manifest.bml", File::Read, File::Required)) {
|
||||||
auto document = BML::unserialize(information.markup.sufamiTurboA);
|
information.manifest.sufamiTurboA = fp->reads();
|
||||||
information.title.sufamiTurboA = document["information/title"].text();
|
} else return;
|
||||||
|
loadSufamiTurboA(BML::unserialize(information.manifest.sufamiTurboA));
|
||||||
auto rom = document["board/rom"];
|
|
||||||
auto ram = document["board/ram"];
|
|
||||||
|
|
||||||
if(rom["name"]) {
|
|
||||||
uint size = rom["size"].natural();
|
|
||||||
sufamiturboA.rom.map(allocate<uint8>(size, 0xff), size);
|
|
||||||
interface->loadRequest(ID::SufamiTurboSlotAROM, rom["name"].text(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ram["name"]) {
|
|
||||||
uint size = ram["size"].natural();
|
|
||||||
sufamiturboA.ram.map(allocate<uint8>(size, 0xff), size);
|
|
||||||
interface->loadRequest(ID::SufamiTurboSlotARAM, ram["name"].text(), false);
|
|
||||||
memory.append({ID::SufamiTurboSlotARAM, ram["name"].text()});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(document["board/linkable"]) {
|
|
||||||
interface->loadRequest(ID::SufamiTurboSlotB, "Sufami Turbo", "st", false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboB() -> void {
|
auto Cartridge::loadSufamiTurboB() -> void {
|
||||||
interface->loadRequest(ID::SufamiTurboSlotBManifest, "manifest.bml", true);
|
if(auto fp = interface->open(ID::SufamiTurboB, "manifest.bml", File::Read, File::Required)) {
|
||||||
auto document = BML::unserialize(information.markup.sufamiTurboB);
|
information.manifest.sufamiTurboB = fp->reads();
|
||||||
information.title.sufamiTurboB = document["information/title"].text();
|
} else return;
|
||||||
|
loadSufamiTurboB(BML::unserialize(information.manifest.sufamiTurboB));
|
||||||
|
}
|
||||||
|
|
||||||
auto rom = document["board/rom"];
|
auto Cartridge::save() -> void {
|
||||||
auto ram = document["board/ram"];
|
saveCartridge(BML::unserialize(information.manifest.cartridge));
|
||||||
|
saveGameBoy(BML::unserialize(information.manifest.gameBoy));
|
||||||
if(rom["name"]) {
|
saveBSMemory(BML::unserialize(information.manifest.bsMemory));
|
||||||
uint size = rom["size"].natural();
|
saveSufamiTurboA(BML::unserialize(information.manifest.sufamiTurboA));
|
||||||
sufamiturboB.rom.map(allocate<uint8>(size, 0xff), size);
|
saveSufamiTurboB(BML::unserialize(information.manifest.sufamiTurboB));
|
||||||
interface->loadRequest(ID::SufamiTurboSlotBROM, rom["name"].text(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ram["name"]) {
|
|
||||||
uint size = ram["size"].natural();
|
|
||||||
sufamiturboB.ram.map(allocate<uint8>(size, 0xff), size);
|
|
||||||
interface->loadRequest(ID::SufamiTurboSlotBRAM, ram["name"].text(), false);
|
|
||||||
memory.append({ID::SufamiTurboSlotBRAM, ram["name"].text()});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::unload() -> void {
|
auto Cartridge::unload() -> void {
|
||||||
rom.reset();
|
rom.reset();
|
||||||
ram.reset();
|
ram.reset();
|
||||||
memory.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,11 @@ struct Cartridge {
|
||||||
|
|
||||||
auto sha256() const -> string { return _sha256; }
|
auto sha256() const -> string { return _sha256; }
|
||||||
auto region() const -> Region { return _region; }
|
auto region() const -> Region { return _region; }
|
||||||
|
auto manifest() const -> string;
|
||||||
|
auto title() const -> string;
|
||||||
|
|
||||||
auto manifest() -> string;
|
auto load() -> bool;
|
||||||
auto title() -> string;
|
auto save() -> void;
|
||||||
|
|
||||||
auto load() -> void;
|
|
||||||
auto unload() -> void;
|
auto unload() -> void;
|
||||||
|
|
||||||
auto serialize(serializer&) -> void;
|
auto serialize(serializer&) -> void;
|
||||||
|
@ -15,20 +15,14 @@ struct Cartridge {
|
||||||
MappedRAM rom;
|
MappedRAM rom;
|
||||||
MappedRAM ram;
|
MappedRAM ram;
|
||||||
|
|
||||||
struct Memory {
|
|
||||||
unsigned id;
|
|
||||||
string name;
|
|
||||||
};
|
|
||||||
vector<Memory> memory;
|
|
||||||
|
|
||||||
struct Information {
|
struct Information {
|
||||||
struct Markup {
|
struct Manifest {
|
||||||
string cartridge;
|
string cartridge;
|
||||||
string gameBoy;
|
string gameBoy;
|
||||||
string bsMemory;
|
string bsMemory;
|
||||||
string sufamiTurboA;
|
string sufamiTurboA;
|
||||||
string sufamiTurboB;
|
string sufamiTurboB;
|
||||||
} markup;
|
} manifest;
|
||||||
|
|
||||||
struct Title {
|
struct Title {
|
||||||
string cartridge;
|
string cartridge;
|
||||||
|
@ -39,62 +33,94 @@ struct Cartridge {
|
||||||
} title;
|
} title;
|
||||||
} information;
|
} information;
|
||||||
|
|
||||||
bool hasICD2;
|
struct Has {
|
||||||
bool hasMCC;
|
boolean ICD2;
|
||||||
bool hasNSSDIP;
|
boolean MCC;
|
||||||
bool hasEvent;
|
boolean NSSDIP;
|
||||||
bool hasSA1;
|
boolean Event;
|
||||||
bool hasSuperFX;
|
boolean SA1;
|
||||||
bool hasARMDSP;
|
boolean SuperFX;
|
||||||
bool hasHitachiDSP;
|
boolean ARMDSP;
|
||||||
bool hasNECDSP;
|
boolean HitachiDSP;
|
||||||
bool hasEpsonRTC;
|
boolean NECDSP;
|
||||||
bool hasSharpRTC;
|
boolean EpsonRTC;
|
||||||
bool hasSPC7110;
|
boolean SharpRTC;
|
||||||
bool hasSDD1;
|
boolean SPC7110;
|
||||||
bool hasOBC1;
|
boolean SDD1;
|
||||||
bool hasMSU1;
|
boolean OBC1;
|
||||||
|
boolean MSU1;
|
||||||
|
|
||||||
bool hasGameBoySlot;
|
boolean GameBoySlot;
|
||||||
bool hasBSMemorySlot;
|
boolean BSMemorySlot;
|
||||||
bool hasSufamiTurboSlots;
|
boolean SufamiTurboSlots;
|
||||||
|
} has;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//cartridge.cpp
|
||||||
auto loadGameBoy() -> void;
|
auto loadGameBoy() -> void;
|
||||||
auto loadBSMemory() -> void;
|
auto loadBSMemory() -> void;
|
||||||
auto loadSufamiTurboA() -> void;
|
auto loadSufamiTurboA() -> void;
|
||||||
auto loadSufamiTurboB() -> void;
|
auto loadSufamiTurboB() -> void;
|
||||||
friend class Interface;
|
|
||||||
friend class ICD2;
|
|
||||||
|
|
||||||
//markup.cpp
|
//load.cpp
|
||||||
auto parseMarkup(const string&) -> void;
|
auto loadCartridge(Markup::Node) -> void;
|
||||||
auto parseMarkupMap(Markup::Node, SuperFamicom::Memory&) -> void;
|
auto loadGameBoy(Markup::Node) -> void;
|
||||||
auto parseMarkupMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
|
auto loadBSMemory(Markup::Node) -> void;
|
||||||
auto parseMarkupMemory(MappedRAM&, Markup::Node, uint id, bool writable) -> void;
|
auto loadSufamiTurboA(Markup::Node) -> void;
|
||||||
|
auto loadSufamiTurboB(Markup::Node) -> void;
|
||||||
|
|
||||||
auto parseMarkupROM(Markup::Node) -> void;
|
auto loadROM(Markup::Node) -> void;
|
||||||
auto parseMarkupRAM(Markup::Node) -> void;
|
auto loadRAM(Markup::Node) -> void;
|
||||||
auto parseMarkupICD2(Markup::Node) -> void;
|
auto loadICD2(Markup::Node) -> void;
|
||||||
auto parseMarkupMCC(Markup::Node) -> void;
|
auto loadMCC(Markup::Node) -> void;
|
||||||
auto parseMarkupBSMemory(Markup::Node) -> void;
|
auto loadBSMemoryPack(Markup::Node) -> void;
|
||||||
auto parseMarkupSufamiTurbo(Markup::Node, bool slot) -> void;
|
auto loadSufamiTurbo(Markup::Node, bool slot) -> void;
|
||||||
auto parseMarkupNSS(Markup::Node) -> void;
|
auto loadNSS(Markup::Node) -> void;
|
||||||
auto parseMarkupEvent(Markup::Node) -> void;
|
auto loadEvent(Markup::Node) -> void;
|
||||||
auto parseMarkupSA1(Markup::Node) -> void;
|
auto loadSA1(Markup::Node) -> void;
|
||||||
auto parseMarkupSuperFX(Markup::Node) -> void;
|
auto loadSuperFX(Markup::Node) -> void;
|
||||||
auto parseMarkupARMDSP(Markup::Node) -> void;
|
auto loadARMDSP(Markup::Node) -> void;
|
||||||
auto parseMarkupHitachiDSP(Markup::Node, unsigned roms) -> void;
|
auto loadHitachiDSP(Markup::Node, uint roms) -> void;
|
||||||
auto parseMarkupNECDSP(Markup::Node) -> void;
|
auto loadNECDSP(Markup::Node) -> void;
|
||||||
auto parseMarkupEpsonRTC(Markup::Node) -> void;
|
auto loadEpsonRTC(Markup::Node) -> void;
|
||||||
auto parseMarkupSharpRTC(Markup::Node) -> void;
|
auto loadSharpRTC(Markup::Node) -> void;
|
||||||
auto parseMarkupSPC7110(Markup::Node) -> void;
|
auto loadSPC7110(Markup::Node) -> void;
|
||||||
auto parseMarkupSDD1(Markup::Node) -> void;
|
auto loadSDD1(Markup::Node) -> void;
|
||||||
auto parseMarkupOBC1(Markup::Node) -> void;
|
auto loadOBC1(Markup::Node) -> void;
|
||||||
auto parseMarkupMSU1(Markup::Node) -> void;
|
auto loadMSU1(Markup::Node) -> void;
|
||||||
|
|
||||||
|
auto loadMemory(MappedRAM&, Markup::Node, bool writable, uint id = 1) -> void;
|
||||||
|
auto loadMap(Markup::Node, SuperFamicom::Memory&) -> void;
|
||||||
|
auto loadMap(Markup::Node, const function<uint8 (uint24, uint8)>&, const function<void (uint24, uint8)>&) -> void;
|
||||||
|
|
||||||
|
//save.cpp
|
||||||
|
auto saveCartridge(Markup::Node) -> void;
|
||||||
|
auto saveGameBoy(Markup::Node) -> void;
|
||||||
|
auto saveBSMemory(Markup::Node) -> void;
|
||||||
|
auto saveSufamiTurboA(Markup::Node) -> void;
|
||||||
|
auto saveSufamiTurboB(Markup::Node) -> void;
|
||||||
|
|
||||||
|
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 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, uint = 1) -> void;
|
||||||
|
|
||||||
string _sha256;
|
string _sha256;
|
||||||
Region _region = Region::NTSC;
|
Region _region = Region::NTSC;
|
||||||
|
|
||||||
|
friend class Interface;
|
||||||
|
friend class ICD2;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Cartridge cartridge;
|
extern Cartridge cartridge;
|
||||||
|
|
|
@ -0,0 +1,334 @@
|
||||||
|
auto Cartridge::loadCartridge(Markup::Node node) -> void {
|
||||||
|
information.title.cartridge = node["information/title"].text();
|
||||||
|
auto board = node["board"];
|
||||||
|
_region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if(board["mcc"] || board["bsmemory"]) interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false);
|
||||||
|
if(board["sufamiturbo"]) interface->loadRequest(ID::SufamiTurboA, "Sufami Turbo", "st", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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"], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
|
||||||
|
information.title.sufamiTurboA = node["information/title"].text();
|
||||||
|
|
||||||
|
loadMemory(sufamiturboA.rom, node["rom"], ID::SufamiTurboA);
|
||||||
|
loadMemory(sufamiturboA.ram, node["ram"], ID::SufamiTurboA);
|
||||||
|
|
||||||
|
if(node["board/linkable"]) interface->loadRequest(ID::SufamiTurboB, "Sufami Turbo", "st", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
|
||||||
|
information.title.sufamiTurboB = node["information/title"].text();
|
||||||
|
|
||||||
|
loadMemory(sufamiturboB.rom, node["rom"], ID::SufamiTurboB);
|
||||||
|
loadMemory(sufamiturboB.ram, node["ram"], ID::SufamiTurboB);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
auto Cartridge::loadROM(Markup::Node root) -> void {
|
||||||
|
loadMemory(rom, root, false);
|
||||||
|
for(auto node : root.find("map")) loadMap(node, rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadRAM(Markup::Node root) -> void {
|
||||||
|
loadMemory(ram, root, true);
|
||||||
|
for(auto node : root.find("map")) loadMap(node, ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadICD2(Markup::Node root) -> void {
|
||||||
|
has.GameBoySlot = true;
|
||||||
|
has.ICD2 = true;
|
||||||
|
icd2.revision = max(1, root["revision"].natural());
|
||||||
|
|
||||||
|
//Game Boy core loads data through ICD2 interface
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadMCC(Markup::Node root) -> void {
|
||||||
|
has.BSMemorySlot = true;
|
||||||
|
has.MCC = true;
|
||||||
|
|
||||||
|
loadMemory(mcc.rom, root["rom"], false);
|
||||||
|
loadMemory(mcc.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) node.text() == "mcu"
|
||||||
|
? loadMap(node, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc})
|
||||||
|
: loadMap(node, {&MCC::read, &mcc}, {&MCC::write, &mcc});
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, mcc.ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadBSMemoryPack(Markup::Node root) -> void {
|
||||||
|
has.BSMemorySlot = true;
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) {
|
||||||
|
if(bsmemory.memory.size() == 0) continue;
|
||||||
|
loadMap(node, bsmemory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSufamiTurbo(Markup::Node root, bool slot) -> void {
|
||||||
|
has.SufamiTurboSlots = true;
|
||||||
|
|
||||||
|
for(auto node : root["rom"].find("map")) {
|
||||||
|
auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
||||||
|
if(cart.rom.size() == 0) continue;
|
||||||
|
loadMap(node, cart.rom);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root["ram"].find("map")) {
|
||||||
|
auto& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
||||||
|
if(cart.ram.size() == 0) continue;
|
||||||
|
loadMap(node, cart.ram);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadNSS(Markup::Node root) -> void {
|
||||||
|
has.NSSDIP = true;
|
||||||
|
nss.dip = interface->dipSettings(root);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&NSS::read, &nss}, {&NSS::write, &nss});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadEvent(Markup::Node root) -> void {
|
||||||
|
auto roms = root.find("rom");
|
||||||
|
if(roms.size() != 4) return;
|
||||||
|
|
||||||
|
has.Event = true;
|
||||||
|
|
||||||
|
for(uint n : range(4)) loadMemory(event.rom[n], roms[n], false);
|
||||||
|
loadMemory(event.ram, root["ram"], true);
|
||||||
|
|
||||||
|
event.board = Event::Board::CampusChallenge92;
|
||||||
|
if(root.text() == "CC92") event.board = Event::Board::CampusChallenge92;
|
||||||
|
if(root.text() == "PF94") event.board = Event::Board::Powerfest94;
|
||||||
|
event.timer = root["timer"].natural();
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) node.text() == "mcu"
|
||||||
|
? loadMap(node, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event})
|
||||||
|
: loadMap(node, {&Event::read, &event}, {&Event::write, &event});
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, event.ram);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSA1(Markup::Node root) -> void {
|
||||||
|
has.SA1 = true;
|
||||||
|
|
||||||
|
loadMemory(sa1.rom, root["rom"], false);
|
||||||
|
loadMemory(sa1.bwram, root["bwram"], true);
|
||||||
|
loadMemory(sa1.iram, root["iram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1});
|
||||||
|
for(auto node : root["rom"].find("map")) loadMap(node, {&SA1::mmcromRead, &sa1}, {&SA1::mmcromWrite, &sa1});
|
||||||
|
for(auto node : root["bwram"].find("map")) loadMap(node, {&SA1::mmcbwramRead, &sa1}, {&SA1::mmcbwramWrite, &sa1});
|
||||||
|
for(auto node : root["iram"].find("map")) loadMap(node, sa1.cpuiram);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSuperFX(Markup::Node root) -> void {
|
||||||
|
has.SuperFX = true;
|
||||||
|
|
||||||
|
loadMemory(superfx.rom, root["rom"], false);
|
||||||
|
loadMemory(superfx.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx});
|
||||||
|
for(auto node : root["rom"].find("map")) loadMap(node, superfx.cpurom);
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, superfx.cpuram);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadARMDSP(Markup::Node root) -> void {
|
||||||
|
has.ARMDSP = true;
|
||||||
|
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, root["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, root["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, root["ram"]["name"].text(), File::Read)) {
|
||||||
|
for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read();
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadHitachiDSP(Markup::Node root, uint roms) -> void {
|
||||||
|
has.HitachiDSP = true;
|
||||||
|
|
||||||
|
hitachidsp.Frequency = root["frequency"].natural();
|
||||||
|
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
||||||
|
hitachidsp.Roms = roms; //1 or 2
|
||||||
|
|
||||||
|
loadMemory(hitachidsp.rom, root["rom"], false);
|
||||||
|
loadMemory(hitachidsp.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
||||||
|
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
||||||
|
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, root["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, root["dram"]["name"].text(), File::Read)) {
|
||||||
|
for(auto n : range(3 * 1024)) hitachidsp.dataRAM[n] = fp->readl(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp});
|
||||||
|
for(auto node : root["rom"].find("map")) loadMap(node, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp});
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, {&HitachiDSP::ramRead, &hitachidsp}, {&HitachiDSP::ramWrite, &hitachidsp});
|
||||||
|
for(auto node : root["dram"].find("map")) loadMap(node, {&HitachiDSP::dramRead, &hitachidsp}, {&HitachiDSP::dramWrite, &hitachidsp});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadNECDSP(Markup::Node root) -> void {
|
||||||
|
has.NECDSP = true;
|
||||||
|
|
||||||
|
necdsp.frequency = root["frequency"].natural();
|
||||||
|
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
||||||
|
necdsp.revision
|
||||||
|
= root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
|
||||||
|
: root["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, root["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, root["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, root["dram"]["name"].text(), File::Read)) {
|
||||||
|
for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
||||||
|
for(auto node : root["dram"].find("map")) loadMap(node, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadEpsonRTC(Markup::Node root) -> void {
|
||||||
|
has.EpsonRTC = true;
|
||||||
|
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, root["ram"]["name"].text(), File::Read)) {
|
||||||
|
uint8 data[16] = {0};
|
||||||
|
for(auto& byte : data) fp->read();
|
||||||
|
epsonrtc.load(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSharpRTC(Markup::Node root) -> void {
|
||||||
|
has.SharpRTC = true;
|
||||||
|
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, root["ram"]["name"].text(), File::Read)) {
|
||||||
|
uint8 data[16] = {0};
|
||||||
|
for(auto& byte : data) fp->read();
|
||||||
|
sharprtc.load(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSPC7110(Markup::Node root) -> void {
|
||||||
|
has.SPC7110 = true;
|
||||||
|
|
||||||
|
loadMemory(spc7110.prom, root["prom"], false);
|
||||||
|
loadMemory(spc7110.drom, root["drom"], false);
|
||||||
|
loadMemory(spc7110.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) node.text() == "mcu"
|
||||||
|
? loadMap(node, {&SPC7110::mcuromRead, &spc7110}, {&SPC7110::mcuromWrite, &spc7110})
|
||||||
|
: loadMap(node, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, {&SPC7110::mcuramRead, &spc7110}, {&SPC7110::mcuramWrite, &spc7110});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadSDD1(Markup::Node root) -> void {
|
||||||
|
has.SDD1 = true;
|
||||||
|
|
||||||
|
loadMemory(sdd1.rom, root["rom"], false);
|
||||||
|
loadMemory(sdd1.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
|
||||||
|
for(auto node : root["rom"].find("map")) loadMap(node, {&SDD1::mcuromRead, &sdd1}, {&SDD1::mcuromWrite, &sdd1});
|
||||||
|
for(auto node : root["ram"].find("map")) loadMap(node, {&SDD1::mcuramRead, &sdd1}, {&SDD1::mcuramWrite, &sdd1});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadOBC1(Markup::Node root) -> void {
|
||||||
|
has.OBC1 = true;
|
||||||
|
|
||||||
|
loadMemory(obc1.ram, root["ram"], true);
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&OBC1::read, &obc1}, {&OBC1::write, &obc1});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::loadMSU1(Markup::Node root) -> void {
|
||||||
|
has.MSU1 = true;
|
||||||
|
|
||||||
|
for(auto node : root.find("map")) loadMap(node, {&MSU1::read, &msu1}, {&MSU1::write, &msu1});
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool writable, uint id) -> void {
|
||||||
|
auto name = node["name"].text();
|
||||||
|
auto size = node["size"].natural();
|
||||||
|
ram.allocate(size);
|
||||||
|
if(auto fp = interface->open(id, name, File::Read, !writable)) { //treat ROM as required; RAM as optional
|
||||||
|
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<uint8 (uint24, uint8)>& reader,
|
||||||
|
const function<void (uint24, uint8)>& 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);
|
||||||
|
}
|
|
@ -1,385 +0,0 @@
|
||||||
auto Cartridge::parseMarkup(const string& markup) -> void {
|
|
||||||
auto document = BML::unserialize(markup);
|
|
||||||
auto information = document["information"];
|
|
||||||
auto board = document["board"];
|
|
||||||
|
|
||||||
this->information.title.cartridge = information["title"].text();
|
|
||||||
_region = board["region"].text() == "pal" ? Region::PAL : Region::NTSC;
|
|
||||||
|
|
||||||
if(auto node = board["rom"]) parseMarkupROM(node);
|
|
||||||
if(auto node = board["ram"]) parseMarkupRAM(node);
|
|
||||||
if(auto node = board["icd2"]) parseMarkupICD2(node);
|
|
||||||
if(auto node = board["mcc"]) parseMarkupMCC(node);
|
|
||||||
if(auto node = board["bsmemory"]) parseMarkupBSMemory(node);
|
|
||||||
if(auto node = board.find("sufamiturbo")) if(node(0)) parseMarkupSufamiTurbo(node(0), 0);
|
|
||||||
if(auto node = board.find("sufamiturbo")) if(node(1)) parseMarkupSufamiTurbo(node(1), 1);
|
|
||||||
if(auto node = board["nss"]) parseMarkupNSS(node);
|
|
||||||
if(auto node = board["event"]) parseMarkupEvent(node);
|
|
||||||
if(auto node = board["sa1"]) parseMarkupSA1(node);
|
|
||||||
if(auto node = board["superfx"]) parseMarkupSuperFX(node);
|
|
||||||
if(auto node = board["armdsp"]) parseMarkupARMDSP(node);
|
|
||||||
if(auto node = board["hitachidsp"]) parseMarkupHitachiDSP(node, document["information/board"].text().match("2DC*") ? 2 : 1);
|
|
||||||
if(auto node = board["necdsp"]) parseMarkupNECDSP(node);
|
|
||||||
if(auto node = board["epsonrtc"]) parseMarkupEpsonRTC(node);
|
|
||||||
if(auto node = board["sharprtc"]) parseMarkupSharpRTC(node);
|
|
||||||
if(auto node = board["spc7110"]) parseMarkupSPC7110(node);
|
|
||||||
if(auto node = board["sdd1"]) parseMarkupSDD1(node);
|
|
||||||
if(auto node = board["obc1"]) parseMarkupOBC1(node);
|
|
||||||
if(auto node = board["msu1"]) parseMarkupMSU1(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMap(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::parseMarkupMap(
|
|
||||||
Markup::Node map,
|
|
||||||
const function<uint8 (uint24, uint8)>& reader,
|
|
||||||
const function<void (uint24, uint8)>& 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMemory(MappedRAM& ram, Markup::Node node, uint id, bool writable) -> void {
|
|
||||||
string name = node["name"].text();
|
|
||||||
uint size = node["size"].natural();
|
|
||||||
bool save = !(bool)node["volatile"];
|
|
||||||
ram.map(allocate<uint8>(size, 0xff), size);
|
|
||||||
if(name) {
|
|
||||||
interface->loadRequest(id, name, !writable); //treat ROM as required; RAM as optional
|
|
||||||
if(writable && save) memory.append({id, name});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupROM(Markup::Node root) -> void {
|
|
||||||
parseMarkupMemory(rom, root, ID::ROM, false);
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, rom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupRAM(Markup::Node root) -> void {
|
|
||||||
parseMarkupMemory(ram, root, ID::RAM, true);
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupICD2(Markup::Node root) -> void {
|
|
||||||
hasGameBoySlot = true;
|
|
||||||
hasICD2 = true;
|
|
||||||
icd2.revision = max(1, root["revision"].natural());
|
|
||||||
|
|
||||||
//Game Boy core loads data through ICD2 interface
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&ICD2::read, &icd2}, {&ICD2::write, &icd2});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMCC(Markup::Node root) -> void {
|
|
||||||
hasBSMemorySlot = true;
|
|
||||||
hasMCC = true;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false);
|
|
||||||
|
|
||||||
parseMarkupMemory(mcc.rom, root["rom"], ID::MCCROM, false);
|
|
||||||
parseMarkupMemory(mcc.ram, root["ram"], ID::MCCRAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
if(node.text() == "mcu") {
|
|
||||||
parseMarkupMap(node, {&MCC::mcuRead, &mcc}, {&MCC::mcuWrite, &mcc});
|
|
||||||
} else {
|
|
||||||
parseMarkupMap(node, {&MCC::read, &mcc}, {&MCC::write, &mcc});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, mcc.ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupBSMemory(Markup::Node root) -> void {
|
|
||||||
hasBSMemorySlot = true;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::BSMemory, "BS Memory", "bs", false);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
if(bsmemory.memory.size() == 0) continue;
|
|
||||||
parseMarkupMap(node, bsmemory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSufamiTurbo(Markup::Node root, bool slot) -> void {
|
|
||||||
hasSufamiTurboSlots = true;
|
|
||||||
|
|
||||||
if(slot == 0) {
|
|
||||||
//load required slot A (will request slot B if slot A cartridge is linkable)
|
|
||||||
interface->loadRequest(ID::SufamiTurboSlotA, "Sufami Turbo", "st", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["rom"].find("map")) {
|
|
||||||
SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
|
||||||
if(cart.rom.size() == 0) continue;
|
|
||||||
parseMarkupMap(node, cart.rom);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB);
|
|
||||||
if(cart.ram.size() == 0) continue;
|
|
||||||
parseMarkupMap(node, cart.ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupNSS(Markup::Node root) -> void {
|
|
||||||
hasNSSDIP = true;
|
|
||||||
nss.dip = interface->dipSettings(root);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&NSS::read, &nss}, {&NSS::write, &nss});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupEvent(Markup::Node root) -> void {
|
|
||||||
auto roms = root.find("rom");
|
|
||||||
if(roms.size() != 4) return;
|
|
||||||
|
|
||||||
hasEvent = true;
|
|
||||||
|
|
||||||
for(uint n : range(4)) {
|
|
||||||
parseMarkupMemory(event.rom[n], roms[n], ID::EventROM0 + n, false);
|
|
||||||
}
|
|
||||||
parseMarkupMemory(event.ram, root["ram"], ID::EventRAM, true);
|
|
||||||
|
|
||||||
event.board = Event::Board::CampusChallenge92;
|
|
||||||
if(root.text() == "CC92") event.board = Event::Board::CampusChallenge92;
|
|
||||||
if(root.text() == "PF94") event.board = Event::Board::Powerfest94;
|
|
||||||
event.timer = root["timer"].natural();
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
if(node.text() == "mcu") {
|
|
||||||
parseMarkupMap(node, {&Event::mcuRead, &event}, {&Event::mcuWrite, &event});
|
|
||||||
} else {
|
|
||||||
parseMarkupMap(node, {&Event::read, &event}, {&Event::write, &event});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, event.ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSA1(Markup::Node root) -> void {
|
|
||||||
hasSA1 = true;
|
|
||||||
|
|
||||||
parseMarkupMemory(sa1.rom, root["rom"], ID::SA1ROM, false);
|
|
||||||
parseMarkupMemory(sa1.bwram, root["bwram"], ID::SA1BWRAM, true);
|
|
||||||
parseMarkupMemory(sa1.iram, root["iram"], ID::SA1IRAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&SA1::readIO, &sa1}, {&SA1::writeIO, &sa1});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["rom"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&SA1::mmcromRead, &sa1}, {&SA1::mmcromWrite, &sa1});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["bwram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&SA1::mmcbwramRead, &sa1}, {&SA1::mmcbwramWrite, &sa1});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["iram"].find("map")) {
|
|
||||||
parseMarkupMap(node, sa1.cpuiram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSuperFX(Markup::Node root) -> void {
|
|
||||||
hasSuperFX = true;
|
|
||||||
|
|
||||||
parseMarkupMemory(superfx.rom, root["rom"], ID::SuperFXROM, false);
|
|
||||||
parseMarkupMemory(superfx.ram, root["ram"], ID::SuperFXRAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&SuperFX::readIO, &superfx}, {&SuperFX::writeIO, &superfx});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["rom"].find("map")) {
|
|
||||||
parseMarkupMap(node, superfx.cpurom);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, superfx.cpuram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupARMDSP(Markup::Node root) -> void {
|
|
||||||
hasARMDSP = true;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::ArmDSPPROM, root["prom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::ArmDSPDROM, root["drom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::ArmDSPRAM, root["dram"]["name"].text(), false);
|
|
||||||
memory.append({ID::ArmDSPRAM, root["dram"]["name"].text()});
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupHitachiDSP(Markup::Node root, uint roms) -> void {
|
|
||||||
hasHitachiDSP = true;
|
|
||||||
|
|
||||||
hitachidsp.Frequency = root["frequency"].natural();
|
|
||||||
if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000;
|
|
||||||
hitachidsp.Roms = roms; //1 or 2
|
|
||||||
|
|
||||||
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
|
||||||
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::HitachiDSPDROM, root["drom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::HitachiDSPDRAM, root["dram"]["name"].text(), false);
|
|
||||||
|
|
||||||
parseMarkupMemory(hitachidsp.rom, root["rom"], ID::HitachiDSPROM, false);
|
|
||||||
parseMarkupMemory(hitachidsp.ram, root["ram"], ID::HitachiDSPRAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["rom"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&HitachiDSP::ramRead, &hitachidsp}, {&HitachiDSP::ramWrite, &hitachidsp});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["dram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&HitachiDSP::dramRead, &hitachidsp}, {&HitachiDSP::dramWrite, &hitachidsp});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupNECDSP(Markup::Node root) -> void {
|
|
||||||
hasNECDSP = true;
|
|
||||||
|
|
||||||
necdsp.frequency = root["frequency"].natural();
|
|
||||||
if(necdsp.frequency == 0) necdsp.frequency = 8000000;
|
|
||||||
necdsp.revision
|
|
||||||
= root["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
|
|
||||||
: root["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;
|
|
||||||
|
|
||||||
if(necdsp.revision == NECDSP::Revision::uPD7725) {
|
|
||||||
interface->loadRequest(ID::Nec7725DSPPROM, root["prom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::Nec7725DSPDROM, root["drom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::Nec7725DSPRAM, root["dram"]["name"].text(), false);
|
|
||||||
memory.append({ID::Nec7725DSPRAM, root["dram"]["name"].text()});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(necdsp.revision == NECDSP::Revision::uPD96050) {
|
|
||||||
interface->loadRequest(ID::Nec96050DSPPROM, root["prom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::Nec96050DSPDROM, root["drom"]["name"].text(), true);
|
|
||||||
interface->loadRequest(ID::Nec96050DSPRAM, root["dram"]["name"].text(), false);
|
|
||||||
memory.append({ID::Nec96050DSPRAM, root["dram"]["name"].text()});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["dram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupEpsonRTC(Markup::Node root) -> void {
|
|
||||||
hasEpsonRTC = true;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::EpsonRTC, root["ram"]["name"].text(), false);
|
|
||||||
memory.append({ID::EpsonRTC, root["ram"]["name"].text()});
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSharpRTC(Markup::Node root) -> void {
|
|
||||||
hasSharpRTC = true;
|
|
||||||
|
|
||||||
interface->loadRequest(ID::SharpRTC, root["ram"]["name"].text(), false);
|
|
||||||
memory.append({ID::SharpRTC, root["ram"]["name"].text()});
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSPC7110(Markup::Node root) -> void {
|
|
||||||
hasSPC7110 = true;
|
|
||||||
|
|
||||||
parseMarkupMemory(spc7110.prom, root["prom"], ID::SPC7110PROM, false);
|
|
||||||
parseMarkupMemory(spc7110.drom, root["drom"], ID::SPC7110DROM, false);
|
|
||||||
parseMarkupMemory(spc7110.ram, root["ram"], ID::SPC7110RAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
if(node.text() == "mcu") {
|
|
||||||
parseMarkupMap(node, {&SPC7110::mcuromRead, &spc7110}, {&SPC7110::mcuromWrite, &spc7110});
|
|
||||||
} else {
|
|
||||||
parseMarkupMap(node, {&SPC7110::read, &spc7110}, {&SPC7110::write, &spc7110});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&SPC7110::mcuramRead, &spc7110}, {&SPC7110::mcuramWrite, &spc7110});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupSDD1(Markup::Node root) -> void {
|
|
||||||
hasSDD1 = true;
|
|
||||||
|
|
||||||
parseMarkupMemory(sdd1.rom, root["rom"], ID::SDD1ROM, false);
|
|
||||||
parseMarkupMemory(sdd1.ram, root["ram"], ID::SDD1RAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&SDD1::read, &sdd1}, {&SDD1::write, &sdd1});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["rom"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&SDD1::mcuromRead, &sdd1}, {&SDD1::mcuromWrite, &sdd1});
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto node : root["ram"].find("map")) {
|
|
||||||
parseMarkupMap(node, {&SDD1::mcuramRead, &sdd1}, {&SDD1::mcuramWrite, &sdd1});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupOBC1(Markup::Node root) -> void {
|
|
||||||
hasOBC1 = true;
|
|
||||||
|
|
||||||
parseMarkupMemory(obc1.ram, root["ram"], ID::OBC1RAM, true);
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&OBC1::read, &obc1}, {&OBC1::write, &obc1});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto Cartridge::parseMarkupMSU1(Markup::Node root) -> void {
|
|
||||||
hasMSU1 = true;
|
|
||||||
|
|
||||||
for(auto node : root.find("map")) {
|
|
||||||
parseMarkupMap(node, {&MSU1::read, &msu1}, {&MSU1::write, &msu1});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,123 @@
|
||||||
|
auto Cartridge::saveCartridge(Markup::Node node) -> void {
|
||||||
|
auto board = node["board"];
|
||||||
|
|
||||||
|
if(auto node = board["ram"]) saveRAM(node);
|
||||||
|
if(auto node = board["mcc"]) saveMCC(node);
|
||||||
|
if(auto node = board["event"]) saveEvent(node);
|
||||||
|
if(auto node = board["sa1"]) saveSA1(node);
|
||||||
|
if(auto node = board["superfx"]) saveSuperFX(node);
|
||||||
|
if(auto node = board["armdsp"]) saveARMDSP(node);
|
||||||
|
if(auto node = board["hitachidsp"]) saveHitachiDSP(node);
|
||||||
|
if(auto node = board["necdsp"]) saveNECDSP(node);
|
||||||
|
if(auto node = board["epsonrtc"]) saveEpsonRTC(node);
|
||||||
|
if(auto node = board["sharprtc"]) saveSharpRTC(node);
|
||||||
|
if(auto node = board["spc7110"]) saveSPC7110(node);
|
||||||
|
if(auto node = board["sdd1"]) saveSDD1(node);
|
||||||
|
if(auto node = board["obc1"]) saveOBC1(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveGameBoy(Markup::Node node) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveBSMemory(Markup::Node node) -> void {
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void {
|
||||||
|
saveMemory(sufamiturboA.ram, node["board/ram"], ID::SufamiTurboA);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void {
|
||||||
|
saveMemory(sufamiturboB.ram, node["board/ram"], ID::SufamiTurboB);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
auto Cartridge::saveRAM(Markup::Node node) -> void {
|
||||||
|
saveMemory(ram, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveMCC(Markup::Node node) -> void {
|
||||||
|
saveMemory(mcc.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveEvent(Markup::Node node) -> void {
|
||||||
|
saveMemory(event.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSA1(Markup::Node node) -> void {
|
||||||
|
saveMemory(sa1.bwram, node["bwram"]);
|
||||||
|
saveMemory(sa1.iram, node["iram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSuperFX(Markup::Node node) -> void {
|
||||||
|
saveMemory(superfx.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveARMDSP(Markup::Node node) -> void {
|
||||||
|
if(auto name = node["ram"]["name"].text()) {
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) {
|
||||||
|
for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
|
||||||
|
saveMemory(hitachidsp.ram, node["ram"]);
|
||||||
|
if(auto name = node["dram"]["name"].text()) {
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) {
|
||||||
|
for(auto n : range(3 * 1024)) fp->write(hitachidsp.dataRAM[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveNECDSP(Markup::Node node) -> void {
|
||||||
|
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048;
|
||||||
|
if(auto name = node["dram"]["name"].text()) {
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) {
|
||||||
|
for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
|
||||||
|
if(auto name = node["ram"]["name"].text()) {
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) {
|
||||||
|
uint8 data[16] = {0};
|
||||||
|
epsonrtc.save(data);
|
||||||
|
fp->write(data, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSharpRTC(Markup::Node node) -> void {
|
||||||
|
if(auto name = node["ram"]["name"].text()) {
|
||||||
|
if(auto fp = interface->open(ID::SuperFamicom, name, File::Write)) {
|
||||||
|
uint8 data[16] = {0};
|
||||||
|
sharprtc.save(data);
|
||||||
|
fp->write(data, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSPC7110(Markup::Node node) -> void {
|
||||||
|
saveMemory(spc7110.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveSDD1(Markup::Node node) -> void {
|
||||||
|
saveMemory(sdd1.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Cartridge::saveOBC1(Markup::Node node) -> void {
|
||||||
|
saveMemory(obc1.ram, node["ram"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
auto Cartridge::saveMemory(MappedRAM& memory, Markup::Node node, uint id) -> void {
|
||||||
|
if(!node || node["volatile"]) return;
|
||||||
|
auto name = node["name"].text();
|
||||||
|
auto size = node["size"].natural();
|
||||||
|
if(auto fp = interface->open(id, name, File::Write)) {
|
||||||
|
fp->write(memory.data(), memory.size());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
auto ArmDSP::firmware() const -> nall::vector<uint8> {
|
auto ArmDSP::firmware() const -> nall::vector<uint8> {
|
||||||
nall::vector<uint8> buffer;
|
nall::vector<uint8> buffer;
|
||||||
if(!cartridge.hasARMDSP) return buffer;
|
if(!cartridge.has.ARMDSP) return buffer;
|
||||||
buffer.reserve(128 * 1024 + 32 * 1024);
|
buffer.reserve(128 * 1024 + 32 * 1024);
|
||||||
for(auto n : range(128 * 1024)) buffer.append(programROM[n]);
|
for(auto n : range(128 * 1024)) buffer.append(programROM[n]);
|
||||||
for(auto n : range( 32 * 1024)) buffer.append(dataROM[n]);
|
for(auto n : range( 32 * 1024)) buffer.append(dataROM[n]);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
auto HitachiDSP::firmware() const -> vector<uint8> {
|
auto HitachiDSP::firmware() const -> vector<uint8> {
|
||||||
vector<uint8> buffer;
|
vector<uint8> buffer;
|
||||||
if(!cartridge.hasHitachiDSP) return buffer;
|
if(!cartridge.has.HitachiDSP) return buffer;
|
||||||
buffer.reserve(1024 * 3);
|
buffer.reserve(1024 * 3);
|
||||||
for(auto n : range(1024)) {
|
for(auto n : range(1024)) {
|
||||||
buffer.append(dataROM[n] >> 0);
|
buffer.append(dataROM[n] >> 0);
|
||||||
|
|
|
@ -85,7 +85,7 @@ auto MSU1::reset() -> void {
|
||||||
|
|
||||||
auto MSU1::dataOpen() -> void {
|
auto MSU1::dataOpen() -> void {
|
||||||
if(dataFile.open()) dataFile.close();
|
if(dataFile.open()) dataFile.close();
|
||||||
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
auto document = BML::unserialize(cartridge.information.manifest.cartridge);
|
||||||
string name = document["board/msu1/rom/name"].text();
|
string name = document["board/msu1/rom/name"].text();
|
||||||
if(!name) name = "msu1.rom";
|
if(!name) name = "msu1.rom";
|
||||||
if(dataFile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
|
if(dataFile.open({interface->path(ID::SuperFamicom), name}, file::mode::read)) {
|
||||||
|
@ -95,7 +95,7 @@ auto MSU1::dataOpen() -> void {
|
||||||
|
|
||||||
auto MSU1::audioOpen() -> void {
|
auto MSU1::audioOpen() -> void {
|
||||||
if(audioFile.open()) audioFile.close();
|
if(audioFile.open()) audioFile.close();
|
||||||
auto document = BML::unserialize(cartridge.information.markup.cartridge);
|
auto document = BML::unserialize(cartridge.information.manifest.cartridge);
|
||||||
string name = {"track-", mmio.audioTrack, ".pcm"};
|
string name = {"track-", mmio.audioTrack, ".pcm"};
|
||||||
for(auto track : document.find("board/msu1/track")) {
|
for(auto track : document.find("board/msu1/track")) {
|
||||||
if(track["number"].natural() != mmio.audioTrack) continue;
|
if(track["number"].natural() != mmio.audioTrack) continue;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
auto NECDSP::firmware() const -> vector<uint8> {
|
auto NECDSP::firmware() const -> vector<uint8> {
|
||||||
vector<uint8> buffer;
|
vector<uint8> buffer;
|
||||||
if(!cartridge.hasNECDSP) return buffer;
|
if(!cartridge.has.NECDSP) return buffer;
|
||||||
uint plength = 2048, dlength = 1024;
|
uint plength = 2048, dlength = 1024;
|
||||||
if(revision == Revision::uPD96050) plength = 16384, dlength = 2048;
|
if(revision == Revision::uPD96050) plength = 16384, dlength = 2048;
|
||||||
buffer.reserve(plength * 3 + dlength * 2);
|
buffer.reserve(plength * 3 + dlength * 2);
|
||||||
|
|
|
@ -183,175 +183,33 @@ auto Interface::sha256() -> string {
|
||||||
return cartridge.sha256();
|
return cartridge.sha256();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//deprecated
|
||||||
auto Interface::group(uint id) -> uint {
|
auto Interface::group(uint id) -> uint {
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case ID::SystemManifest:
|
|
||||||
case ID::IPLROM:
|
|
||||||
return 0;
|
|
||||||
case ID::Manifest:
|
|
||||||
case ID::ROM:
|
|
||||||
case ID::RAM:
|
|
||||||
case ID::EventROM0:
|
|
||||||
case ID::EventROM1:
|
|
||||||
case ID::EventROM2:
|
|
||||||
case ID::EventROM3:
|
|
||||||
case ID::EventRAM:
|
|
||||||
case ID::SA1ROM:
|
|
||||||
case ID::SA1IRAM:
|
|
||||||
case ID::SA1BWRAM:
|
|
||||||
case ID::SuperFXROM:
|
|
||||||
case ID::SuperFXRAM:
|
|
||||||
case ID::ArmDSPPROM:
|
|
||||||
case ID::ArmDSPDROM:
|
|
||||||
case ID::ArmDSPRAM:
|
|
||||||
case ID::HitachiDSPROM:
|
|
||||||
case ID::HitachiDSPRAM:
|
|
||||||
case ID::HitachiDSPDROM:
|
|
||||||
case ID::HitachiDSPDRAM:
|
|
||||||
case ID::Nec7725DSPPROM:
|
|
||||||
case ID::Nec7725DSPDROM:
|
|
||||||
case ID::Nec7725DSPRAM:
|
|
||||||
case ID::Nec96050DSPPROM:
|
|
||||||
case ID::Nec96050DSPDROM:
|
|
||||||
case ID::Nec96050DSPRAM:
|
|
||||||
case ID::EpsonRTC:
|
|
||||||
case ID::SharpRTC:
|
|
||||||
case ID::SPC7110PROM:
|
|
||||||
case ID::SPC7110DROM:
|
|
||||||
case ID::SPC7110RAM:
|
|
||||||
case ID::SDD1ROM:
|
|
||||||
case ID::SDD1RAM:
|
|
||||||
case ID::OBC1RAM:
|
|
||||||
case ID::SuperGameBoyManifest:
|
case ID::SuperGameBoyManifest:
|
||||||
case ID::SuperGameBoyBootROM:
|
case ID::SuperGameBoyBootROM:
|
||||||
case ID::MCCROM:
|
|
||||||
case ID::MCCRAM:
|
|
||||||
return 1;
|
return 1;
|
||||||
case ID::GameBoy:
|
|
||||||
case ID::GameBoyManifest:
|
case ID::GameBoyManifest:
|
||||||
case ID::GameBoyROM:
|
case ID::GameBoyROM:
|
||||||
case ID::GameBoyRAM:
|
case ID::GameBoyRAM:
|
||||||
return 2;
|
return 2;
|
||||||
case ID::BSMemory:
|
|
||||||
case ID::BSMemoryManifest:
|
|
||||||
case ID::BSMemoryROM:
|
|
||||||
return 3;
|
|
||||||
case ID::SufamiTurboSlotA:
|
|
||||||
case ID::SufamiTurboSlotAManifest:
|
|
||||||
case ID::SufamiTurboSlotAROM:
|
|
||||||
case ID::SufamiTurboSlotARAM:
|
|
||||||
return 4;
|
|
||||||
case ID::SufamiTurboSlotB:
|
|
||||||
case ID::SufamiTurboSlotBManifest:
|
|
||||||
case ID::SufamiTurboSlotBROM:
|
|
||||||
case ID::SufamiTurboSlotBRAM:
|
|
||||||
return 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::load(uint id) -> void {
|
auto Interface::load(uint id) -> void {
|
||||||
if(id == ID::SuperFamicom) system.load();
|
if(id == ID::SuperFamicom) system.load();
|
||||||
if(id == ID::BSMemory) cartridge.loadBSMemory();
|
if(id == ID::BSMemory) cartridge.loadBSMemory();
|
||||||
if(id == ID::SufamiTurboSlotA) cartridge.loadSufamiTurboA();
|
if(id == ID::SufamiTurboA) cartridge.loadSufamiTurboA();
|
||||||
if(id == ID::SufamiTurboSlotB) cartridge.loadSufamiTurboB();
|
if(id == ID::SufamiTurboB) cartridge.loadSufamiTurboB();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::save() -> void {
|
auto Interface::save() -> void {
|
||||||
for(auto& memory : cartridge.memory) {
|
system.save();
|
||||||
saveRequest(memory.id, memory.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//deprecated
|
||||||
auto Interface::load(uint id, const stream& stream) -> void {
|
auto Interface::load(uint id, const stream& stream) -> void {
|
||||||
if(id == ID::SystemManifest) {
|
|
||||||
system.information.manifest = stream.text();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::IPLROM) {
|
|
||||||
stream.read((uint8_t*)smp.iplrom, min(64u, stream.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::Manifest) cartridge.information.markup.cartridge = stream.text();
|
|
||||||
if(id == ID::ROM) cartridge.rom.read(stream);
|
|
||||||
if(id == ID::RAM) cartridge.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::EventROM0) event.rom[0].read(stream);
|
|
||||||
if(id == ID::EventROM1) event.rom[1].read(stream);
|
|
||||||
if(id == ID::EventROM2) event.rom[2].read(stream);
|
|
||||||
if(id == ID::EventROM3) event.rom[3].read(stream);
|
|
||||||
if(id == ID::EventRAM) event.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::SA1ROM) sa1.rom.read(stream);
|
|
||||||
if(id == ID::SA1IRAM) sa1.iram.read(stream);
|
|
||||||
if(id == ID::SA1BWRAM) sa1.bwram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::SuperFXROM) superfx.rom.read(stream);
|
|
||||||
if(id == ID::SuperFXRAM) superfx.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::ArmDSPPROM) {
|
|
||||||
for(auto n : range(128 * 1024)) armdsp.programROM[n] = stream.read();
|
|
||||||
}
|
|
||||||
if(id == ID::ArmDSPDROM) {
|
|
||||||
for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = stream.read();
|
|
||||||
}
|
|
||||||
if(id == ID::ArmDSPRAM) {
|
|
||||||
for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = stream.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::HitachiDSPROM) hitachidsp.rom.read(stream);
|
|
||||||
if(id == ID::HitachiDSPRAM) hitachidsp.ram.read(stream);
|
|
||||||
if(id == ID::HitachiDSPDROM) {
|
|
||||||
for(auto n : range(1024)) hitachidsp.dataROM[n] = stream.readl(3);
|
|
||||||
}
|
|
||||||
if(id == ID::HitachiDSPDRAM) {
|
|
||||||
for(auto n : range(3072)) hitachidsp.dataRAM[n] = stream.readl(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::Nec7725DSPPROM) {
|
|
||||||
for(auto n : range( 2048)) necdsp.programROM[n] = stream.readl(3);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec7725DSPDROM) {
|
|
||||||
for(auto n : range( 1024)) necdsp.dataROM[n] = stream.readl(2);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec7725DSPRAM) {
|
|
||||||
for(auto n : range( 256)) necdsp.dataRAM[n] = stream.readl(2);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec96050DSPPROM) {
|
|
||||||
for(auto n : range(16384)) necdsp.programROM[n] = stream.readl(3);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec96050DSPDROM) {
|
|
||||||
for(auto n : range( 2048)) necdsp.dataROM[n] = stream.readl(2);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec96050DSPRAM) {
|
|
||||||
for(auto n : range( 2048)) necdsp.dataRAM[n] = stream.readl(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::EpsonRTC) {
|
|
||||||
uint8 data[16] = {0};
|
|
||||||
stream.read((uint8_t*)data, min(stream.size(), sizeof data));
|
|
||||||
epsonrtc.load(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::SharpRTC) {
|
|
||||||
uint8 data[16] = {0};
|
|
||||||
stream.read((uint8_t*)data, min(stream.size(), sizeof data));
|
|
||||||
sharprtc.load(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::SPC7110PROM) spc7110.prom.read(stream);
|
|
||||||
if(id == ID::SPC7110DROM) spc7110.drom.read(stream);
|
|
||||||
if(id == ID::SPC7110RAM) spc7110.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::SDD1ROM) sdd1.rom.read(stream);
|
|
||||||
if(id == ID::SDD1RAM) sdd1.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::OBC1RAM) obc1.ram.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::MCCROM) mcc.rom.read(stream);
|
|
||||||
if(id == ID::MCCRAM) mcc.ram.read(stream);
|
|
||||||
|
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
if(id == ID::SuperGameBoyManifest) {
|
if(id == ID::SuperGameBoyManifest) {
|
||||||
GameBoy::interface->load(GameBoy::ID::SystemManifest, stream);
|
GameBoy::interface->load(GameBoy::ID::SystemManifest, stream);
|
||||||
|
@ -373,68 +231,15 @@ auto Interface::load(uint id, const stream& stream) -> void {
|
||||||
GameBoy::interface->load(GameBoy::ID::RAM, stream);
|
GameBoy::interface->load(GameBoy::ID::RAM, stream);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(id == ID::BSMemoryManifest) cartridge.information.markup.bsMemory = stream.text();
|
|
||||||
if(id == ID::BSMemoryROM) bsmemory.memory.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::SufamiTurboSlotAManifest) cartridge.information.markup.sufamiTurboA = stream.text();
|
|
||||||
if(id == ID::SufamiTurboSlotAROM) sufamiturboA.rom.read(stream);
|
|
||||||
if(id == ID::SufamiTurboSlotBROM) sufamiturboB.rom.read(stream);
|
|
||||||
|
|
||||||
if(id == ID::SufamiTurboSlotBManifest) cartridge.information.markup.sufamiTurboB = stream.text();
|
|
||||||
if(id == ID::SufamiTurboSlotARAM) sufamiturboA.ram.read(stream);
|
|
||||||
if(id == ID::SufamiTurboSlotBRAM) sufamiturboB.ram.read(stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//deprecated
|
||||||
auto Interface::save(uint id, const stream& stream) -> void {
|
auto Interface::save(uint id, const stream& stream) -> void {
|
||||||
if(id == ID::RAM) stream.write((uint8_t*)cartridge.ram.data(), cartridge.ram.size());
|
|
||||||
if(id == ID::EventRAM) stream.write((uint8_t*)event.ram.data(), event.ram.size());
|
|
||||||
if(id == ID::SA1IRAM) stream.write((uint8_t*)sa1.iram.data(), sa1.iram.size());
|
|
||||||
if(id == ID::SA1BWRAM) stream.write((uint8_t*)sa1.bwram.data(), sa1.bwram.size());
|
|
||||||
if(id == ID::SuperFXRAM) stream.write((uint8_t*)superfx.ram.data(), superfx.ram.size());
|
|
||||||
|
|
||||||
if(id == ID::ArmDSPRAM) {
|
|
||||||
for(auto n : range(16 * 1024)) stream.write(armdsp.programRAM[n]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::HitachiDSPRAM) stream.write((uint8_t*)hitachidsp.ram.data(), hitachidsp.ram.size());
|
|
||||||
if(id == ID::HitachiDSPDRAM) {
|
|
||||||
for(auto n : range(3072)) stream.writel(hitachidsp.dataRAM[n], 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::Nec7725DSPRAM) {
|
|
||||||
for(auto n : range( 256)) stream.writel(necdsp.dataRAM[n], 2);
|
|
||||||
}
|
|
||||||
if(id == ID::Nec96050DSPRAM) {
|
|
||||||
for(auto n : range(2048)) stream.writel(necdsp.dataRAM[n], 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::EpsonRTC) {
|
|
||||||
uint8 data[16] = {0};
|
|
||||||
epsonrtc.save(data);
|
|
||||||
stream.write((uint8_t*)data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::SharpRTC) {
|
|
||||||
uint8 data[16] = {0};
|
|
||||||
sharprtc.save(data);
|
|
||||||
stream.write((uint8_t*)data, sizeof data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(id == ID::SPC7110RAM) stream.write((uint8_t*)spc7110.ram.data(), spc7110.ram.size());
|
|
||||||
if(id == ID::SDD1RAM) stream.write((uint8_t*)sdd1.ram.data(), sdd1.ram.size());
|
|
||||||
if(id == ID::OBC1RAM) stream.write((uint8_t*)obc1.ram.data(), obc1.ram.size());
|
|
||||||
|
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
if(id == ID::GameBoyRAM) {
|
if(id == ID::GameBoyRAM) {
|
||||||
GameBoy::interface->save(GameBoy::ID::RAM, stream);
|
GameBoy::interface->save(GameBoy::ID::RAM, stream);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(id == ID::MCCRAM) stream.write((uint8_t*)mcc.ram.data(), mcc.ram.size());
|
|
||||||
|
|
||||||
if(id == ID::SufamiTurboSlotARAM) stream.write((uint8_t*)sufamiturboA.ram.data(), sufamiturboA.ram.size());
|
|
||||||
if(id == ID::SufamiTurboSlotBRAM) stream.write((uint8_t*)sufamiturboB.ram.data(), sufamiturboB.ram.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::unload() -> void {
|
auto Interface::unload() -> void {
|
||||||
|
@ -459,14 +264,14 @@ auto Interface::run() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::rtc() -> bool {
|
auto Interface::rtc() -> bool {
|
||||||
if(cartridge.hasEpsonRTC) return true;
|
if(cartridge.has.EpsonRTC) return true;
|
||||||
if(cartridge.hasSharpRTC) return true;
|
if(cartridge.has.SharpRTC) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::rtcsync() -> void {
|
auto Interface::rtcsync() -> void {
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.sync();
|
if(cartridge.has.EpsonRTC) epsonrtc.sync();
|
||||||
if(cartridge.hasSharpRTC) sharprtc.sync();
|
if(cartridge.has.SharpRTC) sharprtc.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Interface::serialize() -> serializer {
|
auto Interface::serialize() -> serializer {
|
||||||
|
@ -482,7 +287,7 @@ auto Interface::cheatSet(const lstring& list) -> void {
|
||||||
cheat.reset();
|
cheat.reset();
|
||||||
|
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
if(cartridge.hasICD2) {
|
if(cartridge.has.ICD2) {
|
||||||
GameBoy::cheat.reset();
|
GameBoy::cheat.reset();
|
||||||
for(auto& codeset : list) {
|
for(auto& codeset : list) {
|
||||||
lstring codes = codeset.split("+");
|
lstring codes = codeset.split("+");
|
||||||
|
|
|
@ -2,85 +2,23 @@ namespace SuperFamicom {
|
||||||
|
|
||||||
struct ID {
|
struct ID {
|
||||||
enum : uint {
|
enum : uint {
|
||||||
//cartridges (folders)
|
|
||||||
System,
|
System,
|
||||||
SuperFamicom,
|
SuperFamicom,
|
||||||
GameBoy,
|
GameBoy,
|
||||||
BSMemory,
|
BSMemory,
|
||||||
SufamiTurboSlotA,
|
SufamiTurboA,
|
||||||
SufamiTurboSlotB,
|
SufamiTurboB,
|
||||||
|
|
||||||
//memory (files)
|
|
||||||
SystemManifest,
|
|
||||||
IPLROM,
|
|
||||||
|
|
||||||
Manifest,
|
|
||||||
ROM,
|
|
||||||
RAM,
|
|
||||||
|
|
||||||
EventROM0,
|
|
||||||
EventROM1,
|
|
||||||
EventROM2,
|
|
||||||
EventROM3,
|
|
||||||
EventRAM,
|
|
||||||
|
|
||||||
SA1ROM,
|
|
||||||
SA1IRAM,
|
|
||||||
SA1BWRAM,
|
|
||||||
|
|
||||||
SuperFXROM,
|
|
||||||
SuperFXRAM,
|
|
||||||
|
|
||||||
ArmDSPPROM,
|
|
||||||
ArmDSPDROM,
|
|
||||||
ArmDSPRAM,
|
|
||||||
|
|
||||||
HitachiDSPROM,
|
|
||||||
HitachiDSPRAM,
|
|
||||||
HitachiDSPDROM,
|
|
||||||
HitachiDSPDRAM,
|
|
||||||
|
|
||||||
Nec7725DSPPROM,
|
|
||||||
Nec7725DSPDROM,
|
|
||||||
Nec7725DSPRAM,
|
|
||||||
|
|
||||||
Nec96050DSPPROM,
|
|
||||||
Nec96050DSPDROM,
|
|
||||||
Nec96050DSPRAM,
|
|
||||||
|
|
||||||
EpsonRTC,
|
|
||||||
SharpRTC,
|
|
||||||
|
|
||||||
SPC7110PROM,
|
|
||||||
SPC7110DROM,
|
|
||||||
SPC7110RAM,
|
|
||||||
|
|
||||||
SDD1ROM,
|
|
||||||
SDD1RAM,
|
|
||||||
|
|
||||||
OBC1RAM,
|
|
||||||
|
|
||||||
MCCROM,
|
|
||||||
MCCRAM,
|
|
||||||
|
|
||||||
|
//deprecated
|
||||||
SuperGameBoyManifest,
|
SuperGameBoyManifest,
|
||||||
SuperGameBoyBootROM,
|
SuperGameBoyBootROM,
|
||||||
|
|
||||||
GameBoyManifest,
|
GameBoyManifest,
|
||||||
GameBoyROM,
|
GameBoyROM,
|
||||||
GameBoyRAM,
|
GameBoyRAM,
|
||||||
|
};
|
||||||
|
|
||||||
BSMemoryManifest,
|
enum : uint {
|
||||||
BSMemoryROM,
|
|
||||||
|
|
||||||
SufamiTurboSlotAManifest,
|
|
||||||
SufamiTurboSlotAROM,
|
|
||||||
SufamiTurboSlotARAM,
|
|
||||||
|
|
||||||
SufamiTurboSlotBManifest,
|
|
||||||
SufamiTurboSlotBROM,
|
|
||||||
SufamiTurboSlotBRAM,
|
|
||||||
|
|
||||||
//device ports (bitmask)
|
//device ports (bitmask)
|
||||||
ControllerPort1 = 1,
|
ControllerPort1 = 1,
|
||||||
ControllerPort2 = 2,
|
ControllerPort2 = 2,
|
||||||
|
|
|
@ -24,6 +24,12 @@ auto MappedRAM::reset() -> void {
|
||||||
_writeProtect = false;
|
_writeProtect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto MappedRAM::allocate(uint size) -> void {
|
||||||
|
reset();
|
||||||
|
_data = new uint8[_size = size];
|
||||||
|
memory::fill(_data, _size, 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
auto MappedRAM::map(uint8* source, uint length) -> void {
|
auto MappedRAM::map(uint8* source, uint length) -> void {
|
||||||
reset();
|
reset();
|
||||||
_data = source;
|
_data = source;
|
||||||
|
|
|
@ -23,6 +23,7 @@ private:
|
||||||
|
|
||||||
struct MappedRAM : Memory {
|
struct MappedRAM : Memory {
|
||||||
inline auto reset() -> void;
|
inline auto reset() -> void;
|
||||||
|
inline auto allocate(uint) -> void;
|
||||||
inline auto map(uint8*, uint) -> void;
|
inline auto map(uint8*, uint) -> void;
|
||||||
inline auto copy(const stream& memory) -> void;
|
inline auto copy(const stream& memory) -> void;
|
||||||
inline auto read(const stream& memory) -> void;
|
inline auto read(const stream& memory) -> void;
|
||||||
|
|
|
@ -24,6 +24,12 @@ namespace SuperFamicom {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace SuperFamicom {
|
namespace SuperFamicom {
|
||||||
|
struct File {
|
||||||
|
static const vfs::file::mode Read = vfs::file::mode::read;
|
||||||
|
static const vfs::file::mode Write = vfs::file::mode::write;
|
||||||
|
static const bool Required = true;
|
||||||
|
};
|
||||||
|
|
||||||
struct Thread {
|
struct Thread {
|
||||||
virtual ~Thread() {
|
virtual ~Thread() {
|
||||||
if(thread) co_delete(thread);
|
if(thread) co_delete(thread);
|
||||||
|
|
|
@ -50,22 +50,22 @@ auto System::serializeAll(serializer& s) -> void {
|
||||||
ppu.serialize(s);
|
ppu.serialize(s);
|
||||||
dsp.serialize(s);
|
dsp.serialize(s);
|
||||||
|
|
||||||
if(cartridge.hasICD2) icd2.serialize(s);
|
if(cartridge.has.ICD2) icd2.serialize(s);
|
||||||
if(cartridge.hasMCC) mcc.serialize(s);
|
if(cartridge.has.MCC) mcc.serialize(s);
|
||||||
if(cartridge.hasEvent) event.serialize(s);
|
if(cartridge.has.Event) event.serialize(s);
|
||||||
if(cartridge.hasSA1) sa1.serialize(s);
|
if(cartridge.has.SA1) sa1.serialize(s);
|
||||||
if(cartridge.hasSuperFX) superfx.serialize(s);
|
if(cartridge.has.SuperFX) superfx.serialize(s);
|
||||||
if(cartridge.hasARMDSP) armdsp.serialize(s);
|
if(cartridge.has.ARMDSP) armdsp.serialize(s);
|
||||||
if(cartridge.hasHitachiDSP) hitachidsp.serialize(s);
|
if(cartridge.has.HitachiDSP) hitachidsp.serialize(s);
|
||||||
if(cartridge.hasNECDSP) necdsp.serialize(s);
|
if(cartridge.has.NECDSP) necdsp.serialize(s);
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.serialize(s);
|
if(cartridge.has.EpsonRTC) epsonrtc.serialize(s);
|
||||||
if(cartridge.hasSharpRTC) sharprtc.serialize(s);
|
if(cartridge.has.SharpRTC) sharprtc.serialize(s);
|
||||||
if(cartridge.hasSPC7110) spc7110.serialize(s);
|
if(cartridge.has.SPC7110) spc7110.serialize(s);
|
||||||
if(cartridge.hasSDD1) sdd1.serialize(s);
|
if(cartridge.has.SDD1) sdd1.serialize(s);
|
||||||
if(cartridge.hasOBC1) obc1.serialize(s);
|
if(cartridge.has.OBC1) obc1.serialize(s);
|
||||||
if(cartridge.hasMSU1) msu1.serialize(s);
|
if(cartridge.has.MSU1) msu1.serialize(s);
|
||||||
|
|
||||||
if(cartridge.hasSufamiTurboSlots) sufamiturboA.serialize(s), sufamiturboB.serialize(s);
|
if(cartridge.has.SufamiTurboSlots) sufamiturboA.serialize(s), sufamiturboB.serialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//perform dry-run state save:
|
//perform dry-run state save:
|
||||||
|
|
|
@ -51,14 +51,19 @@ auto System::init() -> void {
|
||||||
auto System::term() -> void {
|
auto System::term() -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::load() -> void {
|
auto System::load() -> bool {
|
||||||
bus.reset();
|
bus.reset();
|
||||||
|
|
||||||
interface->loadRequest(ID::SystemManifest, "manifest.bml", true);
|
if(auto fp = interface->open(ID::System, "manifest.bml", File::Read, File::Required)) {
|
||||||
|
information.manifest = fp->reads();
|
||||||
|
} else return false;
|
||||||
|
|
||||||
auto document = BML::unserialize(information.manifest);
|
auto document = BML::unserialize(information.manifest);
|
||||||
|
|
||||||
if(auto iplrom = document["system/smp/rom/name"].text()) {
|
if(auto iplrom = document["system/smp/rom/name"].text()) {
|
||||||
interface->loadRequest(ID::IPLROM, iplrom, true);
|
if(auto fp = interface->open(ID::System, iplrom, File::Read, File::Required)) {
|
||||||
|
fp->read(smp.iplrom, 64);
|
||||||
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cartridge.load();
|
cartridge.load();
|
||||||
|
@ -66,51 +71,56 @@ auto System::load() -> void {
|
||||||
_cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370;
|
_cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370;
|
||||||
_apuFrequency = 24'606'720;
|
_apuFrequency = 24'606'720;
|
||||||
|
|
||||||
if(cartridge.hasICD2) icd2.load();
|
if(cartridge.has.ICD2) icd2.load();
|
||||||
if(cartridge.hasMCC) mcc.load();
|
if(cartridge.has.MCC) mcc.load();
|
||||||
if(cartridge.hasNSSDIP) nss.load();
|
if(cartridge.has.NSSDIP) nss.load();
|
||||||
if(cartridge.hasEvent) event.load();
|
if(cartridge.has.Event) event.load();
|
||||||
if(cartridge.hasSA1) sa1.load();
|
if(cartridge.has.SA1) sa1.load();
|
||||||
if(cartridge.hasSuperFX) superfx.load();
|
if(cartridge.has.SuperFX) superfx.load();
|
||||||
if(cartridge.hasARMDSP) armdsp.load();
|
if(cartridge.has.ARMDSP) armdsp.load();
|
||||||
if(cartridge.hasHitachiDSP) hitachidsp.load();
|
if(cartridge.has.HitachiDSP) hitachidsp.load();
|
||||||
if(cartridge.hasNECDSP) necdsp.load();
|
if(cartridge.has.NECDSP) necdsp.load();
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.load();
|
if(cartridge.has.EpsonRTC) epsonrtc.load();
|
||||||
if(cartridge.hasSharpRTC) sharprtc.load();
|
if(cartridge.has.SharpRTC) sharprtc.load();
|
||||||
if(cartridge.hasSPC7110) spc7110.load();
|
if(cartridge.has.SPC7110) spc7110.load();
|
||||||
if(cartridge.hasSDD1) sdd1.load();
|
if(cartridge.has.SDD1) sdd1.load();
|
||||||
if(cartridge.hasOBC1) obc1.load();
|
if(cartridge.has.OBC1) obc1.load();
|
||||||
if(cartridge.hasMSU1) msu1.load();
|
if(cartridge.has.MSU1) msu1.load();
|
||||||
|
|
||||||
if(cartridge.hasBSMemorySlot) bsmemory.load();
|
if(cartridge.has.BSMemorySlot) bsmemory.load();
|
||||||
if(cartridge.hasSufamiTurboSlots) sufamiturboA.load(), sufamiturboB.load();
|
if(cartridge.has.SufamiTurboSlots) sufamiturboA.load(), sufamiturboB.load();
|
||||||
|
|
||||||
serializeInit();
|
serializeInit();
|
||||||
_loaded = true;
|
return _loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto System::save() -> void {
|
||||||
|
if(!loaded()) return;
|
||||||
|
cartridge.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto System::unload() -> void {
|
auto System::unload() -> void {
|
||||||
if(!loaded()) return;
|
if(!loaded()) return;
|
||||||
peripherals.unload();
|
peripherals.unload();
|
||||||
|
|
||||||
if(cartridge.hasICD2) icd2.unload();
|
if(cartridge.has.ICD2) icd2.unload();
|
||||||
if(cartridge.hasMCC) mcc.unload();
|
if(cartridge.has.MCC) mcc.unload();
|
||||||
if(cartridge.hasNSSDIP) nss.unload();
|
if(cartridge.has.NSSDIP) nss.unload();
|
||||||
if(cartridge.hasEvent) event.unload();
|
if(cartridge.has.Event) event.unload();
|
||||||
if(cartridge.hasSA1) sa1.unload();
|
if(cartridge.has.SA1) sa1.unload();
|
||||||
if(cartridge.hasSuperFX) superfx.unload();
|
if(cartridge.has.SuperFX) superfx.unload();
|
||||||
if(cartridge.hasARMDSP) armdsp.unload();
|
if(cartridge.has.ARMDSP) armdsp.unload();
|
||||||
if(cartridge.hasHitachiDSP) hitachidsp.unload();
|
if(cartridge.has.HitachiDSP) hitachidsp.unload();
|
||||||
if(cartridge.hasNECDSP) necdsp.unload();
|
if(cartridge.has.NECDSP) necdsp.unload();
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.unload();
|
if(cartridge.has.EpsonRTC) epsonrtc.unload();
|
||||||
if(cartridge.hasSharpRTC) sharprtc.unload();
|
if(cartridge.has.SharpRTC) sharprtc.unload();
|
||||||
if(cartridge.hasSPC7110) spc7110.unload();
|
if(cartridge.has.SPC7110) spc7110.unload();
|
||||||
if(cartridge.hasSDD1) sdd1.unload();
|
if(cartridge.has.SDD1) sdd1.unload();
|
||||||
if(cartridge.hasOBC1) obc1.unload();
|
if(cartridge.has.OBC1) obc1.unload();
|
||||||
if(cartridge.hasMSU1) msu1.unload();
|
if(cartridge.has.MSU1) msu1.unload();
|
||||||
|
|
||||||
if(cartridge.hasBSMemorySlot) bsmemory.unload();
|
if(cartridge.has.BSMemorySlot) bsmemory.unload();
|
||||||
if(cartridge.hasSufamiTurboSlots) sufamiturboA.unload(), sufamiturboB.unload();
|
if(cartridge.has.SufamiTurboSlots) sufamiturboA.unload(), sufamiturboB.unload();
|
||||||
|
|
||||||
cartridge.unload();
|
cartridge.unload();
|
||||||
_loaded = false;
|
_loaded = false;
|
||||||
|
@ -124,23 +134,23 @@ auto System::power() -> void {
|
||||||
dsp.power();
|
dsp.power();
|
||||||
ppu.power();
|
ppu.power();
|
||||||
|
|
||||||
if(cartridge.hasICD2) icd2.power();
|
if(cartridge.has.ICD2) icd2.power();
|
||||||
if(cartridge.hasMCC) mcc.power();
|
if(cartridge.has.MCC) mcc.power();
|
||||||
if(cartridge.hasNSSDIP) nss.power();
|
if(cartridge.has.NSSDIP) nss.power();
|
||||||
if(cartridge.hasEvent) event.power();
|
if(cartridge.has.Event) event.power();
|
||||||
if(cartridge.hasSA1) sa1.power();
|
if(cartridge.has.SA1) sa1.power();
|
||||||
if(cartridge.hasSuperFX) superfx.power();
|
if(cartridge.has.SuperFX) superfx.power();
|
||||||
if(cartridge.hasARMDSP) armdsp.power();
|
if(cartridge.has.ARMDSP) armdsp.power();
|
||||||
if(cartridge.hasHitachiDSP) hitachidsp.power();
|
if(cartridge.has.HitachiDSP) hitachidsp.power();
|
||||||
if(cartridge.hasNECDSP) necdsp.power();
|
if(cartridge.has.NECDSP) necdsp.power();
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.power();
|
if(cartridge.has.EpsonRTC) epsonrtc.power();
|
||||||
if(cartridge.hasSharpRTC) sharprtc.power();
|
if(cartridge.has.SharpRTC) sharprtc.power();
|
||||||
if(cartridge.hasSPC7110) spc7110.power();
|
if(cartridge.has.SPC7110) spc7110.power();
|
||||||
if(cartridge.hasSDD1) sdd1.power();
|
if(cartridge.has.SDD1) sdd1.power();
|
||||||
if(cartridge.hasOBC1) obc1.power();
|
if(cartridge.has.OBC1) obc1.power();
|
||||||
if(cartridge.hasMSU1) msu1.power();
|
if(cartridge.has.MSU1) msu1.power();
|
||||||
|
|
||||||
if(cartridge.hasBSMemorySlot) bsmemory.power();
|
if(cartridge.has.BSMemorySlot) bsmemory.power();
|
||||||
|
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
@ -159,35 +169,35 @@ auto System::reset() -> void {
|
||||||
dsp.reset();
|
dsp.reset();
|
||||||
ppu.reset();
|
ppu.reset();
|
||||||
|
|
||||||
if(cartridge.hasICD2) icd2.reset();
|
if(cartridge.has.ICD2) icd2.reset();
|
||||||
if(cartridge.hasMCC) mcc.reset();
|
if(cartridge.has.MCC) mcc.reset();
|
||||||
if(cartridge.hasNSSDIP) nss.reset();
|
if(cartridge.has.NSSDIP) nss.reset();
|
||||||
if(cartridge.hasEvent) event.reset();
|
if(cartridge.has.Event) event.reset();
|
||||||
if(cartridge.hasSA1) sa1.reset();
|
if(cartridge.has.SA1) sa1.reset();
|
||||||
if(cartridge.hasSuperFX) superfx.reset();
|
if(cartridge.has.SuperFX) superfx.reset();
|
||||||
if(cartridge.hasARMDSP) armdsp.reset();
|
if(cartridge.has.ARMDSP) armdsp.reset();
|
||||||
if(cartridge.hasHitachiDSP) hitachidsp.reset();
|
if(cartridge.has.HitachiDSP) hitachidsp.reset();
|
||||||
if(cartridge.hasNECDSP) necdsp.reset();
|
if(cartridge.has.NECDSP) necdsp.reset();
|
||||||
if(cartridge.hasEpsonRTC) epsonrtc.reset();
|
if(cartridge.has.EpsonRTC) epsonrtc.reset();
|
||||||
if(cartridge.hasSharpRTC) sharprtc.reset();
|
if(cartridge.has.SharpRTC) sharprtc.reset();
|
||||||
if(cartridge.hasSPC7110) spc7110.reset();
|
if(cartridge.has.SPC7110) spc7110.reset();
|
||||||
if(cartridge.hasSDD1) sdd1.reset();
|
if(cartridge.has.SDD1) sdd1.reset();
|
||||||
if(cartridge.hasOBC1) obc1.reset();
|
if(cartridge.has.OBC1) obc1.reset();
|
||||||
if(cartridge.hasMSU1) msu1.reset();
|
if(cartridge.has.MSU1) msu1.reset();
|
||||||
|
|
||||||
if(cartridge.hasBSMemorySlot) bsmemory.reset();
|
if(cartridge.has.BSMemorySlot) bsmemory.reset();
|
||||||
|
|
||||||
if(cartridge.hasICD2) cpu.coprocessors.append(&icd2);
|
if(cartridge.has.ICD2) cpu.coprocessors.append(&icd2);
|
||||||
if(cartridge.hasEvent) cpu.coprocessors.append(&event);
|
if(cartridge.has.Event) cpu.coprocessors.append(&event);
|
||||||
if(cartridge.hasSA1) cpu.coprocessors.append(&sa1);
|
if(cartridge.has.SA1) cpu.coprocessors.append(&sa1);
|
||||||
if(cartridge.hasSuperFX) cpu.coprocessors.append(&superfx);
|
if(cartridge.has.SuperFX) cpu.coprocessors.append(&superfx);
|
||||||
if(cartridge.hasARMDSP) cpu.coprocessors.append(&armdsp);
|
if(cartridge.has.ARMDSP) cpu.coprocessors.append(&armdsp);
|
||||||
if(cartridge.hasHitachiDSP) cpu.coprocessors.append(&hitachidsp);
|
if(cartridge.has.HitachiDSP) cpu.coprocessors.append(&hitachidsp);
|
||||||
if(cartridge.hasNECDSP) cpu.coprocessors.append(&necdsp);
|
if(cartridge.has.NECDSP) cpu.coprocessors.append(&necdsp);
|
||||||
if(cartridge.hasEpsonRTC) cpu.coprocessors.append(&epsonrtc);
|
if(cartridge.has.EpsonRTC) cpu.coprocessors.append(&epsonrtc);
|
||||||
if(cartridge.hasSharpRTC) cpu.coprocessors.append(&sharprtc);
|
if(cartridge.has.SharpRTC) cpu.coprocessors.append(&sharprtc);
|
||||||
if(cartridge.hasSPC7110) cpu.coprocessors.append(&spc7110);
|
if(cartridge.has.SPC7110) cpu.coprocessors.append(&spc7110);
|
||||||
if(cartridge.hasMSU1) cpu.coprocessors.append(&msu1);
|
if(cartridge.has.MSU1) cpu.coprocessors.append(&msu1);
|
||||||
|
|
||||||
scheduler.reset();
|
scheduler.reset();
|
||||||
peripherals.reset();
|
peripherals.reset();
|
||||||
|
|
|
@ -15,7 +15,8 @@ struct System {
|
||||||
|
|
||||||
auto init() -> void;
|
auto init() -> void;
|
||||||
auto term() -> void;
|
auto term() -> void;
|
||||||
auto load() -> void;
|
auto load() -> bool;
|
||||||
|
auto save() -> void;
|
||||||
auto unload() -> void;
|
auto unload() -> void;
|
||||||
auto power() -> void;
|
auto power() -> void;
|
||||||
auto reset() -> void;
|
auto reset() -> void;
|
||||||
|
|
|
@ -23,7 +23,8 @@ struct file {
|
||||||
return offset() >= size();
|
return offset() >= size();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto read(uint8_t* data, uintmax bytes) -> void {
|
auto read(void* vdata, uintmax bytes) -> void {
|
||||||
|
auto data = (uint8_t*)vdata;
|
||||||
while(bytes--) *data++ = read();
|
while(bytes--) *data++ = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,12 +40,15 @@ struct file {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reads(string& s) -> void {
|
auto reads() -> string {
|
||||||
|
string s;
|
||||||
s.resize(size());
|
s.resize(size());
|
||||||
read(s.get<uint8_t>(), s.size());
|
read(s.get<uint8_t>(), s.size());
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto write(const uint8_t* data, uintmax bytes) -> void {
|
auto write(const void* vdata, uintmax bytes) -> void {
|
||||||
|
auto data = (const uint8_t*)vdata;
|
||||||
while(bytes--) write(*data++);
|
while(bytes--) write(*data++);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue