mirror of https://github.com/bsnes-emu/bsnes.git
Update to v106r10 release.
byuu says: Changelog: - manifest: memory/battery now resides under type at memory/type/battery - genius: volatile option changed to battery; auto-disables when not RAM or RTC type - higan: added new Emulator::Game class to parse manifests for all emulated systems consistently - Super Famicom: board manifest appended to manifest viewer now - Super Famicom: cartridge class updated to use Emulator::Game objects - hiro: improve suppression of userland callbacks once Application::quit() is called - this fixes a crash in genius when closing the window with a tree view item selected My intention is to remove Emulator::Interface::sha256(), as it's not really useful. They'll be removed from save states as well. I never bothered validating the SHA256 within them, because that'd be really annoying for ROM hackers. I also intend to rename Emulator::Interface::title() to label() instead. Most everything is still broken. The SNES still needs all the board definitions updated, all the other cores need to move to using Emulator::Game.
This commit is contained in:
parent
e216912ca3
commit
2dd35f984d
|
@ -132,7 +132,7 @@ auto ListWindow::loadDatabase(string location) -> void {
|
||||||
component.memory.manufacturer = object["manufacturer"].text();
|
component.memory.manufacturer = object["manufacturer"].text();
|
||||||
component.memory.part = object["part"].text();
|
component.memory.part = object["part"].text();
|
||||||
component.memory.note = object["note"].text();
|
component.memory.note = object["note"].text();
|
||||||
component.memory.isVolatile = (bool)object["volatile"];
|
component.memory.battery = (bool)object["type/battery"];
|
||||||
}
|
}
|
||||||
if(object.name() == "oscillator") {
|
if(object.name() == "oscillator") {
|
||||||
component.type = Component::Type::Oscillator;
|
component.type = Component::Type::Oscillator;
|
||||||
|
@ -185,6 +185,8 @@ auto ListWindow::saveDatabase(string location) -> void {
|
||||||
if(component.type == Component::Type::Memory) {
|
if(component.type == Component::Type::Memory) {
|
||||||
fp.print(" memory\n");
|
fp.print(" memory\n");
|
||||||
fp.print(" type: ", component.memory.type, "\n");
|
fp.print(" type: ", component.memory.type, "\n");
|
||||||
|
if(component.memory.battery)
|
||||||
|
fp.print(" battery\n");
|
||||||
fp.print(" size: ", component.memory.size, "\n");
|
fp.print(" size: ", component.memory.size, "\n");
|
||||||
fp.print(" category: ", component.memory.category, "\n");
|
fp.print(" category: ", component.memory.category, "\n");
|
||||||
if(component.memory.manufacturer)
|
if(component.memory.manufacturer)
|
||||||
|
@ -193,8 +195,6 @@ auto ListWindow::saveDatabase(string location) -> void {
|
||||||
fp.print(" part: ", component.memory.part, "\n");
|
fp.print(" part: ", component.memory.part, "\n");
|
||||||
if(component.memory.note)
|
if(component.memory.note)
|
||||||
fp.print(" note: ", component.memory.note, "\n");
|
fp.print(" note: ", component.memory.note, "\n");
|
||||||
if(component.memory.isVolatile)
|
|
||||||
fp.print(" volatile\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(component.type == Component::Type::Oscillator) {
|
if(component.type == Component::Type::Oscillator) {
|
||||||
|
@ -370,7 +370,7 @@ auto GameWindow::reloadList() -> void {
|
||||||
string index = {"[", counter++, "] "};
|
string index = {"[", counter++, "] "};
|
||||||
if(component.type == Component::Type::Memory) {
|
if(component.type == Component::Type::Memory) {
|
||||||
item.setText({index, "Memory"});
|
item.setText({index, "Memory"});
|
||||||
item.append(TreeViewItem().setText({"Type: ", component.memory.type}));
|
item.append(TreeViewItem().setText({"Type: ", component.memory.type, component.memory.battery ? " + Battery" : ""}));
|
||||||
item.append(TreeViewItem().setText({"Size: ", component.memory.size}));
|
item.append(TreeViewItem().setText({"Size: ", component.memory.size}));
|
||||||
item.append(TreeViewItem().setText({"Category: ", component.memory.category}));
|
item.append(TreeViewItem().setText({"Category: ", component.memory.category}));
|
||||||
if(component.memory.manufacturer)
|
if(component.memory.manufacturer)
|
||||||
|
@ -379,8 +379,6 @@ auto GameWindow::reloadList() -> void {
|
||||||
item.append(TreeViewItem().setText({"Part: ", component.memory.part}));
|
item.append(TreeViewItem().setText({"Part: ", component.memory.part}));
|
||||||
if(component.memory.note)
|
if(component.memory.note)
|
||||||
item.append(TreeViewItem().setText({"Note: ", component.memory.note}));
|
item.append(TreeViewItem().setText({"Note: ", component.memory.note}));
|
||||||
if(component.memory.isVolatile)
|
|
||||||
item.append(TreeViewItem().setText({"Volatile"}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(component.type == Component::Type::Oscillator) {
|
if(component.type == Component::Type::Oscillator) {
|
||||||
|
@ -480,7 +478,7 @@ MemoryWindow::MemoryWindow() {
|
||||||
partEdit.onChange([&] { modified = true, updateWindow(); });
|
partEdit.onChange([&] { modified = true, updateWindow(); });
|
||||||
noteLabel.setText("Note:").setAlignment(1.0);
|
noteLabel.setText("Note:").setAlignment(1.0);
|
||||||
noteEdit.onChange([&] { modified = true, updateWindow(); });
|
noteEdit.onChange([&] { modified = true, updateWindow(); });
|
||||||
volatileOption.setText("Volatile").onToggle([&] { modified = true, updateWindow(); });
|
batteryOption.setText("Battery").onToggle([&] { modified = true, updateWindow(); });
|
||||||
acceptButton.setText("Accept").onActivate([&] { accept(); });
|
acceptButton.setText("Accept").onActivate([&] { accept(); });
|
||||||
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
|
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
|
||||||
|
|
||||||
|
@ -501,7 +499,7 @@ auto MemoryWindow::show(Memory memory) -> void {
|
||||||
manufacturerEdit.setText(memory.manufacturer);
|
manufacturerEdit.setText(memory.manufacturer);
|
||||||
partEdit.setText(memory.part);
|
partEdit.setText(memory.part);
|
||||||
noteEdit.setText(memory.note);
|
noteEdit.setText(memory.note);
|
||||||
volatileOption.setChecked(memory.isVolatile);
|
batteryOption.setChecked(memory.battery);
|
||||||
|
|
||||||
updateWindow();
|
updateWindow();
|
||||||
setCentered(*gameWindow);
|
setCentered(*gameWindow);
|
||||||
|
@ -517,7 +515,7 @@ auto MemoryWindow::accept() -> void {
|
||||||
memory.manufacturer = manufacturerEdit.text().strip();
|
memory.manufacturer = manufacturerEdit.text().strip();
|
||||||
memory.part = partEdit.text().strip();
|
memory.part = partEdit.text().strip();
|
||||||
memory.note = noteEdit.text().strip();
|
memory.note = noteEdit.text().strip();
|
||||||
memory.isVolatile = volatileOption.checked();
|
memory.battery = batteryOption.checked() && (memory.type == "RAM" || memory.type == "RTC");
|
||||||
|
|
||||||
Component component{Component::Type::Memory};
|
Component component{Component::Type::Memory};
|
||||||
component.memory = memory;
|
component.memory = memory;
|
||||||
|
@ -550,6 +548,7 @@ auto MemoryWindow::updateWindow() -> void {
|
||||||
manufacturerEdit.setBackgroundColor(manufacturerEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
manufacturerEdit.setBackgroundColor(manufacturerEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
||||||
partEdit.setBackgroundColor(partEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
partEdit.setBackgroundColor(partEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
||||||
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
|
||||||
|
batteryOption.setEnabled(typeEdit.text().strip() == "RAM" || typeEdit.text().strip() == "RTC");
|
||||||
acceptButton.setEnabled(valid);
|
acceptButton.setEnabled(valid);
|
||||||
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
|
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ struct Memory {
|
||||||
string manufacturer;
|
string manufacturer;
|
||||||
string part;
|
string part;
|
||||||
string note;
|
string note;
|
||||||
bool isVolatile = false;
|
boolean battery;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Oscillator {
|
struct Oscillator {
|
||||||
|
@ -151,7 +151,7 @@ private:
|
||||||
LineEdit noteEdit{¬eLayout, Size{~0, 0}};
|
LineEdit noteEdit{¬eLayout, Size{~0, 0}};
|
||||||
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
||||||
Widget controlSpacer{&controlLayout, Size{~0, 0}};
|
Widget controlSpacer{&controlLayout, Size{~0, 0}};
|
||||||
CheckLabel volatileOption{&controlLayout, Size{0, 0}};
|
CheckLabel batteryOption{&controlLayout, Size{0, 0}};
|
||||||
Button acceptButton{&controlLayout, Size{80, 0}};
|
Button acceptButton{&controlLayout, Size{80, 0}};
|
||||||
Button cancelButton{&controlLayout, Size{80, 0}};
|
Button cancelButton{&controlLayout, Size{80, 0}};
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@ using namespace nall;
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const string Name = "higan";
|
static const string Name = "higan";
|
||||||
static const string Version = "106.09";
|
static const string Version = "106.10";
|
||||||
static const string Author = "byuu";
|
static const string Author = "byuu";
|
||||||
static const string License = "GPLv3";
|
static const string License = "GPLv3";
|
||||||
static const string Website = "https://byuu.org/";
|
static const string Website = "https://byuu.org/";
|
||||||
|
@ -38,3 +38,4 @@ namespace Emulator {
|
||||||
|
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
#include "interface.hpp"
|
#include "interface.hpp"
|
||||||
|
#include "game.hpp"
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace Emulator {
|
||||||
|
|
||||||
|
struct Game {
|
||||||
|
struct Memory;
|
||||||
|
struct Oscillator;
|
||||||
|
|
||||||
|
inline auto load(string_view) -> void;
|
||||||
|
inline auto memory(string_view) -> maybe<Memory>;
|
||||||
|
inline auto oscillator(natural = 0) -> maybe<Oscillator>;
|
||||||
|
|
||||||
|
struct Memory {
|
||||||
|
explicit operator bool() const { return type; }
|
||||||
|
inline auto name() const -> string;
|
||||||
|
|
||||||
|
string type;
|
||||||
|
boolean battery;
|
||||||
|
natural size;
|
||||||
|
string category;
|
||||||
|
string manufacturer;
|
||||||
|
string part;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Oscillator {
|
||||||
|
explicit operator bool() const { return frequency; }
|
||||||
|
|
||||||
|
natural frequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
Markup::Node document;
|
||||||
|
string sha256;
|
||||||
|
string label;
|
||||||
|
string name;
|
||||||
|
string region;
|
||||||
|
string revision;
|
||||||
|
string board;
|
||||||
|
vector<Memory> memoryList;
|
||||||
|
vector<Oscillator> oscillatorList;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Game::load(string_view text) -> void {
|
||||||
|
document = BML::unserialize(text);
|
||||||
|
|
||||||
|
sha256 = document["game/sha256"].text();
|
||||||
|
label = document["game/label"].text();
|
||||||
|
name = document["game/name"].text();
|
||||||
|
region = document["game/region"].text();
|
||||||
|
revision = document["game/revision"].text();
|
||||||
|
board = document["game/board"].text();
|
||||||
|
|
||||||
|
for(auto node : document.find("game/board/memory")) {
|
||||||
|
Memory memory;
|
||||||
|
memory.type = node["type"].text();
|
||||||
|
memory.battery = (bool)node["type/battery"];
|
||||||
|
memory.size = node["size"].natural();
|
||||||
|
memory.category = node["category"].text();
|
||||||
|
memory.manufacturer = node["manufacturer"].text();
|
||||||
|
memory.part = node["part"].text();
|
||||||
|
memoryList.append(memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto node : document.find("game/board/oscillator")) {
|
||||||
|
Oscillator oscillator;
|
||||||
|
oscillator.frequency = node["frequency"].natural();
|
||||||
|
oscillatorList.append(oscillator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Game::memory(string_view name) -> maybe<Memory> {
|
||||||
|
for(auto& memory : memoryList) {
|
||||||
|
if(memory.name() == name) return memory;
|
||||||
|
}
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Game::oscillator(natural index) -> maybe<Oscillator> {
|
||||||
|
if(index < oscillatorList.size()) return oscillatorList[index];
|
||||||
|
return nothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Game::Memory::name() const -> string {
|
||||||
|
if(part) return string{part, ".", category, ".", type}.downcase();
|
||||||
|
return string{category, ".", type}.downcase();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,26 +8,32 @@ namespace SuperFamicom {
|
||||||
Cartridge cartridge;
|
Cartridge cartridge;
|
||||||
|
|
||||||
auto Cartridge::manifest() const -> string {
|
auto Cartridge::manifest() const -> string {
|
||||||
string manifest = information.manifest.cartridge;
|
string manifest = BML::serialize(game.document);
|
||||||
if(information.manifest.gameBoy) manifest.append("\n[[Game Boy]]\n\n", information.manifest.gameBoy);
|
manifest.append("\n", BML::serialize(board));
|
||||||
if(information.manifest.bsMemory) manifest.append("\n[[BS Memory]]\n\n", information.manifest.bsMemory);
|
if(slotGameBoy.document) manifest.append("\n", BML::serialize(slotGameBoy.document));
|
||||||
if(information.manifest.sufamiTurboA) manifest.append("\n[[Sufami Turbo - Slot A]]\n\n", information.manifest.sufamiTurboA);
|
if(slotBSMemory.document) manifest.append("\n", BML::serialize(slotBSMemory.document));
|
||||||
if(information.manifest.sufamiTurboB) manifest.append("\n[[Sufami Turbo - Slot B]]\n\n", information.manifest.sufamiTurboB);
|
if(slotSufamiTurboA.document) manifest.append("\n", BML::serialize(slotSufamiTurboA.document));
|
||||||
|
if(slotSufamiTurboB.document) manifest.append("\n", BML::serialize(slotSufamiTurboB.document));
|
||||||
return manifest;
|
return manifest;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::title() const -> string {
|
auto Cartridge::title() const -> string {
|
||||||
string title = information.title.cartridge;
|
auto label = game.label;
|
||||||
if(information.title.gameBoy) title.append(" + ", information.title.gameBoy);
|
if(slotGameBoy.label) label.append(" + ", slotGameBoy.label);
|
||||||
if(information.title.bsMemory) title.append(" + ", information.title.bsMemory);
|
if(slotBSMemory.label) label.append(" + ", slotBSMemory.label);
|
||||||
if(information.title.sufamiTurboA) title.append(" + ", information.title.sufamiTurboA);
|
if(slotSufamiTurboA.label) label.append(" + ", slotSufamiTurboA.label);
|
||||||
if(information.title.sufamiTurboB) title.append(" + ", information.title.sufamiTurboB);
|
if(slotSufamiTurboB.label) label.append(" + ", slotSufamiTurboB.label);
|
||||||
return title;
|
return label;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::load() -> bool {
|
auto Cartridge::load() -> bool {
|
||||||
information = {};
|
information = {};
|
||||||
has = {};
|
has = {};
|
||||||
|
game = {};
|
||||||
|
slotGameBoy = {};
|
||||||
|
slotBSMemory = {};
|
||||||
|
slotSufamiTurboA = {};
|
||||||
|
slotSufamiTurboB = {};
|
||||||
|
|
||||||
if(auto loaded = platform->load(ID::SuperFamicom, "Super Famicom", "sfc", {"Auto", "NTSC", "PAL"})) {
|
if(auto loaded = platform->load(ID::SuperFamicom, "Super Famicom", "sfc", {"Auto", "NTSC", "PAL"})) {
|
||||||
information.pathID = loaded.pathID();
|
information.pathID = loaded.pathID();
|
||||||
|
@ -35,10 +41,9 @@ auto Cartridge::load() -> bool {
|
||||||
} else return false;
|
} else return false;
|
||||||
|
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) {
|
if(auto fp = platform->open(ID::SuperFamicom, "manifest.bml", File::Read, File::Required)) {
|
||||||
information.manifest.cartridge = fp->reads();
|
game.load(fp->reads());
|
||||||
} else return false;
|
} else return false;
|
||||||
auto document = BML::unserialize(information.manifest.cartridge);
|
loadCartridge(game.document);
|
||||||
loadCartridge(document);
|
|
||||||
|
|
||||||
//Game Boy
|
//Game Boy
|
||||||
if(cartridge.has.ICD) {
|
if(cartridge.has.ICD) {
|
||||||
|
@ -91,9 +96,8 @@ auto Cartridge::loadGameBoy() -> bool {
|
||||||
#if defined(SFC_SUPERGAMEBOY)
|
#if defined(SFC_SUPERGAMEBOY)
|
||||||
//invoked from ICD::load()
|
//invoked from ICD::load()
|
||||||
information.sha256 = GameBoy::cartridge.sha256();
|
information.sha256 = GameBoy::cartridge.sha256();
|
||||||
information.manifest.gameBoy = GameBoy::cartridge.manifest();
|
slotGameBoy.load(GameBoy::cartridge.manifest());
|
||||||
information.title.gameBoy = GameBoy::cartridge.title();
|
loadGameBoy(slotGameBoy.document);
|
||||||
loadGameBoy(BML::unserialize(information.manifest.gameBoy));
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
@ -101,34 +105,40 @@ auto Cartridge::loadGameBoy() -> bool {
|
||||||
|
|
||||||
auto Cartridge::loadBSMemory() -> bool {
|
auto Cartridge::loadBSMemory() -> bool {
|
||||||
if(auto fp = platform->open(bsmemory.pathID, "manifest.bml", File::Read, File::Required)) {
|
if(auto fp = platform->open(bsmemory.pathID, "manifest.bml", File::Read, File::Required)) {
|
||||||
information.manifest.bsMemory = fp->reads();
|
slotBSMemory.load(fp->reads());
|
||||||
} else return false;
|
} else return false;
|
||||||
loadBSMemory(BML::unserialize(string{information.manifest.bsMemory}.replace("type: ", "type:")));
|
loadBSMemory(slotBSMemory.document);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboA() -> bool {
|
auto Cartridge::loadSufamiTurboA() -> bool {
|
||||||
if(auto fp = platform->open(sufamiturboA.pathID, "manifest.bml", File::Read, File::Required)) {
|
if(auto fp = platform->open(sufamiturboA.pathID, "manifest.bml", File::Read, File::Required)) {
|
||||||
information.manifest.sufamiTurboA = fp->reads();
|
slotSufamiTurboA.load(fp->reads());
|
||||||
} else return false;
|
} else return false;
|
||||||
loadSufamiTurboA(BML::unserialize(string{information.manifest.sufamiTurboA}.replace("type: ", "type:")));
|
loadSufamiTurboA(slotSufamiTurboA.document);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboB() -> bool {
|
auto Cartridge::loadSufamiTurboB() -> bool {
|
||||||
if(auto fp = platform->open(sufamiturboB.pathID, "manifest.bml", File::Read, File::Required)) {
|
if(auto fp = platform->open(sufamiturboB.pathID, "manifest.bml", File::Read, File::Required)) {
|
||||||
information.manifest.sufamiTurboB = fp->reads();
|
slotSufamiTurboB.load(fp->reads());
|
||||||
} else return false;
|
} else return false;
|
||||||
loadSufamiTurboB(BML::unserialize(string{information.manifest.sufamiTurboB}.replace("type: ", "type:")));
|
loadSufamiTurboB(slotSufamiTurboB.document);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::save() -> void {
|
auto Cartridge::save() -> void {
|
||||||
saveCartridge(BML::unserialize(information.manifest.cartridge));
|
saveCartridge(game.document);
|
||||||
saveGameBoy(BML::unserialize(information.manifest.gameBoy));
|
if(has.GameBoySlot) {
|
||||||
saveBSMemory(BML::unserialize(information.manifest.bsMemory));
|
saveGameBoy(slotGameBoy.document);
|
||||||
saveSufamiTurboA(BML::unserialize(string{information.manifest.sufamiTurboA}.replace("type: ", "type:")));
|
}
|
||||||
saveSufamiTurboB(BML::unserialize(string{information.manifest.sufamiTurboB}.replace("type: ", "type:")));
|
if(has.BSMemorySlot) {
|
||||||
|
saveBSMemory(slotBSMemory.document);
|
||||||
|
}
|
||||||
|
if(has.SufamiTurboSlots) {
|
||||||
|
saveSufamiTurboA(slotSufamiTurboA.document);
|
||||||
|
saveSufamiTurboB(slotSufamiTurboB.document);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::unload() -> void {
|
auto Cartridge::unload() -> void {
|
||||||
|
|
|
@ -18,22 +18,6 @@ struct Cartridge {
|
||||||
uint pathID = 0;
|
uint pathID = 0;
|
||||||
string region;
|
string region;
|
||||||
string sha256;
|
string sha256;
|
||||||
|
|
||||||
struct Manifest {
|
|
||||||
string cartridge;
|
|
||||||
string gameBoy;
|
|
||||||
string bsMemory;
|
|
||||||
string sufamiTurboA;
|
|
||||||
string sufamiTurboB;
|
|
||||||
} manifest;
|
|
||||||
|
|
||||||
struct Title {
|
|
||||||
string cartridge;
|
|
||||||
string gameBoy;
|
|
||||||
string bsMemory;
|
|
||||||
string sufamiTurboA;
|
|
||||||
string sufamiTurboB;
|
|
||||||
} title;
|
|
||||||
} information;
|
} information;
|
||||||
|
|
||||||
struct Has {
|
struct Has {
|
||||||
|
@ -59,6 +43,13 @@ struct Cartridge {
|
||||||
} has;
|
} has;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Emulator::Game game;
|
||||||
|
Emulator::Game slotGameBoy;
|
||||||
|
Emulator::Game slotBSMemory;
|
||||||
|
Emulator::Game slotSufamiTurboA;
|
||||||
|
Emulator::Game slotSufamiTurboB;
|
||||||
|
Markup::Node board;
|
||||||
|
|
||||||
//cartridge.cpp
|
//cartridge.cpp
|
||||||
auto loadGameBoy() -> bool;
|
auto loadGameBoy() -> bool;
|
||||||
auto loadBSMemory() -> bool;
|
auto loadBSMemory() -> bool;
|
||||||
|
@ -66,7 +57,7 @@ private:
|
||||||
auto loadSufamiTurboB() -> bool;
|
auto loadSufamiTurboB() -> bool;
|
||||||
|
|
||||||
//load.cpp
|
//load.cpp
|
||||||
auto loadBoard(Markup::Node) -> Markup::Node;
|
auto loadBoard(string) -> Markup::Node;
|
||||||
auto loadCartridge(Markup::Node) -> void;
|
auto loadCartridge(Markup::Node) -> void;
|
||||||
auto loadGameBoy(Markup::Node) -> void;
|
auto loadGameBoy(Markup::Node) -> void;
|
||||||
auto loadBSMemory(Markup::Node) -> void;
|
auto loadBSMemory(Markup::Node) -> void;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
|
auto Cartridge::loadBoard(string board) -> Markup::Node {
|
||||||
string output;
|
string output;
|
||||||
|
|
||||||
auto board = node["game/board"].text();
|
|
||||||
if(board.beginsWith("SNSP-")) board.replace("SNSP-", "SHVC-", 1L);
|
if(board.beginsWith("SNSP-")) board.replace("SNSP-", "SHVC-", 1L);
|
||||||
if(board.beginsWith("MAXI-")) board.replace("MAXI-", "SHVC-", 1L);
|
if(board.beginsWith("MAXI-")) board.replace("MAXI-", "SHVC-", 1L);
|
||||||
if(board.beginsWith("MJSC-")) board.replace("MJSC-", "SHVC-", 1L);
|
if(board.beginsWith("MJSC-")) board.replace("MJSC-", "SHVC-", 1L);
|
||||||
|
@ -26,10 +25,10 @@ auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadCartridge(Markup::Node node) -> void {
|
auto Cartridge::loadCartridge(Markup::Node node) -> void {
|
||||||
information.title.cartridge = node["game/label"].text();
|
board = loadBoard(game.board);
|
||||||
|
|
||||||
if(region() == "Auto") {
|
if(region() == "Auto") {
|
||||||
auto region = node["game/region"].text();
|
auto region = game.region;
|
||||||
if(region.endsWith("BRA")
|
if(region.endsWith("BRA")
|
||||||
|| region.endsWith("CAN")
|
|| region.endsWith("CAN")
|
||||||
|| region.endsWith("HKG")
|
|| region.endsWith("HKG")
|
||||||
|
@ -46,15 +45,13 @@ auto Cartridge::loadCartridge(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto board = node["board"];
|
|
||||||
if(!board) board = loadBoard(node);
|
|
||||||
|
|
||||||
if(board["bsmemory"] || board["mcc/bsmemory"] || board["sa1/bsmemory"]) {
|
if(board["bsmemory"] || board["mcc/bsmemory"] || board["sa1/bsmemory"]) {
|
||||||
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
|
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
|
||||||
bsmemory.pathID = loaded.pathID();
|
bsmemory.pathID = loaded.pathID();
|
||||||
loadBSMemory();
|
loadBSMemory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(board["sufamiturbo"]) {
|
if(board["sufamiturbo"]) {
|
||||||
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
|
if(auto loaded = platform->load(ID::SufamiTurboA, "Sufami Turbo", "st")) {
|
||||||
sufamiturboA.pathID = loaded.pathID();
|
sufamiturboA.pathID = loaded.pathID();
|
||||||
|
@ -88,17 +85,18 @@ auto Cartridge::loadGameBoy(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadBSMemory(Markup::Node node) -> void {
|
auto Cartridge::loadBSMemory(Markup::Node node) -> void {
|
||||||
information.title.bsMemory = node["game/label"].text();
|
if(node["game/board/memory/type"].text() == "ROM") {
|
||||||
bsmemory.readonly = node["game/memory/type"].text() == "ROM";
|
bsmemory.readonly = true;
|
||||||
|
loadMemory(bsmemory.memory, node["game/board/memory(type=ROM)"], File::Required, bsmemory.pathID);
|
||||||
loadMemory(bsmemory.memory, node["game/memory"], File::Required, bsmemory.pathID);
|
} else {
|
||||||
|
bsmemory.readonly = false;
|
||||||
|
loadMemory(bsmemory.memory, node["game/board/memory(type=Flash)"], File::Required, bsmemory.pathID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
|
auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
|
||||||
information.title.sufamiTurboA = node["game/label"].text();
|
loadMemory(sufamiturboA.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboA.pathID);
|
||||||
|
loadMemory(sufamiturboA.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboA.pathID);
|
||||||
loadMemory(sufamiturboA.rom, node["game/memory(type=ROM)" ], File::Required, sufamiturboA.pathID);
|
|
||||||
loadMemory(sufamiturboA.ram, node["game/memory(type=NVRAM)"], File::Optional, sufamiturboA.pathID);
|
|
||||||
|
|
||||||
if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
|
if(auto loaded = platform->load(ID::SufamiTurboB, "Sufami Turbo", "st")) {
|
||||||
sufamiturboB.pathID = loaded.pathID();
|
sufamiturboB.pathID = loaded.pathID();
|
||||||
|
@ -107,10 +105,8 @@ auto Cartridge::loadSufamiTurboA(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
|
auto Cartridge::loadSufamiTurboB(Markup::Node node) -> void {
|
||||||
information.title.sufamiTurboB = node["game/label"].text();
|
loadMemory(sufamiturboB.rom, node["game/board/memory(type=ROM)"], File::Required, sufamiturboB.pathID);
|
||||||
|
loadMemory(sufamiturboB.ram, node["game/board/memory(type=RAM)"], File::Optional, sufamiturboB.pathID);
|
||||||
loadMemory(sufamiturboB.rom, node["game/memory(type=ROM)" ], File::Required, sufamiturboB.pathID);
|
|
||||||
loadMemory(sufamiturboB.ram, node["game/memory(type=NVRAM)"], File::Optional, sufamiturboB.pathID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -227,15 +223,21 @@ auto Cartridge::loadSuperFX(Markup::Node node) -> void {
|
||||||
auto Cartridge::loadARMDSP(Markup::Node node) -> void {
|
auto Cartridge::loadARMDSP(Markup::Node node) -> void {
|
||||||
has.ARMDSP = true;
|
has.ARMDSP = true;
|
||||||
|
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["prom"]["name"].text(), File::Read, File::Required)) {
|
if(auto memory = game.memory(node["prom/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
|
||||||
for(auto n : range(128 * 1024)) armdsp.programROM[n] = fp->read();
|
for(auto n : range(128 * 1024)) armdsp.programROM[n] = fp->read();
|
||||||
}
|
}
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["drom"]["name"].text(), File::Read, File::Required)) {
|
}
|
||||||
|
if(auto memory = game.memory(node["drom/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
|
||||||
for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = fp->read();
|
for(auto n : range( 32 * 1024)) armdsp.dataROM[n] = fp->read();
|
||||||
}
|
}
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["ram"]["name"].text(), File::Read)) {
|
}
|
||||||
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
|
||||||
for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read();
|
for(auto n : range( 16 * 1024)) armdsp.programRAM[n] = fp->read();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto leaf : node.find("map")) loadMap(leaf, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp});
|
for(auto leaf : node.find("map")) loadMap(leaf, {&ArmDSP::read, &armdsp}, {&ArmDSP::write, &armdsp});
|
||||||
}
|
}
|
||||||
|
@ -253,12 +255,16 @@ auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void {
|
||||||
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
for(auto& word : hitachidsp.dataROM) word = 0x000000;
|
||||||
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
for(auto& word : hitachidsp.dataRAM) word = 0x00;
|
||||||
|
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["drom"]["name"].text(), File::Read, File::Required)) {
|
if(auto memory = game.memory(node["drom/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
|
||||||
for(auto n : range(1 * 1024)) hitachidsp.dataROM[n] = fp->readl(3);
|
for(auto n : range(1 * 1024)) hitachidsp.dataROM[n] = fp->readl(3);
|
||||||
}
|
}
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["dram"]["name"].text(), File::Read)) {
|
}
|
||||||
|
if(auto memory = game.memory(node["dram/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
|
||||||
for(auto n : range(3 * 1024)) hitachidsp.dataRAM[n] = fp->readl(1);
|
for(auto n : range(3 * 1024)) hitachidsp.dataRAM[n] = fp->readl(1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto leaf : node.find("map")) loadMap(leaf, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp});
|
for(auto leaf : node.find("map")) loadMap(leaf, {&HitachiDSP::dspRead, &hitachidsp}, {&HitachiDSP::dspWrite, &hitachidsp});
|
||||||
for(auto leaf : node["rom"].find("map")) loadMap(leaf, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp});
|
for(auto leaf : node["rom"].find("map")) loadMap(leaf, {&HitachiDSP::romRead, &hitachidsp}, {&HitachiDSP::romWrite, &hitachidsp});
|
||||||
|
@ -284,15 +290,21 @@ auto Cartridge::loadNECDSP(Markup::Node node) -> void {
|
||||||
if(necdsp.revision == NECDSP::Revision::uPD7725 ) memory::assign(size, 2048, 1024, 256);
|
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(necdsp.revision == NECDSP::Revision::uPD96050) memory::assign(size, 16384, 2048, 2048);
|
||||||
|
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["prom"]["name"].text(), File::Read, File::Required)) {
|
if(auto memory = game.memory(node["prom/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
|
||||||
for(auto n : range(size[0])) necdsp.programROM[n] = fp->readl(3);
|
for(auto n : range(size[0])) necdsp.programROM[n] = fp->readl(3);
|
||||||
}
|
}
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["drom"]["name"].text(), File::Read, File::Required)) {
|
}
|
||||||
|
if(auto memory = game.memory(node["drom/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
|
||||||
for(auto n : range(size[1])) necdsp.dataROM[n] = fp->readl(2);
|
for(auto n : range(size[1])) necdsp.dataROM[n] = fp->readl(2);
|
||||||
}
|
}
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["dram"]["name"].text(), File::Read)) {
|
}
|
||||||
|
if(auto memory = game.memory(node["dram/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
|
||||||
for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2);
|
for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto leaf : node.find("map")) loadMap(leaf, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
for(auto leaf : node.find("map")) loadMap(leaf, {&NECDSP::read, &necdsp}, {&NECDSP::write, &necdsp});
|
||||||
for(auto leaf : node["dram"].find("map")) loadMap(leaf, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
for(auto leaf : node["dram"].find("map")) loadMap(leaf, {&NECDSP::readRAM, &necdsp}, {&NECDSP::writeRAM, &necdsp});
|
||||||
|
@ -302,11 +314,13 @@ auto Cartridge::loadEpsonRTC(Markup::Node node) -> void {
|
||||||
has.EpsonRTC = true;
|
has.EpsonRTC = true;
|
||||||
|
|
||||||
epsonrtc.initialize();
|
epsonrtc.initialize();
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["ram"]["name"].text(), File::Read)) {
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
|
||||||
uint8 data[16] = {0};
|
uint8 data[16] = {0};
|
||||||
for(auto& byte : data) byte = fp->read();
|
for(auto& byte : data) byte = fp->read();
|
||||||
epsonrtc.load(data);
|
epsonrtc.load(data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto leaf : node.find("map")) loadMap(leaf, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
for(auto leaf : node.find("map")) loadMap(leaf, {&EpsonRTC::read, &epsonrtc}, {&EpsonRTC::write, &epsonrtc});
|
||||||
}
|
}
|
||||||
|
@ -315,11 +329,13 @@ auto Cartridge::loadSharpRTC(Markup::Node node) -> void {
|
||||||
has.SharpRTC = true;
|
has.SharpRTC = true;
|
||||||
|
|
||||||
sharprtc.initialize();
|
sharprtc.initialize();
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, node["ram"]["name"].text(), File::Read)) {
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
|
||||||
uint8 data[16] = {0};
|
uint8 data[16] = {0};
|
||||||
for(auto& byte : data) byte = fp->read();
|
for(auto& byte : data) byte = fp->read();
|
||||||
sharprtc.load(data);
|
sharprtc.load(data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto leaf : node.find("map")) loadMap(leaf, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
for(auto leaf : node.find("map")) loadMap(leaf, {&SharpRTC::read, &sharprtc}, {&SharpRTC::write, &sharprtc});
|
||||||
}
|
}
|
||||||
|
@ -366,13 +382,14 @@ auto Cartridge::loadMSU1(Markup::Node node) -> void {
|
||||||
|
|
||||||
auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, maybe<uint> id) -> void {
|
auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, maybe<uint> id) -> void {
|
||||||
if(!id) id = pathID();
|
if(!id) id = pathID();
|
||||||
auto name = node["name"].text();
|
if(auto memory = game.memory(node["name"].text())) {
|
||||||
auto size = node["size"].natural();
|
ram.allocate(memory->size);
|
||||||
ram.allocate(size);
|
if(memory->type == "RAM" && !memory->battery) return;
|
||||||
if(auto fp = platform->open(id(), name, File::Read, required)) {
|
if(memory->type == "RTC" && !memory->battery) return;
|
||||||
ram.allocate(fp->size()); //TODO: temporary hack
|
if(auto fp = platform->open(id(), memory->name(), File::Read, required)) {
|
||||||
fp->read(ram.data(), ram.size());
|
fp->read(ram.data(), ram.size());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::loadMap(Markup::Node map, SuperFamicom::Memory& memory) -> void {
|
auto Cartridge::loadMap(Markup::Node map, SuperFamicom::Memory& memory) -> void {
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
auto Cartridge::saveCartridge(Markup::Node node) -> void {
|
auto Cartridge::saveCartridge(Markup::Node node) -> void {
|
||||||
auto board = node["board"];
|
|
||||||
|
|
||||||
if(auto node = board["ram"]) saveRAM(node);
|
if(auto node = board["ram"]) saveRAM(node);
|
||||||
if(auto node = board["mcc"]) saveMCC(node);
|
if(auto node = board["mcc"]) saveMCC(node);
|
||||||
if(auto node = board["event"]) saveEvent(node);
|
if(auto node = board["event"]) saveEvent(node);
|
||||||
|
@ -23,11 +21,11 @@ auto Cartridge::saveBSMemory(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void {
|
auto Cartridge::saveSufamiTurboA(Markup::Node node) -> void {
|
||||||
saveMemory(sufamiturboA.ram, node["game/memory(type=NVRAM)"], sufamiturboA.pathID);
|
saveMemory(sufamiturboA.ram, node["game/board/memory(type=RAM)"], sufamiturboA.pathID);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void {
|
auto Cartridge::saveSufamiTurboB(Markup::Node node) -> void {
|
||||||
saveMemory(sufamiturboB.ram, node["game/memory(type=NVRAM)"], sufamiturboB.pathID);
|
saveMemory(sufamiturboB.ram, node["game/board/memory(type=RAM)"], sufamiturboB.pathID);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -54,9 +52,9 @@ auto Cartridge::saveSuperFX(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveARMDSP(Markup::Node node) -> void {
|
auto Cartridge::saveARMDSP(Markup::Node node) -> void {
|
||||||
if(!node["ram/volatile"]) {
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
if(auto name = node["ram/name"].text()) {
|
if(memory->battery) {
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, name, File::Write)) {
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
|
||||||
for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]);
|
for(auto n : range(16 * 1024)) fp->write(armdsp.programRAM[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,9 +64,9 @@ auto Cartridge::saveARMDSP(Markup::Node node) -> void {
|
||||||
auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
|
auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
|
||||||
saveMemory(hitachidsp.ram, node["ram"]);
|
saveMemory(hitachidsp.ram, node["ram"]);
|
||||||
|
|
||||||
if(!node["dram/volatile"]) {
|
if(auto memory = game.memory(node["dram/name"].text())) {
|
||||||
if(auto name = node["dram/name"].text()) {
|
if(memory->battery) {
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, name, File::Write)) {
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
|
||||||
for(auto n : range(3 * 1024)) fp->write(hitachidsp.dataRAM[n]);
|
for(auto n : range(3 * 1024)) fp->write(hitachidsp.dataRAM[n]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,10 +74,10 @@ auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveNECDSP(Markup::Node node) -> void {
|
auto Cartridge::saveNECDSP(Markup::Node node) -> void {
|
||||||
if(!node["dram/volatile"]) {
|
|
||||||
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048;
|
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048;
|
||||||
if(auto name = node["dram/name"].text()) {
|
if(auto memory = game.memory(node["dram/name"].text())) {
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, name, File::Write)) {
|
if(memory->battery) {
|
||||||
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
|
||||||
for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2);
|
for(auto n : range(size)) fp->writel(necdsp.dataRAM[n], 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,9 +85,9 @@ auto Cartridge::saveNECDSP(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
|
auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
|
||||||
if(!node["ram/volatile"]) {
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
if(auto name = node["ram/name"].text()) {
|
if(memory->battery) {
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, name, File::Write)) {
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
|
||||||
uint8 data[16] = {0};
|
uint8 data[16] = {0};
|
||||||
epsonrtc.save(data);
|
epsonrtc.save(data);
|
||||||
fp->write(data, 16);
|
fp->write(data, 16);
|
||||||
|
@ -99,9 +97,9 @@ auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cartridge::saveSharpRTC(Markup::Node node) -> void {
|
auto Cartridge::saveSharpRTC(Markup::Node node) -> void {
|
||||||
if(!node["ram/volatile"]) {
|
if(auto memory = game.memory(node["ram/name"].text())) {
|
||||||
if(auto name = node["ram/name"].text()) {
|
if(memory->battery) {
|
||||||
if(auto fp = platform->open(ID::SuperFamicom, name, File::Write)) {
|
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
|
||||||
uint8 data[16] = {0};
|
uint8 data[16] = {0};
|
||||||
sharprtc.save(data);
|
sharprtc.save(data);
|
||||||
fp->write(data, 16);
|
fp->write(data, 16);
|
||||||
|
@ -124,12 +122,13 @@ auto Cartridge::saveOBC1(Markup::Node node) -> void {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
auto Cartridge::saveMemory(MappedRAM& memory, Markup::Node node, maybe<uint> id) -> void {
|
auto Cartridge::saveMemory(MappedRAM& ram, Markup::Node node, maybe<uint> id) -> void {
|
||||||
if(!id) id = pathID();
|
if(!id) id = pathID();
|
||||||
if(!node || node["volatile"]) return;
|
if(auto memory = game.memory(node["name"].text())) {
|
||||||
auto name = node["name"].text();
|
if(memory->type == "RAM" && !memory->battery) return;
|
||||||
auto size = node["size"].natural();
|
if(memory->type == "RTC" && !memory->battery) return;
|
||||||
if(auto fp = platform->open(id(), name, File::Write)) {
|
if(auto fp = platform->open(id(), memory->name(), File::Write)) {
|
||||||
fp->write(memory.data(), memory.size());
|
fp->write(ram.data(), ram.size());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ auto MSU1::power() -> void {
|
||||||
|
|
||||||
auto MSU1::dataOpen() -> void {
|
auto MSU1::dataOpen() -> void {
|
||||||
dataFile.reset();
|
dataFile.reset();
|
||||||
auto document = BML::unserialize(cartridge.information.manifest.cartridge);
|
auto document = Markup::Node(); //todo: fix this
|
||||||
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 = platform->open(ID::SuperFamicom, name, File::Read)) {
|
if(dataFile = platform->open(ID::SuperFamicom, name, File::Read)) {
|
||||||
|
@ -82,7 +82,7 @@ auto MSU1::dataOpen() -> void {
|
||||||
|
|
||||||
auto MSU1::audioOpen() -> void {
|
auto MSU1::audioOpen() -> void {
|
||||||
audioFile.reset();
|
audioFile.reset();
|
||||||
auto document = BML::unserialize(cartridge.information.manifest.cartridge);
|
auto document = Markup::Node(); //todo: fix this
|
||||||
string name = {"track-", io.audioTrack, ".pcm"};
|
string name = {"track-", io.audioTrack, ".pcm"};
|
||||||
for(auto track : document.find("board/msu1/track")) {
|
for(auto track : document.find("board/msu1/track")) {
|
||||||
if(track["number"].natural() != io.audioTrack) continue;
|
if(track["number"].natural() != io.audioTrack) continue;
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct pObject {
|
||||||
virtual auto setFont(const Font& font) -> void;
|
virtual auto setFont(const Font& font) -> void;
|
||||||
virtual auto setVisible(bool visible) -> void;
|
virtual auto setVisible(bool visible) -> void;
|
||||||
|
|
||||||
auto locked() const -> bool { return locks != 0; }
|
auto locked() const -> bool { return locks != 0 || Application::state.quit; }
|
||||||
auto lock() -> void { ++locks; }
|
auto lock() -> void { ++locks; }
|
||||||
auto unlock() -> void { --locks; }
|
auto unlock() -> void { --locks; }
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct pObject {
|
||||||
virtual auto setFont(const Font& font) -> void;
|
virtual auto setFont(const Font& font) -> void;
|
||||||
virtual auto setVisible(bool visible) -> void;
|
virtual auto setVisible(bool visible) -> void;
|
||||||
|
|
||||||
auto locked() const -> bool { return locks != 0; }
|
auto locked() const -> bool { return locks != 0 || Application::state.quit; }
|
||||||
auto lock() -> void { ++locks; }
|
auto lock() -> void { ++locks; }
|
||||||
auto unlock() -> void { --locks; }
|
auto unlock() -> void { --locks; }
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct pObject {
|
||||||
virtual auto setFont(const Font& font) -> void;
|
virtual auto setFont(const Font& font) -> void;
|
||||||
virtual auto setVisible(bool visible) -> void;
|
virtual auto setVisible(bool visible) -> void;
|
||||||
|
|
||||||
auto locked() const -> bool { return locks != 0; }
|
auto locked() const -> bool { return locks != 0 || Application::state.quit; }
|
||||||
auto lock() -> void { locks++; }
|
auto lock() -> void { locks++; }
|
||||||
auto unlock() -> void { locks--; }
|
auto unlock() -> void { locks--; }
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct pObject {
|
||||||
virtual auto setGroup(sGroup group) -> void;
|
virtual auto setGroup(sGroup group) -> void;
|
||||||
virtual auto setVisible(bool visible) -> void;
|
virtual auto setVisible(bool visible) -> void;
|
||||||
|
|
||||||
auto locked() const -> bool { return locks != 0; }
|
auto locked() const -> bool { return locks != 0 || Application::state.quit; }
|
||||||
auto lock() -> void { ++locks; }
|
auto lock() -> void { ++locks; }
|
||||||
auto unlock() -> void { --locks; }
|
auto unlock() -> void { --locks; }
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct BSMemory : Heuristics {
|
struct BSMemory {
|
||||||
BSMemory(vector<uint8_t>& data, string location);
|
BSMemory(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct Famicom : Heuristics {
|
struct Famicom {
|
||||||
Famicom(vector<uint8_t>& data, string location);
|
Famicom(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct GameBoyAdvance : Heuristics {
|
struct GameBoyAdvance {
|
||||||
GameBoyAdvance(vector<uint8_t>& buffer, string location);
|
GameBoyAdvance(vector<uint8_t>& buffer, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct GameBoy : Heuristics {
|
struct GameBoy {
|
||||||
GameBoy(vector<uint8_t>& data, string location);
|
GameBoy(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct GameGear : Heuristics {
|
struct GameGear {
|
||||||
GameGear(vector<uint8_t>& data, string location);
|
GameGear(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -4,6 +4,8 @@ auto Memory::text() const -> string {
|
||||||
string output;
|
string output;
|
||||||
output.append(" memory\n");
|
output.append(" memory\n");
|
||||||
output.append(" type: ", _type, "\n");
|
output.append(" type: ", _type, "\n");
|
||||||
|
if(_battery)
|
||||||
|
output.append(" battery\n");
|
||||||
output.append(" size: 0x", hex(_size), "\n");
|
output.append(" size: 0x", hex(_size), "\n");
|
||||||
output.append(" category: ", _category, "\n");
|
output.append(" category: ", _category, "\n");
|
||||||
if(_manufacturer)
|
if(_manufacturer)
|
||||||
|
@ -12,8 +14,6 @@ if(_part)
|
||||||
output.append(" part: ", _part, "\n");
|
output.append(" part: ", _part, "\n");
|
||||||
if(_note)
|
if(_note)
|
||||||
output.append(" note: ", _note, "\n");
|
output.append(" note: ", _note, "\n");
|
||||||
if(_battery)
|
|
||||||
output.append(" battery\n");
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,16 +26,4 @@ if(_note)
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
//deprecated
|
|
||||||
auto Heuristics::memory(string type, uint size, string name, string metadata) const -> string {
|
|
||||||
string output;
|
|
||||||
output.append(" memory\n");
|
|
||||||
output.append(" type: ", type, "\n");
|
|
||||||
output.append(" size: 0x", hex(size), "\n");
|
|
||||||
output.append(" name: ", name, "\n");
|
|
||||||
if(metadata)
|
|
||||||
output.append(" metadata: ", metadata, "\n");
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,20 @@ namespace Heuristics {
|
||||||
|
|
||||||
struct Memory {
|
struct Memory {
|
||||||
auto& type(string type) { _type = type; return *this; }
|
auto& type(string type) { _type = type; return *this; }
|
||||||
|
auto& battery(boolean battery = true) { _battery = battery; return *this; }
|
||||||
auto& size(natural size) { _size = size; return *this; }
|
auto& size(natural size) { _size = size; return *this; }
|
||||||
auto& category(string category) { _category = category; return *this; }
|
auto& category(string category) { _category = category; return *this; }
|
||||||
auto& manufacturer(string manufacturer) { _manufacturer = manufacturer; return *this; }
|
auto& manufacturer(string manufacturer) { _manufacturer = manufacturer; return *this; }
|
||||||
auto& part(string part) { _part = part; return *this; }
|
auto& part(string part) { _part = part; return *this; }
|
||||||
auto& battery(boolean battery = true) { _battery = battery; return *this; }
|
|
||||||
auto& note(string note) { _note = note; return *this; }
|
auto& note(string note) { _note = note; return *this; }
|
||||||
auto text() const -> string;
|
auto text() const -> string;
|
||||||
|
|
||||||
string _type;
|
string _type;
|
||||||
|
boolean _battery;
|
||||||
natural _size;
|
natural _size;
|
||||||
string _category;
|
string _category;
|
||||||
string _manufacturer;
|
string _manufacturer;
|
||||||
string _part;
|
string _part;
|
||||||
boolean _battery;
|
|
||||||
string _note;
|
string _note;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,8 +28,4 @@ struct Oscillator {
|
||||||
string _note;
|
string _note;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Heuristics {
|
|
||||||
auto memory(string type, uint size, string name, string metadata = {}) const -> string;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct MasterSystem : Heuristics {
|
struct MasterSystem {
|
||||||
MasterSystem(vector<uint8_t>& data, string location);
|
MasterSystem(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct MegaDrive : Heuristics {
|
struct MegaDrive {
|
||||||
MegaDrive(vector<uint8_t>& data, string location);
|
MegaDrive(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct PCEngine : Heuristics {
|
struct PCEngine {
|
||||||
PCEngine(vector<uint8_t>& data, string location);
|
PCEngine(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct SufamiTurbo : Heuristics {
|
struct SufamiTurbo {
|
||||||
SufamiTurbo(vector<uint8_t>& data, string location);
|
SufamiTurbo(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct SuperFamicom : Heuristics {
|
struct SuperFamicom {
|
||||||
SuperFamicom(vector<uint8_t>& data, string location);
|
SuperFamicom(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct SuperGrafx : Heuristics {
|
struct SuperGrafx {
|
||||||
SuperGrafx(vector<uint8_t>& data, string location);
|
SuperGrafx(vector<uint8_t>& data, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
namespace Heuristics {
|
namespace Heuristics {
|
||||||
|
|
||||||
struct WonderSwan : Heuristics {
|
struct WonderSwan {
|
||||||
WonderSwan(vector<uint8_t>& buffer, string location);
|
WonderSwan(vector<uint8_t>& buffer, string location);
|
||||||
explicit operator bool() const;
|
explicit operator bool() const;
|
||||||
auto manifest() const -> string;
|
auto manifest() const -> string;
|
||||||
|
|
Loading…
Reference in New Issue