Update to v106r14 release.

byuu says:

Changelog:

  - game/memory/type/battery → game/memory/volatile
  - (manufacturer.)content.type → (architecture.)content.type
  - nall: Markup::find() strips spaces from values in comparisons
  - higan: updated game manifest loading/saving code for all cores
  - GBA: flash memory ID is internally selected based on the
    manufacturer and memory size
  - SFC: ST018 (ARM6) frequency can be modified via game manifest now
  - WS: EEPROM::name removed (not useful)
  - icarus, genius: battery→volatile updates

I did my best to look over the diff between r13 and r14, but it's 84KiB
excluding the game database changes. It's just too much for me. I'd
greatly appreciate if someone could look over it and check for any
errors in this update. But more than likely, I suppose we'll iron out
any issues by determining which games fail to load.

Right now, I know the Super Game Boy support doesn't seem to work. But
all non-SFC cores should work fully, and all normal + NEC DSP SFC games
should work as well. Unsure about the rest.

Also, I'm planning to change the Game Boy “MBC1M” mapper to “MBC1#A” to
indicate it's an alternate wiring configuration of the stock MBC1, and
not a new mapper type.
This commit is contained in:
Tim Allen 2018-04-15 15:49:53 +10:00
parent eaa2c1f6c0
commit 8f61c267c5
36 changed files with 2251 additions and 2460 deletions

View File

