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();
updateWindow();
setCentered();
setVisible();
}
auto ListWindow::quit() -> void {
@ -127,12 +126,12 @@ auto ListWindow::loadDatabase(string location) -> void {
if(object.name() == "memory") {
component.type = Component::Type::Memory;
component.memory.type = object["type"].text();
component.memory.battery = (bool)object["type/battery"];
component.memory.size = object["size"].text();
component.memory.content = object["content"].text();
component.memory.manufacturer = object["manufacturer"].text();
component.memory.architecture = object["architecture"].text();
component.memory.identifier = object["identifier"].text();
component.memory.Volatile = (bool)object["volatile"];
}
if(object.name() == "oscillator") {
component.type = Component::Type::Oscillator;
@ -184,8 +183,6 @@ auto ListWindow::saveDatabase(string location) -> void {
if(component.type == Component::Type::Memory) {
fp.print(" memory\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(" content: ", component.memory.content, "\n");
if(component.memory.manufacturer)
@ -194,6 +191,8 @@ auto ListWindow::saveDatabase(string location) -> void {
fp.print(" architecture: ", component.memory.architecture, "\n");
if(component.memory.identifier)
fp.print(" identifier: ", component.memory.identifier, "\n");
if(component.memory.Volatile)
fp.print(" volatile\n");
}
if(component.type == Component::Type::Oscillator) {
@ -367,7 +366,7 @@ auto GameWindow::reloadList() -> void {
string index = {"[", counter++, "] "};
if(component.type == Component::Type::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({"Content: ", component.memory.content}));
if(component.memory.manufacturer)
@ -376,6 +375,8 @@ auto GameWindow::reloadList() -> void {
item.append(TreeViewItem().setText({"Architecture: ", component.memory.architecture}));
if(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) {
@ -473,7 +474,7 @@ MemoryWindow::MemoryWindow() {
architectureEdit.onChange([&] { modified = true, updateWindow(); });
identifierLabel.setText("Identifier:").setAlignment(1.0);
identifierEdit.onChange([&] { modified = true, updateWindow(); });
batteryOption.setText("Battery").onToggle([&] { modified = true, updateWindow(); });
volatileOption.setText("Volatile").onToggle([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
@ -494,7 +495,7 @@ auto MemoryWindow::show(Memory memory) -> void {
manufacturerEdit.setText(memory.manufacturer);
architectureEdit.setText(memory.architecture);
identifierEdit.setText(memory.identifier);
batteryOption.setChecked(memory.battery);
volatileOption.setChecked(memory.Volatile);
updateWindow();
setCentered(*gameWindow);
@ -510,7 +511,7 @@ auto MemoryWindow::accept() -> void {
memory.manufacturer = manufacturerEdit.text().strip();
memory.architecture = architectureEdit.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.memory = memory;
@ -543,7 +544,7 @@ auto MemoryWindow::updateWindow() -> void {
manufacturerEdit.setBackgroundColor(manufacturerEdit.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}));
batteryOption.setEnabled(typeEdit.text().strip() == "RAM" || typeEdit.text().strip() == "RTC");
volatileOption.setEnabled(typeEdit.text().strip() == "RAM" || typeEdit.text().strip() == "RTC");
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
}
@ -615,11 +616,25 @@ auto OscillatorWindow::updateWindow() -> void {
//
#include <nall/main.hpp>
auto nall::main(string_vector) -> void {
auto nall::main(string_vector args) -> void {
Application::setName("genius");
new ListWindow;
new GameWindow;
new MemoryWindow;
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();
}

View File

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

View File

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

View File

@ -11,19 +11,23 @@ struct Game {
inline auto oscillator(natural = 0) -> maybe<Oscillator>;
struct Memory {
Memory() = default;
inline Memory(Markup::Node);
explicit operator bool() const { return type; }
inline auto name() const -> string;
string type;
boolean battery;
natural size;
string content;
string manufacturer;
string architecture;
string identifier;
boolean nonVolatile;
};
struct Oscillator {
Oscillator() = default;
inline Oscillator(Markup::Node);
explicit operator bool() const { return frequency; }
natural frequency;
@ -51,21 +55,11 @@ auto Game::load(string_view text) -> void {
board = document["game/board"].text();
for(auto node : document.find("game/board/memory")) {
Memory memory;
memory.type = node["type"].text();
memory.battery = (bool)node["type/battery"];
memory.size = node["size"].natural();
memory.content = node["content"].text();
memory.manufacturer = node["manufacturer"].text();
memory.architecture = node["architecture"].text();
memory.identifier = node["identifier"].text();
memoryList.append(memory);
memoryList.append(Memory{node});
}
for(auto node : document.find("game/board/oscillator")) {
Oscillator oscillator;
oscillator.frequency = node["frequency"].natural();
oscillatorList.append(oscillator);
oscillatorList.append(Oscillator{node});
}
}
@ -94,9 +88,23 @@ auto Game::oscillator(natural index) -> maybe<Oscillator> {
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 {
if(manufacturer) return string{manufacturer, ".", content, ".", type}.downcase();
if(architecture) return string{architecture, ".", 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) {
cartridge.board = this;
auto board = document["board"];
information.type = document["game/board"].text();
information.type = board["id"].text();
information.battery = (bool)board["prg/ram/name"];
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)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
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)) {
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()));
}
}
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()));
}
}
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()));
}
}
prgram.writable = true;
chrram.writable = true;
}
}
auto Board::save() -> void {
auto document = BML::unserialize(cartridge.manifest());
if(auto name = document["board/prg/ram/name"].text()) {
if(auto fp = platform->open(cartridge.pathID(), name, File::Write)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Write)) {
fp->write(prgram.data, prgram.size);
}
}
}
if(auto name = document["board/chr/ram/name"].text()) {
if(auto fp = platform->open(cartridge.pathID(), name, File::Write)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Character)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(cartridge.pathID(), memory.name(), File::Write)) {
fp->write(chrram.data, chrram.size);
}
}
}
}
auto Board::Memory::read(uint addr) const -> uint8 {
return data[mirror(addr, size)];
@ -138,9 +132,9 @@ auto Board::serialize(serializer& s) -> void {
auto Board::load(string manifest) -> Board* {
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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -223,17 +223,23 @@ auto Cartridge::loadSuperFX(Markup::Node node) -> void {
auto Cartridge::loadARMDSP(Markup::Node node) -> void {
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)) {
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)) {
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)) {
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 {
has.HitachiDSP = true;
hitachidsp.Frequency = node["frequency"].natural();
if(hitachidsp.Frequency == 0) hitachidsp.Frequency = 20'000'000;
if(auto oscillator = game.oscillator()) {
hitachidsp.Frequency = oscillator->frequency;
} else {
hitachidsp.Frequency = 20'000'000;
}
hitachidsp.Roms = roms; //1 or 2
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.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)) {
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)) {
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 {
has.NECDSP = true;
necdsp.Frequency = node["frequency"].natural();
if(necdsp.Frequency == 0) necdsp.Frequency = 8000000;
if(auto oscillator = game.oscillator()) {
necdsp.Frequency = oscillator->frequency;
} else {
necdsp.Frequency = 7'600'000;
}
necdsp.revision
= node["model"].text() == "uPD7725" ? NECDSP::Revision::uPD7725
: 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::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)) {
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 fp = platform->open(ID::SuperFamicom, memory->name(), File::Read, File::Required)) {
if(auto memory = Emulator::Game::Memory{node["memory(type=ROM,content=Data)"]}) {
if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Read, File::Required)) {
for(auto n : range(size[1])) necdsp.dataROM[n] = fp->readl(2);
}
}
if(auto memory = game.memory(node["memory(type=RAM,category=Data"])) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Read)) {
if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) {
if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Read)) {
for(auto n : range(size[2])) necdsp.dataRAM[n] = fp->readl(2);
}
}
@ -314,7 +327,7 @@ auto Cartridge::loadEpsonRTC(Markup::Node node) -> void {
has.EpsonRTC = true;
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)) {
uint8 data[16] = {0};
for(auto& byte : data) byte = fp->read();
@ -329,7 +342,7 @@ auto Cartridge::loadSharpRTC(Markup::Node node) -> void {
has.SharpRTC = true;
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)) {
uint8 data[16] = {0};
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(auto memory = game.memory(node)) {
ram.allocate(memory->size);
if(memory->type == "RAM" && !memory->battery) return;
if(memory->type == "RTC" && !memory->battery) return;
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Read, required)) {
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 {
if(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) {
if(memory->battery) {
if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
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 {
saveMemory(hitachidsp.ram, node["ram"]);
if(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) {
if(memory->battery) {
if(auto memory = game.memory(node["memory(type=RAM,content=Data)"])) {
if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
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 {
uint size = necdsp.revision == NECDSP::Revision::uPD7725 ? 256 : 2048;
if(auto memory = game.memory(node["memory(type=RAM,category=Data)"])) {
if(memory->battery) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
if(auto memory = Emulator::Game::Memory{node["memory(type=RAM,content=Data)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory.name(), File::Write)) {
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 {
if(auto memory = game.memory(node["memory(type=RTC)"])) {
if(memory->battery) {
if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
uint8 data[16] = {0};
epsonrtc.save(data);
@ -97,8 +97,8 @@ auto Cartridge::saveEpsonRTC(Markup::Node node) -> void {
}
auto Cartridge::saveSharpRTC(Markup::Node node) -> void {
if(auto memory = game.memory(node["memory(type=RTC)"])) {
if(memory->battery) {
if(auto memory = game.memory(node["memory(type=RTC,content=Time)"])) {
if(memory->nonVolatile) {
if(auto fp = platform->open(ID::SuperFamicom, memory->name(), File::Write)) {
uint8 data[16] = {0};
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 {
if(!id) id = pathID();
if(auto memory = game.memory(node)) {
if(memory->type == "RAM" && !memory->battery) return;
if(memory->type == "RTC" && !memory->battery) return;
if(memory->type == "RAM" && !memory->nonVolatile) return;
if(memory->type == "RTC" && !memory->nonVolatile) return;
if(auto fp = platform->open(id(), memory->name(), File::Write)) {
fp->write(ram.data(), ram.size());
}

View File

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

View File

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

View File

@ -1,490 +1,498 @@
database
revision: 2018-04-08
revision: 2018-04-15
//Boards (Production)
database
revision: 2018-02-27
revision: 2018-04-10
board: BANDAI-PT-923
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
sufamiturbo
slot type=SufamiTurbo
rom
map address=20-3f,a0-bf:8000-ffff mask=0x8000
ram
map address=60-6f,e0-ef:0000-ffff
sufamiturbo
slot type=SufamiTurbo
rom
map address=40-5f,c0-df:0000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: BSC-1A5M-02
rom
memory type=ROM content=Program
map address=00-1f:8000-ffff mask=0x8000 base=0x000000
map address=20-3f:8000-ffff mask=0x8000 base=0x100000
map address=80-9f:8000-ffff mask=0x8000 base=0x200000
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
bsmemory
slot type=BSMemory
map address=c0-ef:0000-ffff
board: BSC-1A7M-01
rom
memory type=ROM content=Program
map address=00-1f:8000-ffff mask=0x8000 base=0x000000
map address=20-3f:8000-ffff mask=0x8000 base=0x100000
map address=80-9f:8000-ffff mask=0x8000 base=0x200000
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
bsmemory
slot type=BSMemory
map address=c0-ef:0000-ffff
board: BSC-1J3M-01
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-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
bsmemory
slot type=BSMemory
map address=20-3f,a0-bf:8000-ffff
map address=60-7d,e0-ff:0000-ffff
board: BSC-1J5M-01
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-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
bsmemory
slot type=BSMemory
map address=20-3f,a0-bf:8000-ffff
map address=60-7d,e0-ff:0000-ffff
board: BSC-1L3B-01
sa1
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=c0-ff:0000-ffff
bwram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800
bsmemory
slot type=BSMemory
board: BSC-1L5B-01
sa1
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=c0-ff:0000-ffff
bwram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800
bsmemory
slot type=BSMemory
board: SGB-R-10
rom
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
icd revision=2
map address=00-3f,80-bf:6000-67ff,7000-7fff
rom
gameboy
memory type=ROM content=Boot architecture=LR35902
slot type=GameBoy
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=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-1A1B-(04,05,06)
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A1M-(01,10,11,20)
rom
memory type=ROM content=Program
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
board: SHVC-1A3B-(11,12,13)
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A3B-20
rom
memory type=ROM content=Program
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
board: SHVC-1A3M-(10,20,21,30)
rom
memory type=ROM content=Program
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
board: SHVC-1A5B-(02,04)
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A5M-(01,11,20)
rom
memory type=ROM content=Program
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
board: SHVC-1B0N-(02,03,10)
rom
memory type=ROM content=Program
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
prom
drom
dram
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1B5B-02
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
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
prom
drom
dram
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1C0N
superfx
map address=00-3f,80-bf:3000-34ff
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
map address=60-7d,e0-ff:0000-ffff
board: SHVC-1C0N5S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
memory type=ROM content=Program
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
memory type=RAM content=Save
map address=60-7d,e0-ff:0000-ffff
board: SHVC-1CA0N5S-01
superfx
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=40-5f,c0-df:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: SHVC-1CA0N6S-01
superfx
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=40-5f,c0-df:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: SHVC-1CA6B-01
superfx
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=40-5f,c0-df:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: SHVC-1CB0N7S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: SHVC-1CB5B-20
superfx
map address=00-3f,80-bf:3000-34ff
rom
memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: SHVC-1CB7B-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
memory type=ROM content=Program
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: SHVC-1DC0N-01
hitachidsp model=HG51B169 frequency=20000000
hitachidsp model=HG51BS169
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
memory type=ROM content=Data architecture=HG51BS169
memory type=RAM content=Data architecture=HG51BS169
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
oscillator
board: SHVC-1DS0B-20
rom
memory type=ROM content=Program
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
prom
drom
dram
memory type=ROM content=Program architecture=uPD96050
memory type=ROM content=Data architecture=uPD96050
memory type=RAM content=Data architecture=uPD96050
map address=68-6f,e8-ef:0000-7fff mask=0x8000
oscillator
board: SHVC-1J0N-(01,10,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-1J1M-(11,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-1J3B-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-1J3M-(01,11,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-1J5M-(01,11,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-1K0N-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
prom
drom
dram
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1K1B-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
necdsp model=uPD7725 frequency=8000000
necdsp model=uPD7725
map address=00-1f,80-9f:6000-7fff mask=0xfff
prom
drom
dram
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-1L0N3S-01
sa1
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=c0-ff:0000-ffff
bwram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1L3B-(02,11)
sa1
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=c0-ff:0000-ffff
bwram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1L5B-(11,20)
sa1
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=c0-ff:0000-ffff
bwram
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
memory type=RAM content=Internal
map address=00-3f,80-bf:3000-37ff size=0x800
board: SHVC-1N0N-(01,10)
sdd1
map address=00-3f,80-bf:4800-480f
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff
board: SHVC-2A0N-01#R
rom
board: SHVC-2A0N-01#A
memory type=ROM content=Program
map address=00-2f,80-af:8000-ffff mask=0x8000
map address=40-6f,c0-ef:0000-ffff mask=0x8000
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=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-2A1M-01
rom
memory type=ROM content=Program
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
board: SHVC-2A3B-01
rom
memory type=ROM content=Program
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
board: SHVC-2A3M-01#R
rom
board: SHVC-2A3M-01#A
memory type=ROM content=Program
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
board: SHVC-2A3M-(01,11,20)
rom
memory type=ROM content=Program
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
board: SHVC-2A5M-01
rom
memory type=ROM content=Program
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
board: SHVC-2B3B-01
rom
memory type=ROM content=Program
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
necdsp model=uPD7725 frequency=8000000
necdsp model=uPD7725
map address=60-6f,e0-ef:0000-7fff mask=0x3fff
prom
drom
dram
memory type=ROM content=Program architecture=uPD7725
memory type=ROM content=Data architecture=uPD7725
memory type=RAM content=Data architecture=uPD7725
oscillator
board: SHVC-2DC0N-01
hitachidsp model=HG51B169 frequency=20000000
hitachidsp model=HG51BS169
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
memory type=ROM content=Data architecture=HG51BS169
memory type=RAM content=Data architecture=HG51BS169
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
oscillator
board: SHVC-2E3M-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff mask=0x8000
obc1
map address=00-3f,80-bf:6000-7fff 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)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-2J3M-(01,11,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-2J5M-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-3J0N-01
rom
memory type=ROM content=Program
map address=00-2f,80-af:8000-ffff
map address=40-6f,c0-ef:0000-ffff
board: SHVC-BA0N-(01,10)
rom
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-BA1M-01
rom
memory type=ROM content=Program
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
board: SHVC-BA3M-(01,10)
rom
memory type=ROM content=Program
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
board: SHVC-BJ0N-(01,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-BJ1M-(10,20)
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-BJ3M-10
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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
board: SHVC-LDH3C-01
@ -493,40 +501,41 @@ board: SHVC-LDH3C-01
map address=50,58:0000-ffff
map=mcu address=00-3f,80-bf:8000-ffff mask=0x800000
map=mcu address=c0-ff:0000-ffff mask=0xc00000
prom
drom
ram
memory type=ROM content=Program
memory type=ROM content=Data
memory type=RAM content=Save
map address=00-3f,80-bf:6000-7fff mask=0xe000
epsonrtc
map address=00-3f,80-bf:4840-4842
ram
memory type=RTC content=Time manufacturer=Epson
board: SHVC-LN3B-01
sdd1
map address=00-3f,80-bf:4800-480f
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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=70-73:0000-ffff
board: SHVC-SGB2-01
rom
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff 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
rom
gameboy
memory type=ROM content=Boot architecture=LR35902
oscillator
slot type=GameBoy
board: SHVC-YA0N-01
rom
memory type=ROM content=Program
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: SHVC-YJ0N-01
rom
memory type=ROM content=Program
map address=00-3f,80-bf:8000-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);
if(auto node = document["board/rom"]) {
rom.name = node["name"].text();
rom.size = node["size"].natural();
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=ROM,content=Program)"]}) {
rom.size = memory.size;
rom.mask = bit::round(rom.size) - 1;
if(rom.size) {
rom.data = new uint8[rom.mask + 1];
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);
}
}
}
if(auto node = document["board/ram"]) {
if(node["type"].text() == "sram") {
ram.name = node["name"].text();
ram.size = node["size"].natural();
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
ram.size = memory.size;
ram.mask = bit::round(ram.size) - 1;
if(ram.size) {
ram.data = new uint8[ram.mask + 1];
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);
}
}
}
if(node["type"].text() == "eeprom") {
eeprom.setName(node["name"].text());
eeprom.setSize(node["size"].natural() / sizeof(uint16));
if(eeprom.size()) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=EEPROM,content=Save)"]}) {
eeprom.setSize(memory.size / sizeof(uint16));
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());
}
}
}
}
if(auto node = document["board/rtc"]) {
rtc.name = node["name"].text();
rtc.size = node["size"].natural();
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
rtc.size = memory.size;
rtc.mask = bit::round(rtc.size) - 1;
if(rtc.size) {
rtc.data = new uint8[rtc.mask + 1];
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);
}
}
}
information.title = document["information/title"].text();
information.orientation = document["information/orientation"].text() == "vertical";
information.title = document["game/label"].text();
information.orientation = document["game/orientation"].text() == "vertical";
information.sha256 = Hash::SHA256(rom.data, rom.size).digest();
return true;
}
@ -123,43 +113,44 @@ auto Cartridge::load() -> bool {
auto Cartridge::save() -> void {
auto document = BML::unserialize(information.manifest);
if(auto name = document["board/ram/name"].text()) {
if(auto fp = platform->open(pathID(), name, File::Write)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RAM,content=Save)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(ram.data, ram.size);
}
}
}
if(auto name = document["board/eeprom/name"].text()) {
if(auto fp = platform->open(pathID(), name, File::Write)) {
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 name = document["board/rtc/name"].text()) {
if(auto fp = platform->open(pathID(), name, File::Write)) {
if(auto memory = Emulator::Game::Memory{document["game/board/memory(type=RTC,content=Time)"]}) {
if(memory.nonVolatile) {
if(auto fp = platform->open(pathID(), memory.name(), File::Write)) {
fp->write(rtc.data, rtc.size);
}
}
}
}
auto Cartridge::unload() -> void {
delete[] rom.data;
rom.data = nullptr;
rom.size = 0;
rom.mask = 0;
rom.name = "";
delete[] ram.data;
ram.data = nullptr;
ram.size = 0;
ram.mask = 0;
ram.name = "";
delete[] rtc.data;
rtc.data = nullptr;
rtc.size = 0;
rtc.mask = 0;
rtc.name = "";
}
}

View File

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

View File

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

View File

@ -14,7 +14,6 @@ struct EEPROM {
Command = Status,
};
auto name() const -> string;
auto data() -> uint16*;
auto size() const -> uint;
@ -34,7 +33,6 @@ struct EEPROM {
private:
auto execute() -> void;
string _name;
uint16 _data[1024];
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 ...
if(auto node = document["system/eeprom"]) {
eeprom.setName(node["name"].text());
eeprom.setSize(node["size"].natural() / sizeof(uint16));
eeprom.erase();
//initialize user-data section
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());
}
}
@ -55,7 +54,6 @@ auto System::save() -> void {
auto System::unload() -> void {
if(!loaded()) return;
eeprom.setName("");
eeprom.setSize(0);
cartridge.unload();

View File

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

View File

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

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_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("FLASH_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").text());
else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).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").manufacturer("Macronix").text());
else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).content("Save").manufacturer("Macronix").text());
return output;
}

View File

@ -242,12 +242,14 @@ auto GameBoy::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board: ", mapper, "\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
if(ram && ramSize)
output.append(Memory{}.type("RAM").size(ramSize).content("Save").battery(battery).text());
if(ram && ramSize && battery)
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)
output.append(Memory{}.type("Flash").size(flashSize).content("Download").text());
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)
output.append(" accelerometer\n");
if(rumble)

View File

@ -25,7 +25,7 @@ auto GameGear::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
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;
}

View File

@ -4,8 +4,6 @@ auto Memory::text() const -> string {
string output;
output.append(" memory\n");
output.append(" type: ", _type, "\n");
if(_battery)
output.append(" battery\n");
output.append(" size: 0x", hex(_size), "\n");
output.append(" content: ", _content, "\n");
if(_manufacturer)
@ -14,6 +12,8 @@ if(_architecture)
output.append(" architecture: ", _architecture, "\n");
if(_identifier)
output.append(" identifier: ", _identifier, "\n");
if(_volatile)
output.append(" volatile\n");
return output;
}

View File

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

View File

@ -25,7 +25,7 @@ auto MasterSystem::manifest() const -> string {
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
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;
}

View File

@ -32,7 +32,7 @@ auto SufamiTurbo::manifest() const -> string {
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
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;
}

View File

@ -13,7 +13,7 @@ struct SuperFamicom {
auto romSize() const -> uint;
auto ramSize() const -> uint;
auto expansionRamSize() const -> uint;
auto battery() const -> bool;
auto nonVolatile() const -> bool;
private:
auto size() const -> uint { return data.size(); }
@ -72,29 +72,29 @@ auto SuperFamicom::manifest() const -> string {
}
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()) {
output.append(Memory{}.type("RAM").size(size).content("Save").battery(battery()).text());
output.append(Memory{}.type("RAM").size(size).content("Save").text());
}
if(0) {
} 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( 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());
} 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") {
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());
} 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( 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());
} else if(board(0) == "NECEX") {
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(Oscillator{}.frequency(firmwareNECEX() == "ST010" ? 11'000'000 : 15'000'000).text());
} 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") {
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") {
output.append(Memory{}.type("ROM").size(0x100).content("Boot").manufacturer("Nintendo").architecture("LR35902").identifier(firmwareSGB()).text());
if(firmwareSGB() == "SGB2")
@ -112,7 +112,7 @@ auto SuperFamicom::manifest() const -> string {
} else if(board(0) == "SPC7110") {
output.append(Memory{}.type("ROM").size(romSize() - 0x100000).content("Data").text());
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") {
//todo: MARIO CHIP 1 uses CPU oscillator
output.append(Oscillator{}.frequency(21'440'000).text());
@ -411,7 +411,7 @@ auto SuperFamicom::expansionRamSize() const -> uint {
return 0;
}
auto SuperFamicom::battery() const -> bool {
auto SuperFamicom::nonVolatile() const -> bool {
auto cartridgeTypeLo = data[headerAddress + 0x26] & 15;
return cartridgeTypeLo == 0x2 || cartridgeTypeLo == 0x5 || cartridgeTypeLo == 0x6;
}

View File

@ -49,7 +49,7 @@ auto WonderSwan::manifest() const -> string {
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).content("Program").text());
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)
output.append(Memory{}.type("RTC").size(0x10).content("Time").text());
return output;

View File

@ -34,7 +34,7 @@ auto ManagedNode::_evaluate(string query) const -> bool {
if(side(0)) {
auto result = _find(side(0));
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) {