@ -63,7 +63,6 @@ ListWindow::ListWindow() {
reloadList(); reloadList();
updateWindow(); updateWindow();
setCentered(); setCentered();
setVisible();
} }
auto ListWindow::quit() -> void { auto ListWindow::quit() -> void {
@ -127,12 +126,12 @@ auto ListWindow::loadDatabase(string location) -> void {
if(object.name() == "memory") { if(object.name() == "memory") {
component.type = Component::Type::Memory; component.type = Component::Type::Memory;
component.memory.type = object["type"].text(); component.memory.type = object["type"].text();
component.memory.battery = (bool)object["type/battery"];
component.memory.size = object["size"].text(); component.memory.size = object["size"].text();
component.memory.content = object["content"].text(); component.memory.content = object["content"].text();
component.memory.manufacturer = object["manufacturer"].text(); component.memory.manufacturer = object["manufacturer"].text();
component.memory.architecture = object["architecture"].text(); component.memory.architecture = object["architecture"].text();
component.memory.identifier = object["identifier"].text(); component.memory.identifier = object["identifier"].text();
component.memory.Volatile = (bool)object["volatile"];
} }
if(object.name() == "oscillator") { if(object.name() == "oscillator") {
component.type = Component::Type::Oscillator; component.type = Component::Type::Oscillator;
@ -184,8 +183,6 @@ 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(" content: ", component.memory.content, "\n"); fp.print(" content: ", component.memory.content, "\n");
if(component.memory.manufacturer) if(component.memory.manufacturer)
@ -194,6 +191,8 @@ auto ListWindow::saveDatabase(string location) -> void {
fp.print(" architecture: ", component.memory.architecture, "\n"); fp.print(" architecture: ", component.memory.architecture, "\n");
if(component.memory.identifier) if(component.memory.identifier)
fp.print(" identifier: ", component.memory.identifier, "\n"); fp.print(" identifier: ", component.memory.identifier, "\n");
if(component.memory.Volatile)
fp.print(" volatile\n");
} }
if(component.type == Component::Type::Oscillator) { if(component.type == Component::Type::Oscillator) {
@ -367,7 +366,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, component.memory.battery ? " + Battery" : ""})); item.append(TreeViewItem().setText({"Type: ", component.memory.type}));
item.append(TreeViewItem().setText({"Size: ", component.memory.size})); item.append(TreeViewItem().setText({"Size: ", component.memory.size}));
item.append(TreeViewItem().setText({"Content: ", component.memory.content})); item.append(TreeViewItem().setText({"Content: ", component.memory.content}));
if(component.memory.manufacturer) if(component.memory.manufacturer)
@ -376,6 +375,8 @@ auto GameWindow::reloadList() -> void {
item.append(TreeViewItem().setText({"Architecture: ", component.memory.architecture})); item.append(TreeViewItem().setText({"Architecture: ", component.memory.architecture}));
if(component.memory.identifier) if(component.memory.identifier)
item.append(TreeViewItem().setText({"Identifier: ", component.memory.identifier})); item.append(TreeViewItem().setText({"Identifier: ", component.memory.identifier}));
if(component.memory.Volatile)
item.append(TreeViewItem().setText({"Volatile"}));
} }
if(component.type == Component::Type::Oscillator) { if(component.type == Component::Type::Oscillator) {
@ -473,7 +474,7 @@ MemoryWindow::MemoryWindow() {
architectureEdit.onChange([&] { modified = true, updateWindow(); }); architectureEdit.onChange([&] { modified = true, updateWindow(); });
identifierLabel.setText("Identifier:").setAlignment(1.0); identifierLabel.setText("Identifier:").setAlignment(1.0);
identifierEdit.onChange([&] { modified = true, updateWindow(); }); identifierEdit.onChange([&] { modified = true, updateWindow(); });
batteryOption.setText("Battery").onToggle([&] { modified = true, updateWindow(); }); volatileOption.setText("Volatile").onToggle([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); }); acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); }); cancelButton.setText("Cancel").onActivate([&] { cancel(); });
@ -494,7 +495,7 @@ auto MemoryWindow::show(Memory memory) -> void {
manufacturerEdit.setText(memory.manufacturer); manufacturerEdit.setText(memory.manufacturer);
architectureEdit.setText(memory.architecture); architectureEdit.setText(memory.architecture);
identifierEdit.setText(memory.identifier); identifierEdit.setText(memory.identifier);
batteryOption.setChecked(memory.battery); volatileOption.setChecked(memory.Volatile);
updateWindow(); updateWindow();
setCentered(*gameWindow); setCentered(*gameWindow);
@ -510,7 +511,7 @@ auto MemoryWindow::accept() -> void {
memory.manufacturer = manufacturerEdit.text().strip(); memory.manufacturer = manufacturerEdit.text().strip();
memory.architecture = architectureEdit.text().strip(); memory.architecture = architectureEdit.text().strip();
memory.identifier = identifierEdit.text().strip(); memory.identifier = identifierEdit.text().strip();
memory.battery = batteryOption.checked() && (memory.type == "RAM" || memory.type == "RTC"); memory.Volatile = volatileOption.checked() && (memory.type == "RAM" || memory.type == "RTC");
Component component{Component::Type::Memory}; Component component{Component::Type::Memory};
component.memory = memory; component.memory = memory;
@ -543,7 +544,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}));
architectureEdit.setBackgroundColor(architectureEdit.text().strip() ? Color{} : (Color{255, 255, 240})); architectureEdit.setBackgroundColor(architectureEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
identifierEdit.setBackgroundColor(identifierEdit.text().strip() ? Color{} : (Color{255, 255, 240})); identifierEdit.setBackgroundColor(identifierEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
batteryOption.setEnabled(typeEdit.text().strip() == "RAM" || typeEdit.text().strip() == "RTC"); volatileOption.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"});
} }
@ -615,11 +616,25 @@ auto OscillatorWindow::updateWindow() -> void {
// //
#include <nall/main.hpp> #include <nall/main.hpp>
auto nall::main(string_vector) -> void { auto nall::main(string_vector args) -> void {
Application::setName("genius"); Application::setName("genius");
new ListWindow; new ListWindow;
new GameWindow; new GameWindow;
new MemoryWindow; new MemoryWindow;
new OscillatorWindow; new OscillatorWindow;
//internal command used to synchronize all genius databases from an old format to a new format
//if enabled, use with extreme caution and make backups first
/*if(args.size() == 3 && args[1] == "--sync") {
for(auto& filename : directory::contents(args[2], "*.bml")) {
if(filename.beginsWith("Boards")) continue;
print(filename, "\n");
listWindow->loadDatabase({args[2], filename});
listWindow->saveDatabase({args[2], filename});
}
return print("[Done]\n");
}*/
listWindow->setVisible();
Application::run(); Application::run();
} }

View File

@ -1,11 +1,11 @@
struct Memory { struct Memory {
string type; string type;
boolean battery;
string size; string size;
string content; string content;
string manufacturer; string manufacturer;
string architecture; string architecture;
string identifier; string identifier;
boolean Volatile;
}; };
struct Oscillator { struct Oscillator {
@ -150,7 +150,7 @@ private:
LineEdit identifierEdit{&identifierLayout, Size{~0, 0}}; LineEdit identifierEdit{&identifierLayout, 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 batteryOption{&controlLayout, Size{0, 0}}; CheckLabel volatileOption{&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}};
}; };

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator { namespace Emulator {
static const string Name = "higan"; static const string Name = "higan";
static const string Version = "106.13"; static const string Version = "106.14";
static const string Author = "byuu"; static const string Author = "byuu";
static const string License = "GPLv3"; static const string License = "GPLv3";
static const string Website = "https://byuu.org/"; static const string Website = "https://byuu.org/";

View File

@ -11,19 +11,23 @@ struct Game {
inline auto oscillator(natural = 0) -> maybe<Oscillator>; inline auto oscillator(natural = 0) -> maybe<Oscillator>;
struct Memory { struct Memory {
Memory() = default;
inline Memory(Markup::Node);
explicit operator bool() const { return type; } explicit operator bool() const { return type; }
inline auto name() const -> string; inline auto name() const -> string;
string type; string type;
boolean battery;
natural size; natural size;
string content; string content;
string manufacturer; string manufacturer;
string architecture; string architecture;
string identifier; string identifier;
boolean nonVolatile;
}; };
struct Oscillator { struct Oscillator {
Oscillator() = default;
inline Oscillator(Markup::Node);
explicit operator bool() const { return frequency; } explicit operator bool() const { return frequency; }
natural frequency; natural frequency;
@ -51,21 +55,11 @@ auto Game::load(string_view text) -> void {
board = document["game/board"].text(); board = document["game/board"].text();
for(auto node : document.find("game/board/memory")) { for(auto node : document.find("game/board/memory")) {
Memory memory; memoryList.append(Memory{node});
memory.type = node["type"].text();
memory.battery = (bool)node["type/battery"];
memory.size = node["size"].natural();
memory.content = node["content"].text();
memory.manufacturer = node["manufacturer"].text();
memory.architecture = node["architecture"].text();
memory.identifier = node["identifier"].text();
memoryList.append(memory);
} }
for(auto node : document.find("game/board/oscillator")) { for(auto node : document.find("game/board/oscillator")) {
Oscillator oscillator; oscillatorList.append(Oscillator{node});
oscillator.frequency = node["frequency"].natural();
oscillatorList.append(oscillator);
} }
} }
@ -94,9 +88,23 @@ auto Game::oscillator(natural index) -> maybe<Oscillator> {
return nothing; return nothing;
} }
Game::Memory::Memory(Markup::Node node) {
type = node["type"].text();
size = node["size"].natural();
content = node["content"].text();
manufacturer = node["manufacturer"].text();
architecture = node["architecture"].text();
identifier = node["identifier"].text();
nonVolatile = !(bool)node["volatile"];
}
auto Game::Memory::name() const -> string { auto Game::Memory::name() const -> string {
if(manufacturer) return string{manufacturer, ".", content, ".", type}.downcase(); if(architecture) return string{architecture, ".", content, ".", type}.downcase();
return string{content, ".", type}.downcase(); return string{content, ".", type}.downcase();
} }
Game::Oscillator::Oscillator(Markup::Node node) {
frequency = node["frequency"].natural();
}
} }

View File

@ -21,66 +21,60 @@
Board::Board(Markup::Node& document) { Board::Board(Markup::Node& document) {
cartridge.board = this; cartridge.board = this;
auto board = document["board"]; information.type = document["game/board"].text();
information.type = board["id"].text(); if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
information.battery = (bool)board["prg/ram/name"]; if(prgrom.size = memory.size) prgrom.data = new uint8_t[prgrom.size]();
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Read, File::Required)) {
auto prom = board["prg/rom"];
auto pram = board["prg/ram"];
auto crom = board["chr/rom"];
auto cram = board["chr/ram"];
prgrom.size = prom["size"].natural();
prgram.size = pram["size"].natural();
chrrom.size = crom["size"].natural();
chrram.size = cram["size"].natural();
if(prgrom.size) prgrom.data = new uint8_t[prgrom.size]();
if(prgram.size) prgram.data = new uint8_t[prgram.size]();
if(chrrom.size) chrrom.data = new uint8_t[chrrom.size]();
if(chrram.size) chrram.data = new uint8_t[chrram.size]();
if(prgrom.name = prom["name"].text()) {
if(auto fp = platform->open(cartridge.pathID(), prgrom.name, File::Read, File::Required)) {
fp->read(prgrom.data, min(prgrom.size, fp->size())); fp->read(prgrom.data, min(prgrom.size, fp->size()));
} }
} }
if(prgram.name = pram["name"].text()) {
if(auto fp = platform->open(cartridge.pathID(), prgram.name, File::Read)) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(prgram.size = memory.size) prgram.data = new uint8_t[prgram.size](), prgram.writable = true;
if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Read)) {
fp->read(prgram.data, min(prgram.size, fp->size())); fp->read(prgram.data, min(prgram.size, fp->size()));
} }
} }
if(chrrom.name = crom["name"].text()) { }
if(auto fp = platform->open(cartridge.pathID(), chrrom.name, File::Read, File::Required)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Character)"]}) {
if(chrrom.size = memory.size) chrrom.data = new uint8_t[chrrom.size]();
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Read, File::Required)) {
fp->read(chrrom.data, min(chrrom.size, fp->size())); fp->read(chrrom.data, min(chrrom.size, fp->size()));
} }
} }
if(chrram.name = cram["name"].text()) {
if(auto fp = platform->open(cartridge.pathID(), chrram.name, File::Read)) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Character)"]}) {
if(chrram.size = memory.size) chrram.data = new uint8_t[chrram.size](), chrram.writable = true;
if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Read)) {
fp->read(chrram.data, min(chrram.size, fp->size())); fp->read(chrram.data, min(chrram.size, fp->size()));
} }
} }
}
prgram.writable = true;
chrram.writable = true;
} }
auto Board::save() -> void { auto Board::save() -> void {
auto document = BML::unserialize(cartridge.manifest()); auto document = BML::unserialize(cartridge.manifest());
if(auto name = document["board/prg/ram/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(auto fp = platform->open(cartridge.pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Write)) {
fp->write(prgram.data, prgram.size); fp->write(prgram.data, prgram.size);
} }
} }
}
if(auto name = document["board/chr/ram/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Character)"]}) {
if(auto fp = platform->open(cartridge.pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Write)) {
fp->write(chrram.data, chrram.size); fp->write(chrram.data, chrram.size);
} }
} }
} }
}
auto Board::Memory::read(uint addr) const -> uint8 { auto Board::Memory::read(uint addr) const -> uint8 {
return data[mirror(addr, size)]; return data[mirror(addr, size)];
@ -138,9 +132,9 @@ auto Board::serialize(serializer& s) -> void {
auto Board::load(string manifest) -> Board* { auto Board::load(string manifest) -> Board* {
auto document = BML::unserialize(manifest); auto document = BML::unserialize(manifest);
cartridge.information.title = document["information/title"].text(); cartridge.information.title = document["game/label"].text();
string type = document["board/id"].text(); string type = document["game/board"].text();
if(type == "BANDAI-FCG" ) return new BandaiFCG(document); if(type == "BANDAI-FCG" ) return new BandaiFCG(document);

View File

@ -39,7 +39,6 @@ struct Board {
struct Information { struct Information {
string type; string type;
bool battery;
} information; } information;
Memory prgrom; Memory prgrom;

View File

@ -48,8 +48,7 @@ auto Cartridge::load() -> bool {
information.manifest = fp->reads(); information.manifest = fp->reads();
} else return false; } else return false;
//todo: temporary hack so (type=) node lookup works; replace with a proper game/memory parser auto document = BML::unserialize(information.manifest);
auto document = BML::unserialize(string{information.manifest}.replace("type: ", "type:"));
information.title = document["game/label"].text(); information.title = document["game/label"].text();
auto mapperID = document["game/board"].text(); auto mapperID = document["game/board"].text();
@ -69,31 +68,29 @@ auto Cartridge::load() -> bool {
accelerometer = (bool)document["game/board/accelerometer"]; accelerometer = (bool)document["game/board/accelerometer"];
rumble = (bool)document["game/board/rumble"]; rumble = (bool)document["game/board/rumble"];
if(auto node = document["game/memory(type=ROM)"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.size = max(0x4000, node["size"].natural()); rom.size = max(0x4000, (uint)memory.size);
rom.data = (uint8*)memory::allocate(rom.size, 0xff); rom.data = (uint8*)memory::allocate(rom.size, 0xff);
if(auto name = node["name"].text()) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
fp->read(rom.data, min(rom.size, fp->size())); fp->read(rom.data, min(rom.size, fp->size()));
} }
} }
}
if(auto node = document["game/memory(type=NVRAM)"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
ram.size = node["size"].natural(); ram.size = memory.size;
ram.data = (uint8*)memory::allocate(ram.size, 0xff); ram.data = (uint8*)memory::allocate(ram.size, 0xff);
if(auto name = node["name"].text()) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Optional)) {
fp->read(ram.data, min(ram.size, fp->size())); fp->read(ram.data, min(ram.size, fp->size()));
} }
} }
} }
if(auto node = document["game/memory(type=RTC)"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
rtc.size = node["size"].natural(); rtc.size = memory.size;
rtc.data = (uint8*)memory::allocate(rtc.size, 0xff); rtc.data = (uint8*)memory::allocate(rtc.size, 0xff);
if(auto name = node["name"].text()) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Optional)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Optional)) {
fp->read(rtc.data, min(rtc.size, fp->size())); fp->read(rtc.data, min(rtc.size, fp->size()));
} }
} }
@ -104,19 +101,19 @@ auto Cartridge::load() -> bool {
} }
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(string{information.manifest}.replace("type: ", "type:")); auto document = BML::unserialize(information.manifest);
if(auto node = document["game/memory(type=NVRAM)"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(auto name = node["name"].text()) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(ram.data, ram.size); fp->write(ram.data, ram.size);
} }
} }
} }
if(auto node = document["game/memory(type=RTC)"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
if(auto name = node["name"].text()) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(rtc.data, rtc.size); fp->write(rtc.data, rtc.size);
} }
} }

View File

@ -35,61 +35,64 @@ auto Cartridge::load() -> bool {
} else return false; } else return false;
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
information.title = document["information/title"].text(); information.title = document["game/label"].text();
hasSRAM = false; hasSRAM = false;
hasEEPROM = false; hasEEPROM = false;
hasFLASH = false; hasFLASH = false;
if(auto node = document["board/rom"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
mrom.size = min(32 * 1024 * 1024, node["size"].natural()); mrom.size = min(32 * 1024 * 1024, (uint)memory.size);
if(auto fp = platform->open(pathID(), node["name"].text(), File::Read, File::Required)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
fp->read(mrom.data, mrom.size); fp->read(mrom.data, mrom.size);
} }
} }
if(auto node = document["board/ram"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(node["type"].text() == "sram") {
hasSRAM = true; hasSRAM = true;
sram.size = min(32 * 1024, node["size"].natural()); sram.size = min(32 * 1024, (uint)memory.size);
sram.mask = sram.size - 1; sram.mask = sram.size - 1;
for(auto n : range(sram.size)) sram.data[n] = 0xff; for(auto n : range(sram.size)) sram.data[n] = 0xff;
if(auto fp = platform->open(pathID(), node["name"].text(), File::Read)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(sram.data, sram.size); fp->read(sram.data, sram.size);
} }
} }
}
if(node["type"].text() == "eeprom") { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) {
hasEEPROM = true; hasEEPROM = true;
eeprom.size = min(8 * 1024, node["size"].natural()); eeprom.size = min(8 * 1024, (uint)memory.size);
eeprom.bits = eeprom.size <= 512 ? 6 : 14; eeprom.bits = eeprom.size <= 512 ? 6 : 14;
if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size if(eeprom.size == 0) eeprom.size = 8192, eeprom.bits = 0; //auto-detect size
eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000; eeprom.mask = mrom.size > 16 * 1024 * 1024 ? 0x0fffff00 : 0x0f000000;
eeprom.test = mrom.size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000; eeprom.test = mrom.size > 16 * 1024 * 1024 ? 0x0dffff00 : 0x0d000000;
for(auto n : range(eeprom.size)) eeprom.data[n] = 0xff; for(auto n : range(eeprom.size)) eeprom.data[n] = 0xff;
if(auto fp = platform->open(pathID(), node["name"].text(), File::Read)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(eeprom.data, eeprom.size); fp->read(eeprom.data, eeprom.size);
} }
} }
if(node["type"].text() == "flash") { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=Flash,content=Save)"]}) {
hasFLASH = true; hasFLASH = true;
flash.id = node["id"].natural(); flash.size = min(128 * 1024, (uint)memory.size);
flash.size = min(128 * 1024, node["size"].natural()); flash.manufacturer = memory.manufacturer;
for(auto n : range(flash.size)) flash.data[n] = 0xff; for(auto n : range(flash.size)) flash.data[n] = 0xff;
//if flash ID not provided; guess that it's a Macronix chip flash.id = 0;
//this will not work for all games; in which case, the ID must be specified manually if(flash.manufacturer == "Atmel" && flash.size == 64 * 1024) flash.id = 0x3d1f;
if(!flash.id && flash.size == 64 * 1024) flash.id = 0x1cc2; if(flash.manufacturer == "Macronix" && flash.size == 64 * 1024) flash.id = 0x1cc2;
if(!flash.id && flash.size == 128 * 1024) flash.id = 0x09c2; if(flash.manufacturer == "Macronix" && flash.size == 128 * 1024) flash.id = 0x09c2;
if(flash.manufacturer == "Panasonic" && flash.size == 64 * 1024) flash.id = 0x1b32;
if(flash.manufacturer == "Sanyo" && flash.size == 128 * 1024) flash.id = 0x1362;
if(flash.manufacturer == "SST" && flash.size == 64 * 1024) flash.id = 0xd4bf;
if(auto fp = platform->open(pathID(), node["name"].text(), File::Read)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(flash.data, flash.size); fp->read(flash.data, flash.size);
} }
} }
}
information.sha256 = Hash::SHA256(mrom.data, mrom.size).digest(); information.sha256 = Hash::SHA256(mrom.data, mrom.size).digest();
return true; return true;
@ -97,11 +100,24 @@ auto Cartridge::load() -> bool {
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
if(auto node = document["board/ram"]) {
if(auto fp = platform->open(pathID(), node["name"].text(), File::Write)) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(node["type"].text() == "sram") fp->write(sram.data, sram.size); if(memory.nonVolatile) {
if(node["type"].text() == "eeprom") fp->write(eeprom.data, eeprom.size); if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
if(node["type"].text() == "flash") fp->write(flash.data, flash.size); fp->write(sram.data, sram.size);
}
}
}
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(eeprom.data, eeprom.size);
}
}
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=Flash,content=Save)"]}) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(flash.data, flash.size);
} }
} }
} }

View File

@ -46,6 +46,8 @@ struct EEPROM {
struct FLASH { struct FLASH {
uint8* data; uint8* data;
uint size; uint size;
string manufacturer;
uint16 id; uint16 id;
bool unlockhi; bool unlockhi;

View File

@ -18,41 +18,37 @@ auto Cartridge::load() -> bool {
} else return false; } else return false;
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
information.title = document["information/title"].text(); information.title = document["game/label"].text();
if(information.region == "Auto") { if(information.region == "Auto") {
if(auto region = document["board/region"].text()) { if(auto region = document["game/region"].text()) {
information.region = region.upcase(); information.region = region.upcase();
} else { } else {
information.region = "NTSC-J"; information.region = "NTSC-J";
} }
} }
if(auto node = document["board/rom"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.size = node["size"].natural() >> 1; rom.size = memory.size >> 1;
rom.mask = bit::round(rom.size) - 1; rom.mask = bit::round(rom.size) - 1;
if(rom.size) {
rom.data = new uint16[rom.mask + 1](); rom.data = new uint16[rom.mask + 1]();
if(auto name = node["name"].text()) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
for(uint n : range(rom.size)) rom.data[n] = fp->readm(2); for(uint n : range(rom.size)) rom.data[n] = fp->readm(2);
} }
} }
}
}
if(auto node = document["board/ram"]) { //todo: handle mode, offset in Emulator::Game::Memory
if(auto mode = node["mode"].text()) { if(auto memory = document["game/board/memory(type=RAM,content=Save)"]) {
if(auto mode = memory["mode"].text()) {
if(mode == "lo" ) ram.bits = 0x00ff; if(mode == "lo" ) ram.bits = 0x00ff;
if(mode == "hi" ) ram.bits = 0xff00; if(mode == "hi" ) ram.bits = 0xff00;
if(mode == "word") ram.bits = 0xffff; if(mode == "word") ram.bits = 0xffff;
} }
ram.size = node["size"].natural() >> (ram.bits == 0xffff); ram.size = memory["size"].natural() >> (ram.bits == 0xffff);
ram.mask = bit::round(ram.size) - 1; ram.mask = bit::round(ram.size) - 1;
if(ram.size) {
ram.data = new uint16[ram.mask + 1](); ram.data = new uint16[ram.mask + 1]();
if(auto name = node["name"].text()) { if(!(bool)memory["volatile"]) {
if(auto fp = platform->open(pathID(), name, File::Read)) { if(auto fp = platform->open(pathID(), "save.ram", File::Read)) {
for(uint n : range(ram.size)) { for(uint n : range(ram.size)) {
if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101; if(ram.bits != 0xffff) ram.data[n] = fp->readm(1) * 0x0101;
if(ram.bits == 0xffff) ram.data[n] = fp->readm(2); if(ram.bits == 0xffff) ram.data[n] = fp->readm(2);
@ -60,7 +56,6 @@ auto Cartridge::load() -> bool {
} }
} }
} }
}
return true; return true;
} }
@ -68,8 +63,9 @@ auto Cartridge::load() -> bool {
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
if(auto name = document["board/ram/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
for(uint n : range(ram.size)) { for(uint n : range(ram.size)) {
if(ram.bits != 0xffff) fp->writem(ram.data[n], 1); if(ram.bits != 0xffff) fp->writem(ram.data[n], 1);
if(ram.bits == 0xffff) fp->writem(ram.data[n], 2); if(ram.bits == 0xffff) fp->writem(ram.data[n], 2);
@ -77,6 +73,7 @@ auto Cartridge::save() -> void {
} }
} }
} }
}
auto Cartridge::unload() -> void { auto Cartridge::unload() -> void {
delete[] rom.data; delete[] rom.data;

View File

@ -27,33 +27,27 @@ auto Cartridge::load() -> bool {
} else return false; } else return false;
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
information.title = document["information/title"].text(); information.title = document["game/label"].text();
if(auto node = document["board/rom"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.size = node["size"].natural(); rom.size = memory.size;
rom.mask = bit::round(rom.size) - 1; rom.mask = bit::round(rom.size) - 1;
if(rom.size) {
rom.data = new uint8[rom.mask + 1]; rom.data = new uint8[rom.mask + 1];
if(auto name = node["name"].text()) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
fp->read(rom.data, rom.size); fp->read(rom.data, rom.size);
} }
} }
}
}
if(auto node = document["board/ram"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
ram.size = node["size"].natural(); ram.size = memory.size;
ram.mask = bit::round(ram.size) - 1; ram.mask = bit::round(ram.size) - 1;
if(ram.size) {
ram.data = new uint8[ram.mask + 1]; ram.data = new uint8[ram.mask + 1];
if(auto name = node["name"].text()) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), name, File::Read)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(ram.data, ram.size); fp->read(ram.data, ram.size);
} }
} }
} }
}
return true; return true;
} }
@ -61,12 +55,14 @@ auto Cartridge::load() -> bool {
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
if(auto name = document["board/ram/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(ram.data, ram.size); fp->write(ram.data, ram.size);
} }
} }
} }
}
auto Cartridge::unload() -> void { auto Cartridge::unload() -> void {
delete[] rom.data; delete[] rom.data;

View File

@ -24,19 +24,15 @@ auto Cartridge::load() -> bool {
} else return false; } else return false;
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
information.title = document["information/title"].text(); information.title = document["game/label"].text();
if(auto node = document["board/rom"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.size = node["size"].natural(); rom.size = memory.size;
if(rom.size) {
rom.data = new uint8[rom.size](); rom.data = new uint8[rom.size]();
if(auto name = node["name"].text()) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
if(auto fp = platform->open(pathID(), name, File::Read, File::Required)) {
fp->read(rom.data, rom.size); fp->read(rom.data, rom.size);
} }
} }
}
}
information.sha256 = Hash::SHA256(rom.data, rom.size).digest(); information.sha256 = Hash::SHA256(rom.data, rom.size).digest();
return true; return true;

View File

@ -223,17 +223,23 @@ 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 memory = game.memory(node["memory(type=ROM,category=Program)"])) { if(auto oscillator = game.oscillator()) {
armdsp.Frequency = oscillator->frequency;
} else {
armdsp.Frequency = 21'440'000;
}
if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { 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 memory = game.memory(node["memory(type=ROM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=ROM,content=Data)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { if(auto 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 memory = game.memory(node["memory(type=RAM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { 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();
} }
@ -245,8 +251,11 @@ auto Cartridge::loadARMDSP(Markup::Node node) -> void {
auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void { auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void {
has.HitachiDSP = true; has.HitachiDSP = true;
hitachidsp.Frequency = node["frequency"].natural(); if(auto oscillator = game.oscillator()) {
if(hitachidsp.Frequency == 0) hitachidsp.Frequency = 20'000'000; hitachidsp.Frequency = oscillator->frequency;
} else {
hitachidsp.Frequency = 20'000'000;
}
hitachidsp.Roms = roms; //1 or 2 hitachidsp.Roms = roms; //1 or 2
loadMemory(hitachidsp.rom, node["rom"], File::Required); loadMemory(hitachidsp.rom, node["rom"], File::Required);
@ -255,12 +264,12 @@ 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 memory = game.memory(node["memory(type=ROM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=ROM,content=Data)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { if(auto 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 memory = game.memory(node["memory(type=RAM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { 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);
} }
@ -275,8 +284,12 @@ auto Cartridge::loadHitachiDSP(Markup::Node node, uint roms) -> void {
auto Cartridge::loadNECDSP(Markup::Node node) -> void { auto Cartridge::loadNECDSP(Markup::Node node) -> void {
has.NECDSP = true; has.NECDSP = true;
necdsp.Frequency = node["frequency"].natural(); if(auto oscillator = game.oscillator()) {
if(necdsp.Frequency == 0) necdsp.Frequency = 8000000; necdsp.Frequency = oscillator->frequency;
} else {
necdsp.Frequency = 7'600'000;
}
necdsp.revision necdsp.revision
= node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725 = node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
: node["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 : node["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050
@ -290,18 +303,18 @@ 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 memory = game.memory(node["memory(type=ROM,category=Program)"])) { if(auto memory = game.memory(node["memory(type=ROM,content=Program)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { 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 memory = game.memory(node["memory(type=ROM,category=Data)"])) { if(auto memory = Emulator::Game::Memory{node["memory(type=ROM,content=Data)"]}) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) { 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 memory = game.memory(node["memory(type=RAM,category=Data"])) { if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { 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);
} }
} }
@ -314,7 +327,7 @@ auto Cartridge::loadEpsonRTC(Markup::Node node) -> void {
has.EpsonRTC = true; has.EpsonRTC = true;
epsonrtc.initialize(); epsonrtc.initialize();
if(auto memory = game.memory(node["memory(type=RTC)"])) { if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { 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();
@ -329,7 +342,7 @@ auto Cartridge::loadSharpRTC(Markup::Node node) -> void {
has.SharpRTC = true; has.SharpRTC = true;
sharprtc.initialize(); sharprtc.initialize();
if(auto memory = game.memory(node["memory(type=RTC)"])) { if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) { 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();
@ -384,8 +397,8 @@ auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, may
if(!id) id = pathID(); if(!id) id = pathID();
if(auto memory = game.memory(node)) { if(auto memory = game.memory(node)) {
ram.allocate(memory->size); ram.allocate(memory->size);
if(memory->type == "RAM" && !memory->battery) return; if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->battery) return; if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Read, required)) { if(auto fp = platform->open(id(), memory->name(), File::Read, required)) {
fp->read(ram.data(), ram.size()); fp->read(ram.data(), ram.size());
} }

View File

@ -52,8 +52,8 @@ auto Cartridge::saveSuperFX(Markup::Node node) -> void {
} }
auto Cartridge::saveARMDSP(Markup::Node node) -> void { auto Cartridge::saveARMDSP(Markup::Node node) -> void {
if(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(memory->battery) { if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->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]);
} }
@ -64,8 +64,8 @@ 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(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) { if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(memory->battery) { if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->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]);
} }
@ -75,9 +75,9 @@ auto Cartridge::saveHitachiDSP(Markup::Node node) -> void {
auto Cartridge::saveNECDSP(Markup::Node node) -> void { auto Cartridge::saveNECDSP(Markup::Node node) -> void {
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048; uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048;
if(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) { if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) {
if(memory->battery) { if(memory.nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) { 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);
} }
} }
@ -85,8 +85,8 @@ auto Cartridge::saveNECDSP(Markup::Node node) -> void {
} }
auto Cartridge::saveEpsonRTC(Markup::Node node) -> void { auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
if(auto memory = game.memory(node["memory(type=RTC)"])) { if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(memory->battery) { if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->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);
@ -97,8 +97,8 @@ auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
} }
auto Cartridge::saveSharpRTC(Markup::Node node) -> void { auto Cartridge::saveSharpRTC(Markup::Node node) -> void {
if(auto memory = game.memory(node["memory(type=RTC)"])) { if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(memory->battery) { if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->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);
@ -125,8 +125,8 @@ auto Cartridge::saveOBC1(Markup::Node node) -> void {
auto Cartridge::saveMemory(MappedRAM& ram, 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(auto memory = game.memory(node)) { if(auto memory = game.memory(node)) {
if(memory->type == "RAM" && !memory->battery) return; if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->battery) return; if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Write)) { if(auto fp = platform->open(id(), memory->name(), File::Write)) {
fp->write(ram.data(), ram.size()); fp->write(ram.data(), ram.size());
} }

View File

@ -89,7 +89,7 @@ auto ArmDSP::power() -> void {
auto ArmDSP::reset() -> void { auto ArmDSP::reset() -> void {
ARM7TDMI::power(); ARM7TDMI::power();
create(ArmDSP::Enter, 21'477'272); create(ArmDSP::Enter, Frequency);
bridge.ready = false; bridge.ready = false;
bridge.signal = false; bridge.signal = false;

View File

@ -25,6 +25,8 @@ struct ArmDSP : Processor::ARM7TDMI, Thread {
auto firmware() const -> nall::vector<uint8>; auto firmware() const -> nall::vector<uint8>;
auto serialize(serializer&) -> void; auto serialize(serializer&) -> void;
uint Frequency;
uint8 programROM[128 * 1024]; uint8 programROM[128 * 1024];
uint8 dataROM[32 * 1024]; uint8 dataROM[32 * 1024];
uint8 programRAM[16 * 1024]; uint8 programRAM[16 * 1024];

View File

@ -1,490 +1,498 @@
database database
revision: 2018-04-08 revision: 2018-04-15
//Boards (Production) //Boards (Production)
database database
revision: 2018-02-27 revision: 2018-04-10
board: BANDAI-PT-923 board: BANDAI-PT-923
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
sufamiturbo slot type=SufamiTurbo
rom rom
map address=20-3f,a0-bf:8000-ffff mask=0x8000 map address=20-3f,a0-bf:8000-ffff mask=0x8000
ram ram
map address=60-6f,e0-ef:0000-ffff map address=60-6f,e0-ef:0000-ffff
sufamiturbo slot type=SufamiTurbo
rom rom
map address=40-5f,c0-df:0000-ffff mask=0x8000 map address=40-5f,c0-df:0000-ffff mask=0x8000
ram ram
map address=70-7d,f0-ff:0000-ffff map address=70-7d,f0-ff:0000-ffff
board: BSC-1A5M-02 board: BSC-1A5M-02
rom memory type=ROM content=Program
map address=00-1f:8000-ffff mask=0x8000 base=0x000000 map address=00-1f:8000-ffff mask=0x8000 base=0x000000
map address=20-3f:8000-ffff mask=0x8000 base=0x100000 map address=20-3f:8000-ffff mask=0x8000 base=0x100000
map address=80-9f:8000-ffff mask=0x8000 base=0x200000 map address=80-9f:8000-ffff mask=0x8000 base=0x200000
map address=a0-bf:8000-ffff mask=0x8000 base=0x100000 map address=a0-bf:8000-ffff mask=0x8000 base=0x100000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
bsmemory slot type=BSMemory
map address=c0-ef:0000-ffff map address=c0-ef:0000-ffff
board: BSC-1A7M-01 board: BSC-1A7M-01
rom memory type=ROM content=Program
map address=00-1f:8000-ffff mask=0x8000 base=0x000000 map address=00-1f:8000-ffff mask=0x8000 base=0x000000
map address=20-3f:8000-ffff mask=0x8000 base=0x100000 map address=20-3f:8000-ffff mask=0x8000 base=0x100000
map address=80-9f:8000-ffff mask=0x8000 base=0x200000 map address=80-9f:8000-ffff mask=0x8000 base=0x200000
map address=a0-bf:8000-ffff mask=0x8000 base=0x100000 map address=a0-bf:8000-ffff mask=0x8000 base=0x100000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
bsmemory slot type=BSMemory
map address=c0-ef:0000-ffff map address=c0-ef:0000-ffff
board: BSC-1J3M-01 board: BSC-1J3M-01
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff map address=00-1f,80-9f:8000-ffff
map address=40-5f,c0-df:0000-ffff map address=40-5f,c0-df:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
bsmemory slot type=BSMemory
map address=20-3f,a0-bf:8000-ffff map address=20-3f,a0-bf:8000-ffff
map address=60-7d,e0-ff:0000-ffff map address=60-7d,e0-ff:0000-ffff
board: BSC-1J5M-01 board: BSC-1J5M-01
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff map address=00-1f,80-9f:8000-ffff
map address=40-5f,c0-df:0000-ffff map address=40-5f,c0-df:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
bsmemory slot type=BSMemory
map address=20-3f,a0-bf:8000-ffff map address=20-3f,a0-bf:8000-ffff
map address=60-7d,e0-ff:0000-ffff map address=60-7d,e0-ff:0000-ffff
board: BSC-1L3B-01 board: BSC-1L3B-01
sa1 sa1
map address=00-3f,80-bf:2200-23ff map address=00-3f,80-bf:2200-23ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x408000 map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
bwram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff map address=40-4f:0000-ffff
iram memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800 map address=00-3f,80-bf:3000-37ff size=0x800
bsmemory slot type=BSMemory
board: BSC-1L5B-01 board: BSC-1L5B-01
sa1 sa1
map address=00-3f,80-bf:2200-23ff map address=00-3f,80-bf:2200-23ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x408000 map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
bwram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff map address=40-4f:0000-ffff
iram memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800 map address=00-3f,80-bf:3000-37ff size=0x800
bsmemory slot type=BSMemory
board: SGB-R-10 board: SGB-R-10
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
icd revision=2 icd revision=2
map address=00-3f,80-bf:6000-67ff,7000-7fff map address=00-3f,80-bf:6000-67ff,7000-7fff
rom memory type=ROM content=Boot architecture=LR35902
gameboy slot type=GameBoy
board: SHVC-1A0N-(01,02,10,20,30) board: SHVC-1A0N-(01,02,10,20,30)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-1A1B-(04,05,06) board: SHVC-1A1B-(04,05,06)
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A1M-(01,10,11,20) board: SHVC-1A1M-(01,10,11,20)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A3B-(11,12,13) board: SHVC-1A3B-(11,12,13)
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A3B-20 board: SHVC-1A3B-20
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A3M-(10,20,21,30) board: SHVC-1A3M-(10,20,21,30)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A5B-(02,04) board: SHVC-1A5B-(02,04)
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A5M-(01,11,20) board: SHVC-1A5M-(01,11,20)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1B0N-(02,03,10) board: SHVC-1B0N-(02,03,10)
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
necdsp model=uPD7725 frequency=8000000 necdsp model=uPD7725
map address=30-3f,b0-bf:8000-ffff mask=0x3fff map address=30-3f,b0-bf:8000-ffff mask=0x3fff
prom memory type=ROM content=Program architecture=uPD7725
drom memory type=ROM content=Data architecture=uPD7725
dram memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1B5B-02 board: SHVC-1B5B-02
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff map address=70-7d,f0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000 necdsp model=uPD7725
map address=20-3f,a0-bf:8000-ffff mask=0x3fff map address=20-3f,a0-bf:8000-ffff mask=0x3fff
prom memory type=ROM content=Program architecture=uPD7725
drom memory type=ROM content=Data architecture=uPD7725
dram memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1C0N board: SHVC-1C0N
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=60-7d,e0-ff:0000-ffff map address=60-7d,e0-ff:0000-ffff
board: SHVC-1C0N5S-01 board: SHVC-1C0N5S-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000 map address=00-1f,80-9f:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=60-7d,e0-ff:0000-ffff map address=60-7d,e0-ff:0000-ffff
board: SHVC-1CA0N5S-01 board: SHVC-1CA0N5S-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff map address=40-5f,c0-df:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff map address=70-71,f0-f1:0000-ffff
board: SHVC-1CA0N6S-01 board: SHVC-1CA0N6S-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff map address=40-5f,c0-df:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff map address=70-71,f0-f1:0000-ffff
board: SHVC-1CA6B-01 board: SHVC-1CA6B-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff map address=40-5f,c0-df:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff map address=70-71,f0-f1:0000-ffff
board: SHVC-1CB0N7S-01 board: SHVC-1CB0N7S-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000 map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff map address=40-5f:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff map address=70-71:0000-ffff
board: SHVC-1CB5B-20 board: SHVC-1CB5B-20
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000 map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff map address=40-5f:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff map address=70-71:0000-ffff
board: SHVC-1CB7B-01 board: SHVC-1CB7B-01
superfx superfx
map address=00-3f,80-bf:3000-34ff map address=00-3f,80-bf:3000-34ff
rom memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000 map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff map address=40-5f:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff map address=70-71:0000-ffff
board: SHVC-1DC0N-01 board: SHVC-1DC0N-01
hitachidsp model=HG51B169 frequency=20000000 hitachidsp model=HG51BS169
map address=00-3f,80-bf:6c00-6fff,7c00-7fff map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff map address=70-77:0000-7fff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
drom memory type=ROM content=Data architecture=HG51BS169
dram memory type=RAM content=Data architecture=HG51BS169
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000 map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
oscillator
board: SHVC-1DS0B-20 board: SHVC-1DS0B-20
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
necdsp model=uPD96050 frequency=11000000 necdsp model=uPD96050
map address=60-67,e0-e7:0000-3fff map address=60-67,e0-e7:0000-3fff
prom memory type=ROM content=Program architecture=uPD96050
drom memory type=ROM content=Data architecture=uPD96050
dram memory type=RAM content=Data architecture=uPD96050
map address=68-6f,e8-ef:0000-7fff mask=0x8000 map address=68-6f,e8-ef:0000-7fff mask=0x8000
oscillator
board: SHVC-1J0N-(01,10,20) board: SHVC-1J0N-(01,10,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
board: SHVC-1J1M-(11,20) board: SHVC-1J1M-(11,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J3B-01 board: SHVC-1J3B-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J3M-(01,11,20) board: SHVC-1J3M-(01,11,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J5M-(01,11,20) board: SHVC-1J5M-(01,11,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1K0N-01 board: SHVC-1K0N-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000 necdsp model=uPD7725
map address=00-1f,80-9f:6000-7fff mask=0xfff map address=00-1f,80-9f:6000-7fff mask=0xfff
prom memory type=ROM content=Program architecture=uPD7725
drom memory type=ROM content=Data architecture=uPD7725
dram memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1K1B-01 board: SHVC-1K1B-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
necdsp model=uPD7725 frequency=8000000 necdsp model=uPD7725
map address=00-1f,80-9f:6000-7fff mask=0xfff map address=00-1f,80-9f:6000-7fff mask=0xfff
prom memory type=ROM content=Program architecture=uPD7725
drom memory type=ROM content=Data architecture=uPD7725
dram memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1L0N3S-01 board: SHVC-1L0N3S-01
sa1 sa1
map address=00-3f,80-bf:2200-23ff map address=00-3f,80-bf:2200-23ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x408000 map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
bwram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff map address=40-4f:0000-ffff
iram memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800 map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1L3B-(02,11) board: SHVC-1L3B-(02,11)
sa1 sa1
map address=00-3f,80-bf:2200-23ff map address=00-3f,80-bf:2200-23ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x408000 map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
bwram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff map address=40-4f:0000-ffff
iram memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800 map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1L5B-(11,20) board: SHVC-1L5B-(11,20)
sa1 sa1
map address=00-3f,80-bf:2200-23ff map address=00-3f,80-bf:2200-23ff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x408000 map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
bwram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000 map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff map address=40-4f:0000-ffff
iram memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800 map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1N0N-(01,10) board: SHVC-1N0N-(01,10)
sdd1 sdd1
map address=00-3f,80-bf:4800-480f map address=00-3f,80-bf:4800-480f
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
board: SHVC-2A0N-01#R board: SHVC-2A0N-01#A
rom memory type=ROM content=Program
map address=00-2f,80-af:8000-ffff mask=0x8000 map address=00-2f,80-af:8000-ffff mask=0x8000
map address=40-6f,c0-ef:0000-ffff mask=0x8000 map address=40-6f,c0-ef:0000-ffff mask=0x8000
board: SHVC-2A0N-(01,10,11,20) board: SHVC-2A0N-(01,10,11,20)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-2A1M-01 board: SHVC-2A1M-01
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3B-01 board: SHVC-2A3B-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3M-01#R board: SHVC-2A3M-01#A
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3M-(01,11,20) board: SHVC-2A3M-(01,11,20)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A5M-01 board: SHVC-2A5M-01
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2B3B-01 board: SHVC-2B3B-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
necdsp model=uPD7725 frequency=8000000 necdsp model=uPD7725
map address=60-6f,e0-ef:0000-7fff mask=0x3fff map address=60-6f,e0-ef:0000-7fff mask=0x3fff
prom memory type=ROM content=Program architecture=uPD7725
drom memory type=ROM content=Data architecture=uPD7725
dram memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-2DC0N-01 board: SHVC-2DC0N-01
hitachidsp model=HG51B169 frequency=20000000 hitachidsp model=HG51BS169
map address=00-3f,80-bf:6c00-6fff,7c00-7fff map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff map address=70-77:0000-7fff
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
drom memory type=ROM content=Data architecture=HG51BS169
dram memory type=RAM content=Data architecture=HG51BS169
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000 map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
oscillator
board: SHVC-2E3M-01 board: SHVC-2E3M-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000 map address=00-3f,80-bf:8000-ffff mask=0x8000
obc1 obc1
map address=00-3f,80-bf:6000-7fff mask=0xe000 map address=00-3f,80-bf:6000-7fff mask=0xe000
map address=70-71,f0-f1:6000-7fff,e000-ffff mask=0xe000 map address=70-71,f0-f1:6000-7fff,e000-ffff mask=0xe000
ram memory type=RAM content=Save
board: SHVC-2J0N-(01,10,11,20) board: SHVC-2J0N-(01,10,11,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
board: SHVC-2J3M-(01,11,20) board: SHVC-2J3M-(01,11,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000 map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: SHVC-2J5M-01 board: SHVC-2J5M-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000 map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: SHVC-3J0N-01 board: SHVC-3J0N-01
rom memory type=ROM content=Program
map address=00-2f,80-af:8000-ffff map address=00-2f,80-af:8000-ffff
map address=40-6f,c0-ef:0000-ffff map address=40-6f,c0-ef:0000-ffff
board: SHVC-BA0N-(01,10) board: SHVC-BA0N-(01,10)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-BA1M-01 board: SHVC-BA1M-01
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-BA3M-(01,10) board: SHVC-BA3M-(01,10)
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
ram memory type=RAM content=Save
map address=70-7d,f0-ff:0000-7fff mask=0x8000 map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-BJ0N-(01,20) board: SHVC-BJ0N-(01,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
board: SHVC-BJ1M-(10,20) board: SHVC-BJ1M-(10,20)
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-BJ3M-10 board: SHVC-BJ3M-10
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=20-3f,a0-bf:6000-7fff mask=0xe000 map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-LDH3C-01 board: SHVC-LDH3C-01
@ -493,40 +501,41 @@ board: SHVC-LDH3C-01
map address=50,58:0000-ffff map address=50,58:0000-ffff
map=mcu address=00-3f,80-bf:8000-ffff mask=0x800000 map=mcu address=00-3f,80-bf:8000-ffff mask=0x800000
map=mcu address=c0-ff:0000-ffff mask=0xc00000 map=mcu address=c0-ff:0000-ffff mask=0xc00000
prom memory type=ROM content=Program
drom memory type=ROM content=Data
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff mask=0xe000 map address=00-3f,80-bf:6000-7fff mask=0xe000
epsonrtc epsonrtc
map address=00-3f,80-bf:4840-4842 map address=00-3f,80-bf:4840-4842
ram memory type=RTC content=Time manufacturer=Epson
board: SHVC-LN3B-01 board: SHVC-LN3B-01
sdd1 sdd1
map address=00-3f,80-bf:4800-480f map address=00-3f,80-bf:4800-480f
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff map address=c0-ff:0000-ffff
ram memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff mask=0xe000 map address=00-3f,80-bf:6000-7fff mask=0xe000
map address=70-73:0000-ffff map address=70-73:0000-ffff
board: SHVC-SGB2-01 board: SHVC-SGB2-01
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
icd revision=2 frequency=20971520 icd revision=2
map address=00-3f,80-bf:6000-67ff,7000-7fff map address=00-3f,80-bf:6000-67ff,7000-7fff
rom memory type=ROM content=Boot architecture=LR35902
gameboy oscillator
slot type=GameBoy
board: SHVC-YA0N-01 board: SHVC-YA0N-01
rom memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000 map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000 map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-YJ0N-01 board: SHVC-YJ0N-01
rom memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff map address=40-7d,c0-ff:0000-ffff

View File

@ -62,60 +62,50 @@ auto Cartridge::load() -> bool {
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
if(auto node = document["board/rom"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.name = node["name"].text(); rom.size = memory.size;
rom.size = node["size"].natural();
rom.mask = bit::round(rom.size) - 1; rom.mask = bit::round(rom.size) - 1;
if(rom.size) {
rom.data = new uint8[rom.mask + 1]; rom.data = new uint8[rom.mask + 1];
memory::fill(rom.data, rom.mask + 1, 0xff); memory::fill(rom.data, rom.mask + 1, 0xff);
if(rom.name) if(auto fp = platform->open(pathID(), rom.name, File::Read, File::Required)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read, File::Required)) {
fp->read(rom.data, rom.size); fp->read(rom.data, rom.size);
} }
} }
}
if(auto node = document["board/ram"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(node["type"].text() == "sram") { ram.size = memory.size;
ram.name = node["name"].text();
ram.size = node["size"].natural();
ram.mask = bit::round(ram.size) - 1; ram.mask = bit::round(ram.size) - 1;
if(ram.size) {
ram.data = new uint8[ram.mask + 1]; ram.data = new uint8[ram.mask + 1];
memory::fill(ram.data, ram.mask + 1, 0xff); memory::fill(ram.data, ram.mask + 1, 0xff);
if(ram.name) if(auto fp = platform->open(pathID(), ram.name, File::Read)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(ram.data, ram.size); fp->read(ram.data, ram.size);
} }
} }
} }
if(node["type"].text() == "eeprom") { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) {
eeprom.setName(node["name"].text()); eeprom.setSize(memory.size / sizeof(uint16));
eeprom.setSize(node["size"].natural() / sizeof(uint16));
if(eeprom.size()) {
eeprom.erase(); eeprom.erase();
if(eeprom.name()) if(auto fp = platform->open(pathID(), eeprom.name(), File::Read)) { if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(eeprom.data(), eeprom.size()); fp->read(eeprom.data(), eeprom.size());
} }
} }
}
}
if(auto node = document["board/rtc"]) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
rtc.name = node["name"].text(); rtc.size = memory.size;
rtc.size = node["size"].natural();
rtc.mask = bit::round(rtc.size) - 1; rtc.mask = bit::round(rtc.size) - 1;
if(rtc.size) {
rtc.data = new uint8[rtc.mask + 1]; rtc.data = new uint8[rtc.mask + 1];
memory::fill(rtc.data, rtc.mask + 1, 0x00); memory::fill(rtc.data, rtc.mask + 1, 0x00);
if(rtc.name) if(auto fp = platform->open(pathID(), rtc.name, File::Read)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Read)) {
fp->read(rtc.data, rtc.size); fp->read(rtc.data, rtc.size);
} }
} }
} }
information.title = document["information/title"].text(); information.title = document["game/label"].text();
information.orientation = document["information/orientation"].text() == "vertical"; information.orientation = document["game/orientation"].text() == "vertical";
information.sha256 = Hash::SHA256(rom.data, rom.size).digest(); information.sha256 = Hash::SHA256(rom.data, rom.size).digest();
return true; return true;
} }
@ -123,43 +113,44 @@ auto Cartridge::load() -> bool {
auto Cartridge::save() -> void { auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest); auto document = BML::unserialize(information.manifest);
if(auto name = document["board/ram/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(ram.data, ram.size); fp->write(ram.data, ram.size);
} }
} }
}
if(auto name = document["board/eeprom/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(eeprom.data(), eeprom.size()); fp->write(eeprom.data(), eeprom.size());
} }
} }
if(auto name = document["board/rtc/name"].text()) { if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
if(auto fp = platform->open(pathID(), name, File::Write)) { if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(rtc.data, rtc.size); fp->write(rtc.data, rtc.size);
} }
} }
} }
}
auto Cartridge::unload() -> void { auto Cartridge::unload() -> void {
delete[] rom.data; delete[] rom.data;
rom.data = nullptr; rom.data = nullptr;
rom.size = 0; rom.size = 0;
rom.mask = 0; rom.mask = 0;
rom.name = "";
delete[] ram.data; delete[] ram.data;
ram.data = nullptr; ram.data = nullptr;
ram.size = 0; ram.size = 0;
ram.mask = 0; ram.mask = 0;
ram.name = "";
delete[] rtc.data; delete[] rtc.data;
rtc.data = nullptr; rtc.data = nullptr;
rtc.size = 0; rtc.size = 0;
rtc.mask = 0; rtc.mask = 0;
rtc.name = "";
} }
} }

View File

@ -66,7 +66,6 @@ struct Cartridge : Thread, IO {
uint8* data = nullptr; uint8* data = nullptr;
uint size = 0; uint size = 0;
uint mask = 0; uint mask = 0;
string name;
}; };
struct RTC : Memory { struct RTC : Memory {

View File

@ -4,14 +4,9 @@ namespace WonderSwan {
#include "serialization.cpp" #include "serialization.cpp"
auto EEPROM::name() const -> string { return _name; }
auto EEPROM::data() -> uint16* { return _data; } auto EEPROM::data() -> uint16* { return _data; }
auto EEPROM::size() const -> uint { return _size; } auto EEPROM::size() const -> uint { return _size; }
auto EEPROM::setName(string name) -> void {
_name = name;
}
auto EEPROM::setSize(uint size) -> void { auto EEPROM::setSize(uint size) -> void {
_size = bit::round(size); _size = bit::round(size);
} }

View File

@ -14,7 +14,6 @@ struct EEPROM {
Command = Status, Command = Status,
}; };
auto name() const -> string;
auto data() -> uint16*; auto data() -> uint16*;
auto size() const -> uint; auto size() const -> uint;
@ -34,7 +33,6 @@ struct EEPROM {
private: private:
auto execute() -> void; auto execute() -> void;
string _name;
uint16 _data[1024]; uint16 _data[1024];
uint _size = 0; //in words uint _size = 0; //in words

View File

@ -28,12 +28,11 @@ auto System::load(Emulator::Interface* interface, Model model) -> bool {
//note: IPLROM is currently undumped; otherwise we'd load it here ... //note: IPLROM is currently undumped; otherwise we'd load it here ...
if(auto node = document["system/eeprom"]) { if(auto node = document["system/eeprom"]) {
eeprom.setName(node["name"].text());
eeprom.setSize(node["size"].natural() / sizeof(uint16)); eeprom.setSize(node["size"].natural() / sizeof(uint16));
eeprom.erase(); eeprom.erase();
//initialize user-data section //initialize user-data section
for(uint addr = 0x0030; addr <= 0x003a; addr++) eeprom[addr] = 0x0000; for(uint addr = 0x0030; addr <= 0x003a; addr++) eeprom[addr] = 0x0000;
if(auto fp = platform->open(ID::System, eeprom.name(), File::Read)) { if(auto fp = platform->open(ID::System, node["name"].text(), File::Read)) {
fp->read(eeprom.data(), eeprom.size()); fp->read(eeprom.data(), eeprom.size());
} }
} }
@ -55,7 +54,6 @@ auto System::save() -> void {
auto System::unload() -> void { auto System::unload() -> void {
if(!loaded()) return; if(!loaded()) return;
eeprom.setName("");
eeprom.setSize(0); eeprom.setSize(0);
cartridge.unload(); cartridge.unload();

View File

@ -1,10 +1,10 @@
database database
revision: 2018-03-13 revision: 2018-04-15
//BS Memory (JPN) //BS Memory (JPN)
database database
revision: 2018-02-12 revision: 2018-04-14
game game
sha256: 80c34b50817d58820bc8c88d2d9fa462550b4a76372e19c6467cbfbc8cf5d9ef sha256: 80c34b50817d58820bc8c88d2d9fa462550b4a76372e19c6467cbfbc8cf5d9ef
@ -16,7 +16,7 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
game game
sha256: 859c7f7b4771d920a5bdb11f1d247ab6b43fb026594d1062f6f72d32cd340a0a sha256: 859c7f7b4771d920a5bdb11f1d247ab6b43fb026594d1062f6f72d32cd340a0a
@ -28,7 +28,7 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
game game
sha256: c92a15fdd9b0133f9ea69105d0230a3acd1cdeef98567462eca86ea02a959e4e sha256: c92a15fdd9b0133f9ea69105d0230a3acd1cdeef98567462eca86ea02a959e4e
@ -40,5 +40,5 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program

View File

@ -1,10 +1,10 @@
database database
revision: 2018-03-13 revision: 2018-04-15
//Sufami Turbo (JPN) //Sufami Turbo (JPN)
database database
revision: 2018-02-12 revision: 2018-04-14
game game
sha256: f73bda08743565e0bd101632ebbac2d363d703a3ab39d23f49d95217cab29269 sha256: f73bda08743565e0bd101632ebbac2d363d703a3ab39d23f49d95217cab29269
@ -16,7 +16,7 @@ game
memory memory
type: ROM type: ROM
size: 0x100000 size: 0x100000
category: Program content: Program
note: Unlinkable note: Unlinkable
game game
@ -29,7 +29,7 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
note: Unlinkable note: Unlinkable
game game
@ -42,7 +42,7 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
note: Unlinkable note: Unlinkable
game game
@ -55,7 +55,7 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
note: Unlinkable note: Unlinkable
game game
@ -68,12 +68,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x800 size: 0x800
category: Save content: Save
note: Linkable: SFT-0103-JPN note: Linkable: SFT-0103-JPN
game game
@ -86,12 +85,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -104,12 +102,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -122,12 +119,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -140,12 +136,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -158,12 +153,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -176,12 +170,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x2000 size: 0x2000
category: Save content: Save
note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN note: Linkable: SFT-0104-JPN, SFT-0105-JPN, SFT-0107-JPN, SFT-0108-JPN, SFT-0110-JPN, SFT-0111-JPN
game game
@ -194,12 +187,11 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x800 size: 0x800
category: Save content: Save
note: Linkable: SFT-0101-JPN, SFT-0102-JPN note: Linkable: SFT-0101-JPN, SFT-0102-JPN
game game
@ -212,11 +204,10 @@ game
memory memory
type: ROM type: ROM
size: 0x80000 size: 0x80000
category: Program content: Program
memory memory
type: RAM type: RAM
battery
size: 0x800 size: 0x800
category: Save content: Save
note: Linkable: SFT-0101-JPN, SFT-0102-JPN note: Linkable: SFT-0101-JPN, SFT-0102-JPN

File diff suppressed because it is too large Load Diff

View File

@ -162,10 +162,10 @@ auto Famicom::manifest() const -> string {
} }
if(prgrom) output.append(Memory{}.type("ROM").size(prgrom).content("Program").text()); if(prgrom) output.append(Memory{}.type("ROM").size(prgrom).content("Program").text());
if(prgram) output.append(Memory{}.type("RAM").size(prgram).content("Save").battery().text()); if(prgram) output.append(Memory{}.type("RAM").size(prgram).content("Save").text());
if(chrrom) output.append(Memory{}.type("ROM").size(chrrom).content("Character").text()); if(chrrom) output.append(Memory{}.type("ROM").size(chrrom).content("Character").text());
if(chrram) output.append(Memory{}.type("RAM").size(chrram).content("Character").text()); if(chrram) output.append(Memory{}.type("RAM").size(chrram).content("Character").isVolatile().text());
return output; return output;
} }

View File

@ -58,9 +58,9 @@ auto GameBoyAdvance::manifest() const -> string {
else if(list.left().beginsWith("SRAM_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text()); else if(list.left().beginsWith("SRAM_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text());
else if(list.left().beginsWith("SRAM_F_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text()); else if(list.left().beginsWith("SRAM_F_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).content("Save").text());
else if(list.left().beginsWith("EEPROM_V" )) output.append(Memory{}.type("EEPROM").size( 0x0).content("Save").text()); else if(list.left().beginsWith("EEPROM_V" )) output.append(Memory{}.type("EEPROM").size( 0x0).content("Save").text());
else if(list.left().beginsWith("FLASH_V" )) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").text()); else if(list.left().beginsWith("FLASH_V" )) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").manufacturer("Macronix").text());
else if(list.left().beginsWith("FLASH512_V")) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").text()); else if(list.left().beginsWith("FLASH512_V")) output.append(Memory{}.type("Flash" ).size(0x10000).content("Save").manufacturer("Macronix").text());
else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).content("Save").text()); else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).content("Save").manufacturer("Macronix").text());
return output; return output;
} }

View File

@ -242,12 +242,14 @@ auto GameBoy::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n"); output.append(" name: ", Location::prefix(location), "\n");
output.append(" board: ", mapper, "\n"); output.append(" board: ", mapper, "\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
if(ram && ramSize) if(ram && ramSize && battery)
output.append(Memory{}.type("RAM").size(ramSize).content("Save").battery(battery).text()); output.append(Memory{}.type("RAM").size(ramSize).content("Save").text());
if(ram && ramSize && !battery)
output.append(Memory{}.type("RAM").size(ramSize).content("Save").isVolatile().text());
if(flash && flashSize) if(flash && flashSize)
output.append(Memory{}.type("Flash").size(flashSize).content("Download").text()); output.append(Memory{}.type("Flash").size(flashSize).content("Download").text());
if(rtc && rtcSize) if(rtc && rtcSize)
output.append(Memory{}.type("RTC").size(rtcSize).content("Time").battery().text()); output.append(Memory{}.type("RTC").size(rtcSize).content("Time").text());
if(accelerometer) if(accelerometer)
output.append(" accelerometer\n"); output.append(" accelerometer\n");
if(rumble) if(rumble)

View File

@ -25,7 +25,7 @@ auto GameGear::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n"); output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n"); output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
output.append(Memory{}.type("RAM").size(0x8000).content("Save").battery().text()); output.append(Memory{}.type("RAM").size(0x8000).content("Save").text());
return output; return output;
} }

View File

@ -4,8 +4,6 @@ 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(" content: ", _content, "\n"); output.append(" content: ", _content, "\n");
if(_manufacturer) if(_manufacturer)
@ -14,6 +12,8 @@ if(_architecture)
output.append(" architecture: ", _architecture, "\n"); output.append(" architecture: ", _architecture, "\n");
if(_identifier) if(_identifier)
output.append(" identifier: ", _identifier, "\n"); output.append(" identifier: ", _identifier, "\n");
if(_volatile)
output.append(" volatile\n");
return output; return output;
} }

View File

@ -2,12 +2,12 @@ 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& content(string content) { _content = content; return *this; } auto& content(string content) { _content = content; return *this; }
auto& manufacturer(string manufacturer) { _manufacturer = manufacturer; return *this; } auto& manufacturer(string manufacturer) { _manufacturer = manufacturer; return *this; }
auto& architecture(string architecture) { _architecture = architecture; return *this; } auto& architecture(string architecture) { _architecture = architecture; return *this; }
auto& identifier(string identifier) { _identifier = identifier; return *this; } auto& identifier(string identifier) { _identifier = identifier; return *this; }
auto& isVolatile() { _volatile = true; return *this; }
auto text() const -> string; auto text() const -> string;
string _type; string _type;
@ -17,6 +17,7 @@ struct Memory {
string _manufacturer; string _manufacturer;
string _architecture; string _architecture;
string _identifier; string _identifier;
boolean _volatile;
}; };
struct Oscillator { struct Oscillator {

View File

@ -25,7 +25,7 @@ auto MasterSystem::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n"); output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n"); output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
output.append(Memory{}.type("RAM").size(0x8000).content("Save").battery().text()); output.append(Memory{}.type("RAM").size(0x8000).content("Save").text());
return output; return output;
} }

View File

@ -32,7 +32,7 @@ auto SufamiTurbo::manifest() const -> string {
output.append(" board\n"); output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
if(ramSize) if(ramSize)
output.append(Memory{}.type("RAM").size(ramSize).content("Save").battery().text()); output.append(Memory{}.type("RAM").size(ramSize).content("Save").text());
return output; return output;
} }

View File

@ -13,7 +13,7 @@ struct SuperFamicom {
auto romSize() const -> uint; auto romSize() const -> uint;
auto ramSize() const -> uint; auto ramSize() const -> uint;
auto expansionRamSize() const -> uint; auto expansionRamSize() const -> uint;
auto battery() const -> bool; auto nonVolatile() const -> bool;
private: private:
auto size() const -> uint { return data.size(); } auto size() const -> uint { return data.size(); }
@ -72,29 +72,29 @@ auto SuperFamicom::manifest() const -> string {
} }
if(auto size = ramSize()) { if(auto size = ramSize()) {
output.append(Memory{}.type("RAM").size(size).content("Save").battery(battery()).text()); output.append(Memory{}.type("RAM").size(size).content("Save").text());
} }
if(auto size = expansionRamSize()) { if(auto size = expansionRamSize()) {
output.append(Memory{}.type("RAM").size(size).content("Save").battery(battery()).text()); output.append(Memory{}.type("RAM").size(size).content("Save").text());
} }
if(0) { if(0) {
} else if(board(0) == "ARM") { } else if(board(0) == "ARM") {
output.append(Memory{}.type("ROM").size(0x20000).content("Program").manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text()); output.append(Memory{}.type("ROM").size(0x20000).content("Program").manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text());
output.append(Memory{}.type("ROM").size( 0x8000).content("Data" ).manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text()); output.append(Memory{}.type("ROM").size( 0x8000).content("Data" ).manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text());
output.append(Memory{}.type("RAM").size( 0x4000).content("Data" ).manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).text()); output.append(Memory{}.type("RAM").size( 0x4000).content("Data" ).manufacturer("SETA").architecture("ARM6").identifier(firmwareARM()).isVolatile().text());
output.append(Oscillator{}.frequency(21'440'000).text()); output.append(Oscillator{}.frequency(21'440'000).text());
} else if(board(0) == "BS" && board(1) == "MCC") { } else if(board(0) == "BS" && board(1) == "MCC") {
output.append(Memory{}.type("RAM").size(0x80000).content("Download").battery().text()); output.append(Memory{}.type("RAM").size(0x80000).content("Download").text());
} else if(board(0) == "HITACHI") { } else if(board(0) == "HITACHI") {
output.append(Memory{}.type("ROM").size(0xc00).content("Data").manufacturer("Hitachi").architecture("HG51BS169").identifier(firmwareHITACHI()).text()); output.append(Memory{}.type("ROM").size(0xc00).content("Data").manufacturer("Hitachi").architecture("HG51BS169").identifier(firmwareHITACHI()).text());
output.append(Memory{}.type("RAM").size(0xc00).content("Data").manufacturer("Hitachi").architecture("HG51BS169").identifier(firmwareHITACHI()).text()); output.append(Memory{}.type("RAM").size(0xc00).content("Data").manufacturer("Hitachi").architecture("HG51BS169").identifier(firmwareHITACHI()).isVolatile().text());
output.append(Oscillator{}.frequency(20'000'000).text()); output.append(Oscillator{}.frequency(20'000'000).text());
} else if(board(0) == "NEC") { } else if(board(0) == "NEC") {
output.append(Memory{}.type("ROM").size(0x1800).content("Program").manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).text()); output.append(Memory{}.type("ROM").size(0x1800).content("Program").manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).text());
output.append(Memory{}.type("ROM").size( 0x800).content("Data" ).manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).text()); output.append(Memory{}.type("ROM").size( 0x800).content("Data" ).manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).text());
output.append(Memory{}.type("RAM").size( 0x200).content("Data" ).manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).text()); output.append(Memory{}.type("RAM").size( 0x200).content("Data" ).manufacturer("NEC").architecture("uPD7725").identifier(firmwareNEC()).isVolatile().text());
output.append(Oscillator{}.frequency(7'600'000).text()); output.append(Oscillator{}.frequency(7'600'000).text());
} else if(board(0) == "NECEX") { } else if(board(0) == "NECEX") {
output.append(Memory{}.type("ROM").size(0xc000).content("Program").manufacturer("NEC").architecture("uPD96050").identifier(firmwareNECEX()).text()); output.append(Memory{}.type("ROM").size(0xc000).content("Program").manufacturer("NEC").architecture("uPD96050").identifier(firmwareNECEX()).text());
@ -102,9 +102,9 @@ auto SuperFamicom::manifest() const -> string {
output.append(Memory{}.type("RAM").size(0x1000).content("Data" ).manufacturer("NEC").architecture("uPD96050").identifier(firmwareNECEX()).text()); output.append(Memory{}.type("RAM").size(0x1000).content("Data" ).manufacturer("NEC").architecture("uPD96050").identifier(firmwareNECEX()).text());
output.append(Oscillator{}.frequency(firmwareNECEX() == "ST010" ? 11'000'000 : 15'000'000).text()); output.append(Oscillator{}.frequency(firmwareNECEX() == "ST010" ? 11'000'000 : 15'000'000).text());
} else if(board(0) == "RTC") { } else if(board(0) == "RTC") {
output.append(Memory{}.type("RTC").size(0x10).content("Time").battery().text()); output.append(Memory{}.type("RTC").size(0x10).content("Time").text());
} else if(board(0) == "SA1") { } else if(board(0) == "SA1") {
output.append(Memory{}.type("RAM").size(0x800).content("Internal").text()); output.append(Memory{}.type("RAM").size(0x800).content("Internal").isVolatile().text());
} else if(board(0) == "SGB") { } else if(board(0) == "SGB") {
output.append(Memory{}.type("ROM").size(0x100).content("Boot").manufacturer("Nintendo").architecture("LR35902").identifier(firmwareSGB()).text()); output.append(Memory{}.type("ROM").size(0x100).content("Boot").manufacturer("Nintendo").architecture("LR35902").identifier(firmwareSGB()).text());
if(firmwareSGB() == "SGB2") if(firmwareSGB() == "SGB2")
@ -112,7 +112,7 @@ auto SuperFamicom::manifest() const -> string {
} else if(board(0) == "SPC7110") { } else if(board(0) == "SPC7110") {
output.append(Memory{}.type("ROM").size(romSize() - 0x100000).content("Data").text()); output.append(Memory{}.type("ROM").size(romSize() - 0x100000).content("Data").text());
if(board(1) == "RTC") if(board(1) == "RTC")
output.append(Memory{}.type("RTC").size(0x10).content("Time").battery().text()); output.append(Memory{}.type("RTC").size(0x10).content("Time").text());
} else if(board(0) == "SUPERFX") { } else if(board(0) == "SUPERFX") {
//todo: MARIO CHIP 1 uses CPU oscillator //todo: MARIO CHIP 1 uses CPU oscillator
output.append(Oscillator{}.frequency(21'440'000).text()); output.append(Oscillator{}.frequency(21'440'000).text());
@ -411,7 +411,7 @@ auto SuperFamicom::expansionRamSize() const -> uint {
return 0; return 0;
} }
auto SuperFamicom::battery() const -> bool { auto SuperFamicom::nonVolatile() const -> bool {
auto cartridgeTypeLo = data[headerAddress + 0x26] & 15; auto cartridgeTypeLo = data[headerAddress + 0x26] & 15;
return cartridgeTypeLo == 0x2 || cartridgeTypeLo == 0x5 || cartridgeTypeLo == 0x6; return cartridgeTypeLo == 0x2 || cartridgeTypeLo == 0x5 || cartridgeTypeLo == 0x6;
} }

View File

@ -49,7 +49,7 @@ auto WonderSwan::manifest() const -> string {
output.append(" board\n"); output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text()); output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
if(ramType && ramSize) if(ramType && ramSize)
output.append(Memory{}.type(ramType).size(ramSize).content("Save").battery(ramType == "RAM").text()); output.append(Memory{}.type(ramType).size(ramSize).content("Save").text());
if(hasRTC) if(hasRTC)
output.append(Memory{}.type("RTC").size(0x10).content("Time").text()); output.append(Memory{}.type("RTC").size(0x10).content("Time").text());
return output; return output;

View File

@ -34,7 +34,7 @@ auto ManagedNode::_evaluate(string query) const -> bool {
if(side(0)) { if(side(0)) {
auto result = _find(side(0)); auto result = _find(side(0));
if(result.size() == 0) return false; if(result.size() == 0) return false;
data = result[0].value(); data = result[0].text(); //strips whitespace so rules can match without requiring it
} }
switch(comparator) { switch(comparator) {