Update to v106r09 release.

byuu says:

Changelog:

  - higan, icarus, genius: new manifest syntax (work in progress)

Pretty much only LoROM and HiROM SNES games will load right now, and RAM
will only work right if the save.ram file already exists to pull its
file size from (a temporary cheap hack was used.)

Basically, I'm just getting this out there for evaluation.

One minor errata is that I switched icarus to using “memory/battery” to
indicate battery-backed RAM, whereas genius still uses “memory/volatile”
to indicate non-battery-backed RAM.

I intend to make it “memory/battery” in genius, and have the field
auto-enable when RAM or RTC is selected for type (obviously allowing it
to be unchecked for volatile memory.)

I need to update all 64 production boards, and 25 of 29 generic boards,
to use the new slot syntax; and I also need to update every single core
in higan to use the new manifest game syntax. I want to build out a
generic manifest game parser that all emulation cores will use.

Once I finish this, I'll also need to write a database converter to
update all of my licensed game dumps to the new database syntax.

I also need to write up something for doc.byuu.org explaining the new
manifest game syntax. The manifest board syntax will still be “internal”
and subject to revisions, but once v107 is out, the gamepak manifest
format will be set in stone sans extensions.
This commit is contained in:
Tim Allen 2018-03-05 15:34:07 +11:00
parent a4a3d611a6
commit e216912ca3
27 changed files with 1925 additions and 752 deletions

View File

@ -8,6 +8,7 @@ using namespace hiro;
unique_pointer<ListWindow> listWindow;
unique_pointer<GameWindow> gameWindow;
unique_pointer<MemoryWindow> memoryWindow;
unique_pointer<OscillatorWindow> oscillatorWindow;
//
@ -35,7 +36,7 @@ ListWindow::ListWindow() {
helpMenu.setText("Help");
aboutAction.setText("About ...").onActivate([&] {
MessageDialog().setParent(*this).setTitle("About").setText({
"genius v01\n",
"genius\n",
"Author: byuu\n",
"Website: https://byuu.org/"
}).information();
@ -58,7 +59,7 @@ ListWindow::ListWindow() {
onClose([&] { quit(); });
setSize({960, 600});
setSize({820, 600});
reloadList();
updateWindow();
setCentered();
@ -116,19 +117,31 @@ auto ListWindow::loadDatabase(string location) -> void {
for(auto node : document.find("game")) {
Game game;
game.sha256 = node["sha256"].text();
game.label = node["label"].text();
game.name = node["name"].text();
game.region = node["region"].text();
game.revision = node["revision"].text();
game.board = node["board"].text();
game.name = node["name"].text();
game.label = node["label"].text();
game.note = node["note"].text();
for(auto leaf : node.find("memory")) {
Memory memory;
memory.type = leaf["type"].text();
memory.size = leaf["size"].text();
memory.name = leaf["name"].text();
game.memories.append(memory);
for(auto object : node["board"]) {
Component component;
if(object.name() == "memory") {
component.type = Component::Type::Memory;
component.memory.type = object["type"].text();
component.memory.size = object["size"].text();
component.memory.category = object["category"].text();
component.memory.manufacturer = object["manufacturer"].text();
component.memory.part = object["part"].text();
component.memory.note = object["note"].text();
component.memory.isVolatile = (bool)object["volatile"];
}
if(object.name() == "oscillator") {
component.type = Component::Type::Oscillator;
component.oscillator.frequency = object["frequency"].text();
component.oscillator.note = object["note"].text();
}
game.components.append(component);
}
game.note = node["note"].text();
games.append(game);
}
@ -147,7 +160,10 @@ auto ListWindow::saveDatabase(string location) -> void {
auto copy = games;
copy.sort([](auto x, auto y) {
return string::icompare(x.name, y.name) < 0;
return string::icompare(
{x.name, " ", x.region, " ", x.revision},
{y.name, " ", y.region, " ", y.revision}
) < 0;
});
fp.print("database\n");
@ -155,22 +171,41 @@ auto ListWindow::saveDatabase(string location) -> void {
for(auto& game : copy) {
fp.print("game\n");
fp.print(" sha256: ", game.sha256, "\n");
fp.print(" region: ", game.region, "\n");
fp.print(" sha256: ", game.sha256, "\n");
if(game.label)
fp.print(" label: ", game.label, "\n");
fp.print(" name: ", game.name, "\n");
fp.print(" region: ", game.region, "\n");
fp.print(" revision: ", game.revision, "\n");
if(game.board)
fp.print(" board: ", game.board, "\n");
fp.print(" name: ", game.name, "\n");
if(game.label)
fp.print(" label: ", game.label, "\n");
if(game.note)
fp.print(" note: ", game.note, "\n");
for(auto& memory : game.memories) {
fp.print(" memory\n");
fp.print(" type: ", memory.type, "\n");
fp.print(" size: ", memory.size, "\n");
fp.print(" name: ", memory.name, "\n");
fp.print(" board: ", game.board, "\n");
else if(game.components)
fp.print(" board\n");
for(auto& component : game.components) {
if(component.type == Component::Type::Memory) {
fp.print(" memory\n");
fp.print(" type: ", component.memory.type, "\n");
fp.print(" size: ", component.memory.size, "\n");
fp.print(" category: ", component.memory.category, "\n");
if(component.memory.manufacturer)
fp.print(" manufacturer: ", component.memory.manufacturer, "\n");
if(component.memory.part)
fp.print(" part: ", component.memory.part, "\n");
if(component.memory.note)
fp.print(" note: ", component.memory.note, "\n");
if(component.memory.isVolatile)
fp.print(" volatile\n");
}
if(component.type == Component::Type::Oscillator) {
fp.print(" oscillator\n");
fp.print(" frequency: ", component.oscillator.frequency, "\n");
if(component.oscillator.note)
fp.print(" note: ", component.oscillator.note, "\n");
}
}
if(game.note)
fp.print(" note: ", game.note, "\n");
fp.print("\n");
}
@ -219,39 +254,52 @@ GameWindow::GameWindow() {
gameWindow = this;
layout.setMargin(5);
hashLabel.setText("SHA256:");
hashLabel.setText("SHA256:").setAlignment(1.0);
hashEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
regionLabel.setText("Region:");
regionLabel.setText("Region:").setAlignment(1.0);
regionEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
revisionLabel.setText("Revision:");
revisionEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
boardLabel.setText("Board:");
boardEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
nameLabel.setText("Name:");
nameLabel.setText("Name:").setAlignment(1.0);
nameEdit.onChange([&] { modified = true, updateWindow(); });
labelLabel.setText("Label:");
labelLabel.setText("Label:").setAlignment(1.0);
labelEdit.onChange([&] { modified = true, updateWindow(); });
noteLabel.setText("Note:");
noteLabel.setText("Note:").setAlignment(1.0);
noteEdit.onChange([&] { modified = true, updateWindow(); });
memoryList.onActivate([&] { modifyButton.doActivate(); });
memoryList.onChange([&] { updateWindow(); });
appendButton.setText("Append").onActivate([&] {
componentLabel.setText("Tree:").setAlignment({1.0, 0.0});
componentTree.onActivate([&] { modifyComponentButton.doActivate(); });
componentTree.onChange([&] { updateWindow(); });
appendMemoryButton.setText("Memory").onActivate([&] {
setEnabled(false);
memoryWindow->show();
});
modifyButton.setText("Modify").onActivate([&] {
if(auto item = memoryList.selected()) {
appendOscillatorButton.setText("Oscillator").onActivate([&] {
setEnabled(false);
oscillatorWindow->show();
});
modifyComponentButton.setText("Modify").onActivate([&] {
if(auto item = componentTree.selected()) {
setEnabled(false);
memoryWindow->show(game.memories[item.offset()]);
auto path = item.path().split("/");
auto offset = path(0).natural();
Component component = game.components[offset];
if(component.type == Component::Type::Memory) {
memoryWindow->show(component.memory);
}
if(component.type == Component::Type::Oscillator) {
oscillatorWindow->show(component.oscillator);
}
}
});
removeButton.setText("Remove").onActivate([&] { removeMemory(); });
removeComponentButton.setText("Remove").onActivate([&] { removeComponent(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({800, 480});
setSize({640, 480});
setDismissable();
}
@ -260,14 +308,14 @@ auto GameWindow::show(Game game) -> void {
modified = false;
create = !game.sha256;
hashEdit.setText(game.sha256).setEditable(create);
hashEdit.setText(game.sha256);
regionEdit.setText(game.region);
revisionEdit.setText(game.revision);
boardEdit.setText(game.board);
nameEdit.setText(game.name);
labelEdit.setText(game.label);
noteEdit.setText(game.note);
acceptButton.setText(create ? "Create" : "Modify");
acceptButton.setText(create ? "Create" : "Apply");
reloadList();
updateWindow();
@ -314,70 +362,90 @@ auto GameWindow::cancel() -> void {
}
auto GameWindow::reloadList() -> void {
memoryList.reset();
memoryList.append(TableViewHeader()
.append(TableViewColumn().setText("Type"))
.append(TableViewColumn().setText("Size"))
.append(TableViewColumn().setText("Name").setExpandable())
);
for(auto& memory : game.memories) {
memoryList.append(TableViewItem()
.append(TableViewCell().setText(memory.type))
.append(TableViewCell().setText(memory.size))
.append(TableViewCell().setText(memory.name))
);
componentTree.reset();
uint counter = 1;
for(auto& component : game.components) {
TreeViewItem item;
string index = {"[", counter++, "] "};
if(component.type == Component::Type::Memory) {
item.setText({index, "Memory"});
item.append(TreeViewItem().setText({"Type: ", component.memory.type}));
item.append(TreeViewItem().setText({"Size: ", component.memory.size}));
item.append(TreeViewItem().setText({"Category: ", component.memory.category}));
if(component.memory.manufacturer)
item.append(TreeViewItem().setText({"Manufacturer: ", component.memory.manufacturer}));
if(component.memory.part)
item.append(TreeViewItem().setText({"Part: ", component.memory.part}));
if(component.memory.note)
item.append(TreeViewItem().setText({"Note: ", component.memory.note}));
if(component.memory.isVolatile)
item.append(TreeViewItem().setText({"Volatile"}));
}
if(component.type == Component::Type::Oscillator) {
item.setText({index, "Oscillator"});
item.append(TreeViewItem().setText({"Frequency: ", component.oscillator.frequency}));
if(component.oscillator.note)
item.append(TreeViewItem().setText({"Note: ", component.oscillator.note}));
}
componentTree.append(item);
}
Application::processEvents();
memoryList.resizeColumns();
for(auto& item : componentTree.items()) item.setExpanded();
}
auto GameWindow::updateWindow() -> void {
bool valid = true;
hashEdit.setBackgroundColor(
!create ? Color{192, 255, 192}
: hashEdit.text().strip().size() == 64 ? Color{}
: (valid = false, Color{255, 224, 224})
);
bool hashValid = hashEdit.text().strip().size() == 64;
hashEdit.setEditable(!hashValid).setBackgroundColor(
!create || hashValid ? Color{192, 255, 192}
: (valid = false, Color{255, 224, 224}));
regionEdit.setBackgroundColor(regionEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
revisionEdit.setBackgroundColor(revisionEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
boardEdit.setBackgroundColor(boardEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
nameEdit.setBackgroundColor(nameEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
labelEdit.setBackgroundColor(labelEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
modifyButton.setEnabled((bool)memoryList.selected());
removeButton.setEnabled((bool)memoryList.selected());
modifyComponentButton.setEnabled((bool)componentTree.selected());
removeComponentButton.setEnabled((bool)componentTree.selected());
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Game" : "Modify Game Details"});
if(create && hashValid && hashEdit.focused()) regionEdit.setFocused();
}
auto GameWindow::appendMemory(Memory memory) -> void {
auto GameWindow::appendComponent(Component component) -> void {
modified = true;
auto offset = game.memories.size();
game.memories.append(memory);
auto offset = game.components.size();
game.components.append(component);
reloadList();
memoryList.item(offset).setSelected().setFocused();
componentTree.item(offset).setSelected().setFocused();
updateWindow();
}
auto GameWindow::modifyMemory(Memory memory) -> void {
if(auto item = memoryList.selected()) {
auto GameWindow::modifyComponent(Component component) -> void {
if(auto item = componentTree.selected()) {
modified = true;
auto offset = item.offset();
game.memories[offset] = memory;
auto path = item.path().split("/");
auto offset = path(0).natural();
game.components[offset] = component;
reloadList();
memoryList.item(offset).setSelected().setFocused();
componentTree.item(offset).setSelected().setFocused();
updateWindow();
}
}
auto GameWindow::removeMemory() -> void {
if(auto item = memoryList.selected()) {
auto GameWindow::removeComponent() -> void {
if(auto item = componentTree.selected()) {
if(MessageDialog().setParent(*this).setText({
"Are you sure you want to permanently remove this memory?\n\n",
"Name: ", item.cell(2).text()
"Are you sure you want to permanently remove this component?"
}).question() == "Yes") {
modified = true;
game.memories.remove(item.offset());
auto path = item.path().split("/");
auto offset = path(0).natural();
game.components.remove(offset);
reloadList();
updateWindow();
}
@ -390,25 +458,35 @@ MemoryWindow::MemoryWindow() {
memoryWindow = this;
layout.setMargin(5);
typeLabel.setText("Type:");
typeLabel.setText("Type:").setAlignment(1.0);
typeEdit.append(ComboEditItem().setText("ROM"));
typeEdit.append(ComboEditItem().setText("EPROM"));
typeEdit.append(ComboEditItem().setText("EEPROM"));
typeEdit.append(ComboEditItem().setText("NOR"));
typeEdit.append(ComboEditItem().setText("PSRAM"));
typeEdit.append(ComboEditItem().setText("NVRAM"));
typeEdit.append(ComboEditItem().setText("Flash"));
typeEdit.append(ComboEditItem().setText("RAM"));
typeEdit.append(ComboEditItem().setText("RTC"));
typeEdit.onChange([&] { modified = true, updateWindow(); });
sizeLabel.setText("Size:");
sizeEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
nameLabel.setText("Name:");
nameEdit.onChange([&] { modified = true, updateWindow(); });
sizeLabel.setText("Size:").setAlignment(1.0);
sizeEdit.onChange([&] { modified = true, updateWindow(); });
categoryLabel.setText("Category:").setAlignment(1.0);
categoryEdit.append(ComboEditItem().setText("Program"));
categoryEdit.append(ComboEditItem().setText("Data"));
categoryEdit.append(ComboEditItem().setText("Character"));
categoryEdit.append(ComboEditItem().setText("Save"));
categoryEdit.append(ComboEditItem().setText("Time"));
categoryEdit.onChange([&] { modified = true, updateWindow(); });
manufacturerLabel.setText("Manufacturer:").setAlignment(1.0);
manufacturerEdit.onChange([&] { modified = true, updateWindow(); });
partLabel.setText("Part:").setAlignment(1.0);
partEdit.onChange([&] { modified = true, updateWindow(); });
noteLabel.setText("Note:").setAlignment(1.0);
noteEdit.onChange([&] { modified = true, updateWindow(); });
volatileOption.setText("Volatile").onToggle([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({280, layout.minimumSize().height()});
setSize({320, layout.minimumSize().height()});
setDismissable();
}
@ -419,7 +497,11 @@ auto MemoryWindow::show(Memory memory) -> void {
typeEdit.setText(memory.type);
sizeEdit.setText(memory.size);
nameEdit.setText(memory.name);
categoryEdit.setText(memory.category);
manufacturerEdit.setText(memory.manufacturer);
partEdit.setText(memory.part);
noteEdit.setText(memory.note);
volatileOption.setChecked(memory.isVolatile);
updateWindow();
setCentered(*gameWindow);
@ -431,12 +513,18 @@ auto MemoryWindow::show(Memory memory) -> void {
auto MemoryWindow::accept() -> void {
memory.type = typeEdit.text().strip();
memory.size = sizeEdit.text().strip();
memory.name = nameEdit.text().strip();
memory.category = categoryEdit.text().strip();
memory.manufacturer = manufacturerEdit.text().strip();
memory.part = partEdit.text().strip();
memory.note = noteEdit.text().strip();
memory.isVolatile = volatileOption.checked();
Component component{Component::Type::Memory};
component.memory = memory;
if(create) {
gameWindow->appendMemory(memory);
gameWindow->appendComponent(component);
} else {
gameWindow->modifyMemory(memory);
gameWindow->modifyComponent(component);
}
setVisible(false);
@ -458,18 +546,91 @@ auto MemoryWindow::updateWindow() -> void {
bool valid = true;
typeEdit.setBackgroundColor(typeEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
sizeEdit.setBackgroundColor(sizeEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
nameEdit.setBackgroundColor(nameEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
categoryEdit.setBackgroundColor(categoryEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
manufacturerEdit.setBackgroundColor(manufacturerEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
partEdit.setBackgroundColor(partEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
}
//
OscillatorWindow::OscillatorWindow() {
oscillatorWindow = this;
layout.setMargin(5);
frequencyLabel.setText("Frequency:").setAlignment(1.0);
frequencyEdit.onChange([&] { modified = true, updateWindow(); });
noteLabel.setText("Note:").setAlignment(1.0);
noteEdit.onChange([&] { modified = true, updateWindow(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({320, layout.minimumSize().height()});
setDismissable();
}
auto OscillatorWindow::show(Oscillator oscillator) -> void {
this->oscillator = oscillator;
modified = false;
create = !oscillator.frequency;
frequencyEdit.setText(oscillator.frequency);
noteEdit.setText(oscillator.note);
updateWindow();
setCentered(*gameWindow);
setVisible();
frequencyEdit.setFocused();
}
auto OscillatorWindow::accept() -> void {
oscillator.frequency = frequencyEdit.text().strip();
oscillator.note = noteEdit.text().strip();
Component component{Component::Type::Oscillator};
component.oscillator = oscillator;
if(create) {
gameWindow->appendComponent(component);
} else {
gameWindow->modifyComponent(component);
}
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
auto OscillatorWindow::cancel() -> void {
if(!modified || MessageDialog().setParent(*this).setText({
"Are you sure you want to discard your changes to this property?"
}).question() == "Yes") {
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
}
auto OscillatorWindow::updateWindow() -> void {
bool valid = true;
frequencyEdit.setBackgroundColor(frequencyEdit.text().strip() ? Color{} : (valid = false, Color{255, 224, 224}));
noteEdit.setBackgroundColor(noteEdit.text().strip() ? Color{} : (Color{255, 255, 240}));
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Property" : "Modify Property Details"});
}
//
#include <nall/main.hpp>
auto nall::main(string_vector) -> void {
Application::setName("genius");
new ListWindow;
new GameWindow;
new MemoryWindow;
new OscillatorWindow;
Application::run();
}

View File

@ -1,7 +1,26 @@
struct Memory {
string type;
string size;
string name;
string category;
string manufacturer;
string part;
string note;
bool isVolatile = false;
};
struct Oscillator {
string frequency;
string note;
};
//variant meta-class
struct Component {
enum class Type : uint {
Memory,
Oscillator,
} type;
Memory memory;
Oscillator oscillator;
};
struct Game {
@ -12,7 +31,7 @@ struct Game {
string name;
string label;
string note;
vector<Memory> memories;
vector<Component> components;
};
struct ListWindow : Window {
@ -58,9 +77,9 @@ struct GameWindow : Window {
auto cancel() -> void;
auto reloadList() -> void;
auto updateWindow() -> void;
auto appendMemory(Memory) -> void;
auto modifyMemory(Memory) -> void;
auto removeMemory() -> void;
auto appendComponent(Component) -> void;
auto modifyComponent(Component) -> void;
auto removeComponent() -> void;
private:
bool modified = false;
@ -77,7 +96,7 @@ private:
Label revisionLabel{&infoLayout, Size{0, 0}};
LineEdit revisionEdit{&infoLayout, Size{~0, 0}};
Label boardLabel{&infoLayout, Size{0, 0}};
LineEdit boardEdit{&infoLayout, Size{~0, 0}};
LineEdit boardEdit{&infoLayout, Size{~0, 0}, 0};
HorizontalLayout nameLayout{&layout, Size{~0, 0}};
Label nameLabel{&nameLayout, Size{50, 0}};
LineEdit nameEdit{&nameLayout, Size{~0, 0}};
@ -87,14 +106,17 @@ private:
HorizontalLayout noteLayout{&layout, Size{~0, 0}};
Label noteLabel{&noteLayout, Size{50, 0}};
LineEdit noteEdit{&noteLayout, Size{~0, 0}};
TableView memoryList{&layout, Size{~0, ~0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Button appendButton{&controlLayout, Size{80, 0}};
Button modifyButton{&controlLayout, Size{80, 0}};
Button removeButton{&controlLayout, Size{80, 0}};
Widget spacer{&controlLayout, Size{~0, 0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
HorizontalLayout lowerLayout{&layout, Size{~0, ~0}};
Label componentLabel{&lowerLayout, Size{50, ~0}};
TreeView componentTree{&lowerLayout, Size{~0, ~0}};
VerticalLayout controlLayout{&lowerLayout, Size{0, ~0}};
Button appendMemoryButton{&controlLayout, Size{80, 0}};
Button appendOscillatorButton{&controlLayout, Size{80, 0}};
Button modifyComponentButton{&controlLayout, Size{80, 0}};
Button removeComponentButton{&controlLayout, Size{80, 0}};
Widget controlSpacer{&controlLayout, Size{0, ~0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};
struct MemoryWindow : Window {
@ -111,15 +133,50 @@ private:
VerticalLayout layout{this};
HorizontalLayout infoLayout{&layout, Size{~0, 0}};
Label typeLabel{&infoLayout, Size{40, 0}};
Label typeLabel{&infoLayout, Size{80, 0}};
ComboEdit typeEdit{&infoLayout, Size{~0, 0}};
Label sizeLabel{&infoLayout, Size{0, 0}};
LineEdit sizeEdit{&infoLayout, Size{~0, 0}};
HorizontalLayout nameLayout{&layout, Size{~0, 0}};
Label nameLabel{&nameLayout, Size{40, 0}};
LineEdit nameEdit{&nameLayout, Size{~0, 0}};
HorizontalLayout categoryLayout{&layout, Size{~0, 0}};
Label categoryLabel{&categoryLayout, Size{80, 0}};
ComboEdit categoryEdit{&categoryLayout, Size{~0, 0}};
HorizontalLayout manufacturerLayout{&layout, Size{~0, 0}};
Label manufacturerLabel{&manufacturerLayout, Size{80, 0}};
LineEdit manufacturerEdit{&manufacturerLayout, Size{~0, 0}};
HorizontalLayout partLayout{&layout, Size{~0, 0}};
Label partLabel{&partLayout, Size{80, 0}};
LineEdit partEdit{&partLayout, Size{~0, 0}};
HorizontalLayout noteLayout{&layout, Size{~0, 0}};
Label noteLabel{&noteLayout, Size{80, 0}};
LineEdit noteEdit{&noteLayout, Size{~0, 0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Widget spacer{&controlLayout, Size{~0, 0}};
Widget controlSpacer{&controlLayout, Size{~0, 0}};
CheckLabel volatileOption{&controlLayout, Size{0, 0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};
struct OscillatorWindow : Window {
OscillatorWindow();
auto show(Oscillator = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto updateWindow() -> void;
private:
bool modified = false;
bool create = true;
Oscillator oscillator;
VerticalLayout layout{this};
HorizontalLayout frequencyLayout{&layout, Size{~0, 0}};
Label frequencyLabel{&frequencyLayout, Size{60, 0}};
LineEdit frequencyEdit{&frequencyLayout, Size{~0, 0}};
HorizontalLayout noteLayout{&layout, Size{~0, 0}};
Label noteLabel{&noteLayout, Size{60, 0}};
LineEdit noteEdit{&noteLayout, Size{~0, 0}};
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
Widget controlSpacer{&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.08";
static const string Version = "106.09";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "https://byuu.org/";

View File

@ -1,13 +1,11 @@
auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
string output;
auto region = node["game/region"].text();
auto board = node["game/board"].text();
if(board != "SHVC-SGB2-01") board.trimLeft("SHVC-", 1L);
board.trimLeft("SNSP-", 1L);
board.trimLeft("MAXI-", 1L);
board.trimLeft("MJSC-", 1L);
board.trimLeft("EA-", 1L);
if(board.beginsWith("SNSP-")) board.replace("SNSP-", "SHVC-", 1L);
if(board.beginsWith("MAXI-")) board.replace("MAXI-", "SHVC-", 1L);
if(board.beginsWith("MJSC-")) board.replace("MJSC-", "SHVC-", 1L);
if(board.beginsWith("EA-" )) board.replace("EA-", "SHVC-", 1L);
if(auto fp = platform->open(ID::System, "boards.bml", File::Read, File::Required)) {
auto document = BML::unserialize(fp->reads());
@ -20,65 +18,36 @@ auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
if(string{part(0), revision, part(2)} == board) matched = true;
}
}
if(!matched) continue;
if(region.endsWith("BRA")
|| region.endsWith("CAN")
|| region.endsWith("HKG")
|| region.endsWith("JPN")
|| region.endsWith("KOR")
|| region.endsWith("LTN")
|| region.endsWith("ROC")
|| region.endsWith("USA")
|| region.beginsWith("SHVC-")
|| region == "NTSC") {
output.append("region=ntsc\n");
} else {
output.append("region=pal\n");
}
vector<Markup::Node> rom;
vector<Markup::Node> ram;
for(auto memory : node.find("game/memory")) {
if(memory["type"].text() == "ROM" || memory["type"].text() == "EPROM") {
rom.append(memory);
}
if(memory["type"].text() == "RAM" || memory["type"].text() == "NVRAM") {
ram.append(memory);
}
}
for(auto& line : BML::serialize(leaf).split("\n")) {
line.trimLeft(" ", 1L);
if(line.endsWith("rom") && rom) {
line.append(" name=", rom.left()["name"].text());
line.append(" size=", rom.left()["size"].text());
rom.removeLeft();
}
if(line.endsWith("ram") && ram) {
line.append(" name=", ram.left()["name"].text());
line.append(" size=", ram.left()["size"].text());
if(ram.left()["type"].text() == "RAM") line.append(" volatile");
ram.removeLeft();
}
output.append(line, "\n");
}
break;
if(matched) return leaf;
}
}
return BML::unserialize(output);
return {};
}
auto Cartridge::loadCartridge(Markup::Node node) -> void {
information.title.cartridge = node["game/label"].text();
if(region() == "Auto") {
auto region = node["game/region"].text();
if(region.endsWith("BRA")
|| region.endsWith("CAN")
|| region.endsWith("HKG")
|| region.endsWith("JPN")
|| region.endsWith("KOR")
|| region.endsWith("LTN")
|| region.endsWith("ROC")
|| region.endsWith("USA")
|| region.beginsWith("SHVC-")
|| region == "NTSC") {
information.region = "NTSC";
} else {
information.region = "PAL";
}
}
auto board = node["board"];
if(!board) board = loadBoard(node);
if(region() == "Auto") {
if(board["region"].text() == "ntsc") information.region = "NTSC";
if(board["region"].text() == "pal") information.region = "PAL";
}
if(board["bsmemory"] || board["mcc/bsmemory"] || board["sa1/bsmemory"]) {
if(auto loaded = platform->load(ID::BSMemory, "BS Memory", "bs")) {
@ -401,6 +370,7 @@ auto Cartridge::loadMemory(MappedRAM& ram, Markup::Node node, bool required, may
auto size = node["size"].natural();
ram.allocate(size);
if(auto fp = platform->open(id(), name, File::Read, required)) {
ram.allocate(fp->size()); //TODO: temporary hack
fp->read(ram.data(), ram.size());
}
}

View File

@ -1,376 +1,10 @@
database
revision: 2018-02-21
revision: 2018-03-04
//Boards (Production)
database
revision: 2018-02-21
board: 1A0N-(01,02,10,20,30)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: 1A1B-(04,05,06)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: 1A1M-(01,10,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 1A3B-(11,12,13)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: 1A3B-20
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 1A3M-(10,20,21,30)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 1A5B-(02,04)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: 1A5M-(01,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 1B0N-(02,03,10)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
necdsp model=uPD7725 frequency=8000000
map address=30-3f,b0-bf:8000-ffff mask=0x3fff
prom
drom
dram
board: 1B5B-02
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000
map address=20-3f,a0-bf:8000-ffff mask=0x3fff
prom
drom
dram
board: 1C0N
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=60-7d,e0-ff:0000-ffff
board: 1C0N5S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=60-7d,e0-ff:0000-ffff
board: 1CA0N5S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: 1CA0N6S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: 1CA6B-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71,f0-f1:0000-ffff
board: 1CB0N7S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: 1CB5B-20
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: 1CB7B-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=70-71:0000-ffff
board: 1DC0N-01
hitachidsp model=HG51B169 frequency=20000000
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board: 1DS0B-20
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
necdsp model=uPD96050 frequency=11000000
map address=60-67,e0-e7:0000-3fff
prom
drom
dram
map address=68-6f,e8-ef:0000-7fff mask=0x8000
board: 1J0N-(01,10,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: 1J1M-(11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: 1J3B-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: 1J3M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: 1J5M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: 1K0N-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000
map address=00-1f,80-9f:6000-7fff mask=0xfff
prom
drom
dram
board: 1K1B-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
necdsp model=uPD7725 frequency=8000000
map address=00-1f,80-9f:6000-7fff mask=0xfff
prom
drom
dram
board: 1L0N3S-01
sa1
map address=00-3f,80-bf:2200-23ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
map address=00-3f,80-bf:3000-37ff size=0x800
board: 1L3B-(02,11)
sa1
map address=00-3f,80-bf:2200-23ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
map address=00-3f,80-bf:3000-37ff size=0x800
board: 1L5B-(11,20)
sa1
map address=00-3f,80-bf:2200-23ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
map address=00-3f,80-bf:3000-37ff size=0x800
board: 1N0N-01
sdd1
map address=00-3f,80-bf:4800-480f
rom
map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff
board: 2A0N-(01,10,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: 2A1M-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 2A3B-01
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 2A3M-01#R
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 2A3M-(01,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 2A5M-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: 2B3B-01
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
necdsp model=uPD7725 frequency=8000000
map address=60-6f,e0-ef:0000-7fff mask=0x3fff
prom
drom
dram
board: 2DC0N-01
hitachidsp model=HG51B169 frequency=20000000
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board: 2E3M-01
rom
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
board: 2J0N-(01,10,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: 2J3M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: 2J5M-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: 3J0N-01
rom
map address=00-2f,80-af:8000-ffff
map address=40-6f,c0-ef:0000-ffff
board: BA0N-(01,10)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: BA1M-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: BA3M-(01,10)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
revision: 2018-02-27
board: BANDAI-PT-923
rom
@ -386,25 +20,6 @@ board: BANDAI-PT-923
ram
map address=70-7d,f0-ff:0000-ffff
board: BJ0N-(01,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: BJ1M-(10,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: BJ3M-10
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: BSC-1A5M-02
rom
map address=00-1f:8000-ffff mask=0x8000 base=0x000000
@ -482,6 +97,420 @@ board: SGB-R-10
rom
gameboy
board: SHVC-1A0N-(01,02,10,20,30)
rom
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
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A1M-(01,10,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A3B-(11,12,13)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A3B-20
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A3M-(10,20,21,30)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1A5B-(02,04)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
board: SHVC-1A5M-(01,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-1B0N-(02,03,10)
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
necdsp model=uPD7725 frequency=8000000
map address=30-3f,b0-bf:8000-ffff mask=0x3fff
prom
drom
dram
board: SHVC-1B5B-02
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000
map address=20-3f,a0-bf:8000-ffff mask=0x3fff
prom
drom
dram
board: SHVC-1C0N
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=60-7d,e0-ff:0000-ffff
board: SHVC-1C0N5S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-1f,80-9f:8000-ffff mask=0x8000
ram
map address=60-7d,e0-ff:0000-ffff
board: SHVC-1CA0N5S-01
superfx
map address=00-3f,80-bf:3000-34ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
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
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
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
map address=00-3f,80-bf:8000-ffff mask=0x8000
map address=40-5f,c0-df:0000-ffff
ram
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
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
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
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
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
map address=00-3f:8000-ffff mask=0x8000
map address=40-5f:0000-ffff
ram
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
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board: SHVC-1DS0B-20
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
necdsp model=uPD96050 frequency=11000000
map address=60-67,e0-e7:0000-3fff
prom
drom
dram
map address=68-6f,e8-ef:0000-7fff mask=0x8000
board: SHVC-1J0N-(01,10,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-1J1M-(11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J3B-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J3M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1J5M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-1K0N-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
necdsp model=uPD7725 frequency=8000000
map address=00-1f,80-9f:6000-7fff mask=0xfff
prom
drom
dram
board: SHVC-1K1B-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
necdsp model=uPD7725 frequency=8000000
map address=00-1f,80-9f:6000-7fff mask=0xfff
prom
drom
dram
board: SHVC-1L0N3S-01
sa1
map address=00-3f,80-bf:2200-23ff
rom
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
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
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
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
map address=00-3f,80-bf:8000-ffff mask=0x408000
map address=c0-ff:0000-ffff
bwram
map address=00-3f,80-bf:6000-7fff size=0x2000
map address=40-4f:0000-ffff
iram
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
map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff
board: SHVC-2A0N-01#R
rom
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
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
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3B-01
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3M-01#R
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A3M-(01,11,20)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2A5M-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-2B3B-01
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
necdsp model=uPD7725 frequency=8000000
map address=60-6f,e0-ef:0000-7fff mask=0x3fff
prom
drom
dram
board: SHVC-2DC0N-01
hitachidsp model=HG51B169 frequency=20000000
map address=00-3f,80-bf:6c00-6fff,7c00-7fff
map address=70-77:0000-7fff
rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
drom
dram
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board: SHVC-2E3M-01
rom
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
board: SHVC-2J0N-(01,10,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-2J3M-(01,11,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: SHVC-2J5M-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=10-1f,30-3f,90-9f,b0-bf:6000-7fff mask=0xe000
board: SHVC-3J0N-01
rom
map address=00-2f,80-af:8000-ffff
map address=40-6f,c0-ef:0000-ffff
board: SHVC-BA0N-(01,10)
rom
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
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-BA3M-(01,10)
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
ram
map address=70-7d,f0-ff:0000-7fff mask=0x8000
board: SHVC-BJ0N-(01,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: SHVC-BJ1M-(10,20)
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-BJ3M-10
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: SHVC-LDH3C-01
spc7110
map address=00-3f,80-bf:4800-483f
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
map address=00-3f,80-bf:6000-7fff mask=0xe000
epsonrtc
map address=00-3f,80-bf:4840-4842
ram
board: SHVC-LN3B-01
sdd1
map address=00-3f,80-bf:4800-480f
rom
map address=00-3f,80-bf:8000-ffff
map address=c0-ff:0000-ffff
ram
map address=00-3f,80-bf:6000-7fff mask=0xe000
map address=70-73:0000-ffff
board: SHVC-SGB2-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
@ -491,12 +520,12 @@ board: SHVC-SGB2-01
rom
gameboy
board: YA0N-01
board: SHVC-YA0N-01
rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
map address=40-7d,c0-ff:0000-7fff mask=0x8000
board: YJ0N-01
board: SHVC-YJ0N-01
rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
@ -504,7 +533,7 @@ board: YJ0N-01
//Boards (Generic)
database
revision: 2018-02-21
revision: 2018-03-04
board: ARM-LOROM-RAM
rom
@ -565,15 +594,15 @@ board: BS-SA1-RAM
bsmemory
board: HIROM
rom
rom name=program.rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
board: HIROM-RAM
rom
rom name=program.rom
map address=00-3f,80-bf:8000-ffff
map address=40-7d,c0-ff:0000-ffff
ram
ram name=save.ram
map address=20-3f,a0-bf:6000-7fff mask=0xe000
board: HIROMEX-RAM
@ -597,13 +626,13 @@ board: HITACHI-LOROM
map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board: LOROM
rom
rom name=program.rom
map address=00-7d,80-ff:8000-ffff mask=0x8000
board: LOROM-RAM
rom
rom name=program.rom
map address=00-3f,80-bf:8000-ffff mask=0x8000
ram
ram name=save.ram
map address=70-7d,f0-ff:0000-ffff mask=0x8000
board: LOROMEX-RAM

Binary file not shown.

After

Width:  |  Height:  |  Size: 629 B

View File

@ -84,6 +84,7 @@ namespace name=Icon
binary name=Desktop file=icon/place/desktop.png
binary name=Home file=icon/place/home.png
binary name=Server file=icon/place/server.png
binary name=Settings file=icon/place/settings.png
binary name=Share file=icon/place/share.png
namespace name=Prompt
binary name=Error file=icon/prompt/error.png

View File

@ -1756,6 +1756,28 @@ const nall::vector<uint8_t> Server = { //size: 642
162,75,129,231,151,151,151,31,252,63,158,1,254,0,124,80,17,254,250,115,5,147,0,0,0,0,73,69,78,68,174,66,
96,130,
};
const nall::vector<uint8_t> Settings = { //size: 629
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255,
97,0,0,0,6,98,75,71,68,0,255,0,255,0,255,160,189,167,147,0,0,0,9,112,72,89,115,0,0,11,19,0,
0,11,19,1,0,154,156,24,0,0,0,7,116,73,77,69,7,213,11,4,11,55,32,209,169,238,103,0,0,0,29,116,
69,88,116,67,111,109,109,101,110,116,0,67,114,101,97,116,101,100,32,119,105,116,104,32,84,104,101,32,71,73,77,80,
239,100,37,110,0,0,1,217,73,68,65,84,56,203,197,147,77,107,19,97,20,133,159,105,107,131,52,157,52,35,161,38,
67,55,129,198,221,132,100,66,72,138,88,117,37,53,89,137,8,21,4,33,100,254,65,17,92,117,33,136,43,17,55,45,
253,3,165,45,8,67,178,81,12,88,65,145,188,249,152,162,130,219,36,148,137,52,37,89,180,136,31,113,97,103,72,219,
116,213,133,119,117,121,207,229,112,239,57,231,133,115,150,116,22,240,244,217,147,190,211,63,90,122,124,230,220,152,211,220,
189,119,39,163,235,113,19,64,136,74,22,32,159,51,88,93,91,57,134,157,36,115,9,116,61,110,230,115,6,150,101,1,
152,161,160,74,203,110,16,10,170,160,99,166,146,105,52,77,3,232,15,146,140,13,178,89,150,197,165,105,63,183,179,11,
238,91,44,17,37,70,212,197,79,214,168,211,248,21,191,248,211,255,189,24,185,50,75,171,209,98,251,221,118,175,109,183,
61,59,214,78,111,202,55,229,153,240,78,80,42,149,16,162,146,253,242,249,235,183,99,27,56,130,133,130,42,0,181,90,
173,103,219,223,95,9,81,221,84,20,229,170,36,141,62,92,200,220,10,56,231,232,122,220,213,98,196,97,202,231,12,98,
137,127,171,250,124,62,185,217,108,110,110,172,111,153,157,78,231,189,44,123,3,206,57,249,156,49,220,133,213,181,21,66,
65,149,88,34,202,193,193,225,225,220,92,122,9,32,28,14,27,221,110,183,7,200,213,114,157,194,110,241,180,6,111,94,
191,93,246,43,126,49,57,233,93,188,113,237,38,63,127,253,184,208,110,183,3,145,200,236,3,73,226,242,252,245,121,121,
220,51,78,69,84,16,162,146,125,241,252,229,253,161,54,166,146,105,90,118,3,117,70,69,157,81,47,30,65,178,51,147,
74,166,1,204,141,245,45,215,198,145,193,117,52,77,99,207,222,167,96,22,169,150,235,0,84,203,117,10,102,145,61,123,
223,201,193,112,13,142,84,237,187,73,212,49,51,211,25,10,187,69,39,153,230,199,79,31,78,37,241,220,127,225,255,215,
95,179,89,175,43,2,12,187,45,0,0,0,0,73,69,78,68,174,66,96,130,
};
const nall::vector<uint8_t> Share = { //size: 697
137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,16,0,0,0,16,8,6,0,0,0,31,243,255,
97,0,0,0,4,115,66,73,84,8,8,8,8,124,8,100,136,0,0,0,9,112,72,89,115,0,0,13,215,0,0,13,

View File

@ -91,6 +91,7 @@ extern const nall::vector<uint8_t> Bookmarks;
extern const nall::vector<uint8_t> Desktop;
extern const nall::vector<uint8_t> Home;
extern const nall::vector<uint8_t> Server;
extern const nall::vector<uint8_t> Settings;
extern const nall::vector<uint8_t> Share;
}
namespace Prompt {

View File

@ -1,5 +1,5 @@
database
revision: 2018-02-16
revision: 2018-03-01
//BS Memory (JPN)

View File

@ -1,5 +1,5 @@
database
revision: 2018-02-16
revision: 2018-03-01
//Sufami Turbo (JPN)

File diff suppressed because it is too large Load Diff

View File

@ -3,9 +3,9 @@ auto Icarus::superFamicomManifest(string location) -> string {
auto files = directory::files(location, "*.rom");
concatenate(buffer, {location, "program.rom"});
concatenate(buffer, {location, "data.rom" });
for(auto& file : files.match("*.boot.rom" )) concatenate(buffer, {location, file});
for(auto& file : files.match("*.program.rom")) concatenate(buffer, {location, file});
for(auto& file : files.match("*.data.rom" )) concatenate(buffer, {location, file});
for(auto& file : files.match("*.boot.rom" )) concatenate(buffer, {location, file});
return superFamicomManifest(buffer, location);
}
@ -19,10 +19,7 @@ auto Icarus::superFamicomManifest(vector<uint8_t>& buffer, string location) -> s
if(settings["icarus/UseHeuristics"].boolean()) {
Heuristics::SuperFamicom game{buffer, location};
if(auto manifest = game.manifest()) {
if(exists({location, "msu1.rom"})) manifest.append(" msu1\n");
return manifest;
}
if(auto manifest = game.manifest()) return manifest;
}
return {};
@ -44,11 +41,12 @@ auto Icarus::superFamicomImport(vector<uint8_t>& buffer, string location) -> str
if(settings["icarus/CreateManifests"].boolean()) write({target, "manifest.bml"}, manifest);
uint offset = 0;
auto document = BML::unserialize(manifest);
for(auto rom : document.find("game/memory")) {
for(auto rom : document.find("game/board/memory")) {
if(rom["type"].text() != "ROM") continue;
auto name = rom["name"].text();
auto name = string{rom["part"].text(), ".", rom["category"].text(), ".rom"}.trimLeft(".", 1L).downcase();
auto size = rom["size"].natural();
if(size > buffer.size() - offset) {
auto name = string{rom["note"].text(), ".", rom["category"].text(), ".rom"}.trimLeft(".", 1L).downcase();
auto location = locate({"Firmware/", name});
if(location && file::size(location) == size) {
write({target, name}, file::read(location));

View File

@ -23,9 +23,10 @@ auto BSMemory::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("NAND", data.size(), "program.rom"));
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("Flash").size(data.size()).category("Program").text());
return output;
}

View File

@ -35,66 +35,66 @@ auto Famicom::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(&data[16], data.size() - 16).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
switch(mapper) {
default:
output.append(" board: NES-NROM-256\n");
output.append(" board: NES-NROM-256\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break;
case 1:
output.append(" board: NES-SXROM\n");
output.append(" board: NES-SXROM\n");
output.append(" chip type=MMC1B2\n");
prgram = 8192;
break;
case 2:
output.append(" board: NES-UOROM\n");
output.append(" board: NES-UOROM\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break;
case 3:
output.append(" board: NES-CNROM\n");
output.append(" board: NES-CNROM\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break;
case 4:
//MMC3
output.append(" board: NES-TLROM\n");
output.append(" board: NES-TLROM\n");
output.append(" chip type=MMC3B\n");
prgram = 8192;
//MMC6
//output.append(" board: NES-HKROM\n");
//output.append(" board: NES-HKROM\n");
//output.append(" chip type=MMC6\n");
//prgram = 1024;
break;
case 5:
output.append(" board: NES-ELROM\n");
output.append(" board: NES-ELROM\n");
output.append(" chip type=MMC5\n");
prgram = 65536;
break;
case 7:
output.append(" board: NES-AOROM\n");
output.append(" board: NES-AOROM\n");
break;
case 9:
output.append(" board: NES-PNROM\n");
output.append(" board: NES-PNROM\n");
output.append(" chip type=MMC2\n");
prgram = 8192;
break;
case 10:
output.append(" board: NES-FKROM\n");
output.append(" board: NES-FKROM\n");
output.append(" chip type=MMC4\n");
prgram = 8192;
break;
case 16:
output.append(" board: BANDAI-FCG\n");
output.append(" board: BANDAI-FCG\n");
output.append(" chip type=LZ93D50\n");
break;
@ -102,7 +102,7 @@ auto Famicom::manifest() const -> string {
case 23:
case 25:
//VRC4
output.append(" board: KONAMI-VRC-4\n");
output.append(" board: KONAMI-VRC-4\n");
output.append(" chip type=VRC4\n");
output.append(" pinout a0=1 a1=0\n");
prgram = 8192;
@ -110,62 +110,62 @@ auto Famicom::manifest() const -> string {
case 22:
//VRC2
output.append(" board: KONAMI-VRC-2\n");
output.append(" board: KONAMI-VRC-2\n");
output.append(" chip type=VRC2\n");
output.append(" pinout a0=0 a1=1\n");
break;
case 24:
output.append(" board: KONAMI-VRC-6\n");
output.append(" board: KONAMI-VRC-6\n");
output.append(" chip type=VRC6\n");
break;
case 26:
output.append(" board: KONAMI-VRC-6\n");
output.append(" board: KONAMI-VRC-6\n");
output.append(" chip type=VRC6\n");
prgram = 8192;
break;
case 34:
output.append(" board: NES-BNROM\n");
output.append(" board: NES-BNROM\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break;
case 66:
output.append(" board: NES-GNROM\n");
output.append(" board: NES-GNROM\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
break;
case 69:
output.append(" board: SUNSOFT-5B\n");
output.append(" board: SUNSOFT-5B\n");
output.append(" chip type=5B\n");
prgram = 8192;
break;
case 73:
output.append(" board: KONAMI-VRC-3\n");
output.append(" board: KONAMI-VRC-3\n");
output.append(" chip type=VRC3\n");
output.append(" mirror mode=", mirror == 0 ? "horizontal" : "vertical", "\n");
prgram = 8192;
break;
case 75:
output.append(" board: KONAMI-VRC-1\n");
output.append(" board: KONAMI-VRC-1\n");
output.append(" chip type=VRC1\n");
break;
case 85:
output.append(" board: KONAMI-VRC-7\n");
output.append(" board: KONAMI-VRC-7\n");
output.append(" chip type=VRC7\n");
prgram = 8192;
break;
}
if(prgrom) output.append(memory("ROM", prgrom, "program.rom"));
if(prgram) output.append(memory("NVRAM", prgram, "save.ram"));
if(prgrom) output.append(Memory{}.type("ROM").size(prgrom).category("Program").text());
if(prgram) output.append(Memory{}.type("RAM").size(prgram).category("Save").battery().text());
if(chrrom) output.append(memory("ROM", chrrom, "character.rom"));
if(chrram) output.append(memory("RAM", chrram, "character.ram"));
if(chrrom) output.append(Memory{}.type("ROM").size(chrrom).category("Character").text());
if(chrram) output.append(Memory{}.type("RAM").size(chrram).category("Character").text());
return output;
}

View File

@ -50,16 +50,17 @@ auto GameBoyAdvance::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
if(!list);
else if(list.left().beginsWith("SRAM_V" )) output.append(memory("NVRAM", 0x8000, "save.ram"));
else if(list.left().beginsWith("SRAM_F_V" )) output.append(memory("NVRAM", 0x8000, "save.ram"));
else if(list.left().beginsWith("EEPROM_V" )) output.append(memory("EEPROM", 0x0, "save.ram"));
else if(list.left().beginsWith("FLASH_V" )) output.append(memory("NAND", 0x10000, "save.ram"));
else if(list.left().beginsWith("FLASH512_V")) output.append(memory("NAND", 0x10000, "save.ram"));
else if(list.left().beginsWith("FLASH1M_V" )) output.append(memory("NAND", 0x20000, "save.ram"));
else if(list.left().beginsWith("SRAM_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).category("Save").text());
else if(list.left().beginsWith("SRAM_F_V" )) output.append(Memory{}.type("RAM" ).size( 0x8000).category("Save").text());
else if(list.left().beginsWith("EEPROM_V" )) output.append(Memory{}.type("EEPROM").size( 0x0).category("Save").text());
else if(list.left().beginsWith("FLASH_V" )) output.append(Memory{}.type("Flash" ).size(0x10000).category("Save").text());
else if(list.left().beginsWith("FLASH512_V")) output.append(Memory{}.type("Flash" ).size(0x10000).category("Save").text());
else if(list.left().beginsWith("FLASH1M_V" )) output.append(Memory{}.type("Flash" ).size(0x20000).category("Save").text());
return output;
}

View File

@ -40,9 +40,9 @@ auto GameBoy::manifest() const -> string {
bool accelerometer = false;
bool rumble = false;
uint flashSize = 0;
uint romSize = 0;
uint ramSize = 0;
uint flashSize = 0;
uint rtcSize = 0;
string mapper = "MBC0";
@ -218,8 +218,6 @@ auto GameBoy::manifest() const -> string {
case 0x54: romSize = 96 * 16 * 1024; break;
}
if(mapper == "MBC6" && flash) flashSize = 1024 * 1024;
switch(read(0x0149)) { default:
case 0x00: ramSize = 0 * 1024; break;
case 0x01: ramSize = 2 * 1024; break;
@ -232,21 +230,28 @@ auto GameBoy::manifest() const -> string {
if(mapper == "MBC7" && ram) ramSize = 256;
if(mapper == "TAMA" && ram) ramSize = 32;
if(mapper == "MBC6" && flash) flashSize = 1024 * 1024;
if(mapper == "MBC3" && rtc) rtcSize = 13;
if(mapper == "TAMA" && rtc) rtcSize = 21;
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" board: ", mapper, "\n");
if(accelerometer) output.append(" accelerometer\n");
if(rumble) output.append(" rumble\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
if(flash && flashSize) output.append(memory("NAND", flashSize, "download.rom"));
if(ram && ramSize) output.append(memory(battery ? "NVRAM" : "RAM", ramSize, "save.ram"));
if(rtc && rtcSize) output.append(memory("RTC", rtcSize, "rtc.ram"));
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board: ", mapper, "\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
if(ram && ramSize)
output.append(Memory{}.type("RAM").size(ramSize).category("Save").battery(battery).text());
if(flash && flashSize)
output.append(Memory{}.type("Flash").size(flashSize).category("Download").text());
if(rtc && rtcSize)
output.append(Memory{}.type("RTC").size(rtcSize).category("Time").battery().text());
if(accelerometer)
output.append(" accelerometer\n");
if(rumble)
output.append(" rumble\n");
return output;
}

View File

@ -21,9 +21,11 @@ auto GameGear::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
output.append(Memory{}.type("RAM").size(0x8000).category("Save").battery().text());
return output;
}

View File

@ -1,11 +1,40 @@
namespace Heuristics {
auto Heuristics::memory(string type, uint size, string name) const -> string {
auto Memory::text() const -> string {
string output;
output.append(" memory\n");
output.append(" type: ", type, "\n");
output.append(" size: 0x", hex(size), "\n");
output.append(" name: ", name, "\n");
output.append(" memory\n");
output.append(" type: ", _type, "\n");
output.append(" size: 0x", hex(_size), "\n");
output.append(" category: ", _category, "\n");
if(_manufacturer)
output.append(" manufacturer: ", _manufacturer, "\n");
if(_part)
output.append(" part: ", _part, "\n");
if(_note)
output.append(" note: ", _note, "\n");
if(_battery)
output.append(" battery\n");
return output;
}
auto Oscillator::text() const -> string {
string output;
output.append(" oscillator\n");
output.append(" frequency: ", _frequency, "\n");
if(_note)
output.append(" note: ", _note, "\n");
return output;
}
//deprecated
auto Heuristics::memory(string type, uint size, string name, string metadata) const -> string {
string output;
output.append(" memory\n");
output.append(" type: ", type, "\n");
output.append(" size: 0x", hex(size), "\n");
output.append(" name: ", name, "\n");
if(metadata)
output.append(" metadata: ", metadata, "\n");
return output;
}

View File

@ -1,7 +1,35 @@
namespace Heuristics {
struct Memory {
auto& type(string type) { _type = type; return *this; }
auto& size(natural size) { _size = size; return *this; }
auto& category(string category) { _category = category; return *this; }
auto& manufacturer(string manufacturer) { _manufacturer = manufacturer; return *this; }
auto& part(string part) { _part = part; return *this; }
auto& battery(boolean battery = true) { _battery = battery; return *this; }
auto& note(string note) { _note = note; return *this; }
auto text() const -> string;
string _type;
natural _size;
string _category;
string _manufacturer;
string _part;
boolean _battery;
string _note;
};
struct Oscillator {
auto& frequency(natural frequency) { _frequency = frequency; return *this; }
auto& note(string note) { _note = note; return *this; }
auto text() const -> string;
natural _frequency;
string _note;
};
struct Heuristics {
auto memory(string type, uint size, string name) const -> string;
auto memory(string type, uint size, string name, string metadata = {}) const -> string;
};
}

View File

@ -21,10 +21,11 @@ auto MasterSystem::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(memory("NVRAM", 0x8000, "save.ram"));
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
output.append(Memory{}.type("RAM").size(0x8000).category("Save").battery().text());
return output;
}

View File

@ -71,14 +71,15 @@ auto MegaDrive::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" region: ", regions.left(), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
if(ramSize && ramMode != "none") {
output.append(memory("NVRAM", ramSize, "save.ram"));
output.append(" mode: ", ramMode, "\n");
output.append(" offset: 0x", hex(ramFrom), "\n");
output.append(Memory{}.type("RAM").size(ramSize).category("Save").text());
output.append(" mode: ", ramMode, "\n");
output.append(" offset: 0x", hex(ramFrom), "\n");
}
return output;
}

View File

@ -26,9 +26,10 @@ auto PCEngine::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(" label:", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
return output;
}

View File

@ -27,10 +27,12 @@ auto SufamiTurbo::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
if(ramSize) output.append(memory("NVRAM", ramSize, "save.ram"));
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
if(ramSize)
output.append(Memory{}.type("RAM").size(ramSize).category("Save").battery().text());
return output;
}

View File

@ -57,66 +57,66 @@ auto SuperFamicom::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" region: ", region(), "\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" label: ", label(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" region: ", region(), "\n");
output.append(" revision: ", revision(), "\n");
output.append(" board: ", board(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", label(), "\n");
output.append(" board: ", board(), "\n");
auto board = this->board().split("-");
if(board.left() == "ARM") {
output.append(memory("ROM", size() - 0x28000, "program.rom"));
output.append(memory("ROM", 0x20000, {firmwareARM(), ".program.rom"}));
output.append(memory("ROM", 0x8000, {firmwareARM(), ".data.rom"}));
} else if(board.left() == "HITACHI") {
output.append(memory("ROM", size() - 0xc00, "program.rom"));
output.append(memory("ROM", 0xc00, {firmwareHITACHI(), ".data.rom"}));
} else if(board.left() == "NEC") {
output.append(memory("ROM", size() - 0x2000, "program.rom"));
output.append(memory("ROM", 0x1800, {firmwareNEC(), ".program.rom"}));
output.append(memory("ROM", 0x800, {firmwareNEC(), ".data.rom"}));
} else if(board.left() == "NECEX") {
output.append(memory("ROM", size() - 0xd000, "program.rom"));
output.append(memory("ROM", 0xc000, {firmwareNECEX(), ".program.rom"}));
output.append(memory("ROM", 0x1000, {firmwareNECEX(), ".data.rom"}));
} else if(board.left() == "SGB") {
output.append(memory("ROM", size() - 0x100, "program.rom"));
output.append(memory("ROM", 0x100, {firmwareSGB(), ".boot.rom"}));
} else if(board.left() == "SPC7110") {
output.append(memory("ROM", 0x100000, "program.rom"));
output.append(memory("ROM", size() - 0x100000, "data.rom"));
} else {
output.append(memory("ROM", size(), "program.rom"));
if(auto size = romSize()) {
if(board(0) == "SPC7110") size = 0x100000;
output.append(Memory{}.type("ROM").size(size).category("Program").text());
}
if(auto size = ramSize()) {
auto type = battery() ? "NVRAM" : "RAM";
output.append(memory(type, size, "save.ram"));
output.append(Memory{}.type("RAM").size(size).category("Save").battery(battery()).text());
}
if(auto size = expansionRamSize()) {
auto type = battery() ? "NVRAM" : "RAM";
output.append(memory(type, size, "expansion.ram"));
output.append(Memory{}.type("RAM").size(size).category("Expansion").battery(battery()).text());
}
if(board.left() == "ARM") {
output.append(memory("NVRAM", 0x4000, {firmwareARM(), ".data.ram"}));
} else if(board.left() == "BS" && board(1) == "MCC") {
output.append(memory("PSRAM", 0x80000, "download.ram"));
} else if(board.left() == "HITACHI") {
output.append(memory("RAM", 0xc00, {firmwareHITACHI(), ".data.ram"}));
} else if(board.left() == "NEC") {
output.append(memory("RAM", 0x200, {firmwareNEC(), ".data.ram"}));
} else if(board.left() == "NECEX") {
output.append(memory("NVRAM", 0x1000, {firmwareNEC(), ".data.ram"}));
} else if(board.left() == "RTC") {
output.append(memory("NVRAM", 0x10, "sharp.rtc.ram"));
} else if(board.left() == "SA1") {
output.append(memory("RAM", 0x800, "internal.ram"));
} else if(board.left() == "SPC7110" && board(1) == "RTC") {
output.append(memory("NVRAM", 0x10, "epson.rtc.ram"));
if(0) {
} else if(board(0) == "ARM") {
output.append(Memory{}.type("ROM").size(0x20000).manufacturer("SETA").part("ARM").category("Program").text());
output.append(Memory{}.type("ROM").size( 0x8000).manufacturer("SETA").part("ARM").category("Data").text());
output.append(Memory{}.type("RAM").size( 0x4000).manufacturer("SETA").part("ARM").category("Data").text());
output.append(Oscillator{}.frequency(21'440'000).text());
} else if(board(0) == "BS" && board(1) == "MCC") {
output.append(Memory{}.type("RAM").size(0x80000).category("Download").battery().text());
output.append(Memory{}.type("RTC").size(0x10).category("Time").text());
} else if(board(0) == "HITACHI") {
output.append(Memory{}.type("ROM").size(0xc00).manufacturer("Hitachi").part("HG51BS169").category("Data").note(firmwareHITACHI()).text());
output.append(Memory{}.type("RAM").size(0xc00).manufacturer("Hitachi").part("HG51BS169").category("Data").note(firmwareHITACHI()).text());
output.append(Oscillator{}.frequency(20'000'000).text());
} else if(board(0) == "NEC") {
output.append(Memory{}.type("ROM").size(0x1800).manufacturer("NEC").part("uPD7725").category("Program").note(firmwareNEC()).text());
output.append(Memory{}.type("ROM").size( 0x800).manufacturer("NEC").part("uPD7725").category("Data").note(firmwareNEC()).text());
output.append(Memory{}.type("RAM").size( 0x200).manufacturer("NEC").part("uPD7725").category("Data").note(firmwareNEC()).text());
output.append(Oscillator{}.frequency(7'600'000).text());
} else if(board(0) == "NECEX") {
output.append(Memory{}.type("ROM").size(0xc000).manufacturer("NEC").part("uPD96050").category("Program").note(firmwareNECEX()).text());
output.append(Memory{}.type("ROM").size(0x1000).manufacturer("NEC").part("uPD96050").category("Data").note(firmwareNECEX()).text());
output.append(Memory{}.type("RAM").size(0x1000).manufacturer("NEC").part("uPD96050").category("Data").note(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).category("Time").battery().text());
} else if(board(0) == "SA1") {
output.append(Memory{}.type("RAM").size(0x800).category("Internal").text());
} else if(board(0) == "SGB") {
output.append(Memory{}.type("ROM").size(0x100).manufacturer("Nintendo").part("SGB").category("Boot").note(firmwareSGB()).text());
if(firmwareSGB() == "SGB2")
output.append(Oscillator{}.frequency(20'971'520).text());
} else if(board(0) == "SPC7110") {
output.append(Memory{}.type("ROM").size(romSize() - 0x100000).category("Data").text());
if(board(1) == "RTC")
output.append(Memory{}.type("RTC").size(0x10).category("Time").battery().text());
} else if(board(0) == "SUPERFX") {
//todo: MARIO CHIP 1 uses CPU oscillator
output.append(Oscillator{}.frequency(21'440'000).text());
}
return output;
@ -151,20 +151,20 @@ auto SuperFamicom::region() const -> string {
}
if(!region) {
if(E == 0x00) region = {"SHVC-JPN"};
if(E == 0x01) region = { "SNS-USA"};
if(E == 0x02) region = {"SNSP-EUR"};
if(E == 0x03) region = {"SNSP-SCN"};
if(E == 0x06) region = {"SNSP-FRA"};
if(E == 0x07) region = {"SNSP-HOL"};
if(E == 0x08) region = {"SNSP-ESP"};
if(E == 0x09) region = {"SNSP-NOE"};
if(E == 0x0a) region = {"SNSP-ITA"};
if(E == 0x0b) region = {"SNSP-ROC"};
if(E == 0x0d) region = {"SNSP-KOR"};
if(E == 0x0f) region = { "SNS-CAN"};
if(E == 0x10) region = { "SNS-BRA"};
if(E == 0x11) region = {"SNSP-AUS"};
if(E == 0x00) region = {"JPN"};
if(E == 0x01) region = {"USA"};
if(E == 0x02) region = {"EUR"};
if(E == 0x03) region = {"SCN"};
if(E == 0x06) region = {"FRA"};
if(E == 0x07) region = {"HOL"};
if(E == 0x08) region = {"ESP"};
if(E == 0x09) region = {"NOE"};
if(E == 0x0a) region = {"ITA"};
if(E == 0x0b) region = {"ROC"};
if(E == 0x0d) region = {"KOR"};
if(E == 0x0f) region = {"CAN"};
if(E == 0x10) region = {"BRA"};
if(E == 0x11) region = {"AUS"};
}
return region ? region : "NTSC";
@ -200,20 +200,7 @@ auto SuperFamicom::revision() const -> string {
}
if(!revision) {
if(E == 0x00) revision = {"SHVC-", F};
if(E == 0x01) revision = { "SNS-", F};
if(E == 0x02) revision = {"SNSP-", F};
if(E == 0x03) revision = {"SSWE-", F};
if(E == 0x06) revision = {"SFRA-", F};
if(E == 0x07) revision = {"SHOL-", F};
if(E == 0x08) revision = {"SESP-", F};
if(E == 0x09) revision = {"SFRG-", F};
if(E == 0x0a) revision = {"SITA-", F};
if(E == 0x0b) revision = {"SSCN-", F};
if(E == 0x0d) revision = {"SKOR-", F};
if(E == 0x0f) revision = { "SNS-", F};
if(E == 0x10) revision = {"SBRA-", F};
if(E == 0x11) revision = {"SNSP-", F};
revision = {"1.", F};
}
return revision ? revision : string{"1.", F};
@ -410,9 +397,6 @@ auto SuperFamicom::romSize() const -> uint {
if((size() & 0xffff) == 0xd000) return size() - 0xd000;
if((size() & 0x3ffff) == 0x28000) return size() - 0x28000;
return size();
//auto romSize = data[headerAddress + 0x27] & 15;
//return 1024 << romSize;
}
auto SuperFamicom::ramSize() const -> uint {
@ -494,33 +478,33 @@ auto SuperFamicom::scoreHeader(uint address) -> uint {
}
auto SuperFamicom::firmwareARM() const -> string {
return "st018";
return "ST018";
}
auto SuperFamicom::firmwareHITACHI() const -> string {
return "cx4";
return "Cx4";
}
auto SuperFamicom::firmwareNEC() const -> string {
if(label() == "PILOTWINGS") return "dsp1";
if(label() == "DUNGEON MASTER") return "dsp2";
if(label() == "SDガンダムGX") return "dsp3";
if(label() == "PLANETS CHAMP TG3000") return "dsp4";
if(label() == "TOP GEAR 3000") return "dsp4";
return "dsp1b";
if(label() == "PILOTWINGS") return "DSP1";
if(label() == "DUNGEON MASTER") return "DSP2";
if(label() == "SDガンダムGX") return "DSP3";
if(label() == "PLANETS CHAMP TG3000") return "DSP4";
if(label() == "TOP GEAR 3000") return "DSP4";
return "DSP1B";
}
auto SuperFamicom::firmwareNECEX() const -> string {
if(label() == "EXHAUST HEAT2") return "st010";
if(label() == "F1 ROC II") return "st010";
if(label() == "2DAN MORITA SHOUGI") return "st011";
return "st010";
if(label() == "EXHAUST HEAT2") return "ST010";
if(label() == "F1 ROC II") return "ST010";
if(label() == "2DAN MORITA SHOUGI") return "ST011";
return "ST010";
}
auto SuperFamicom::firmwareSGB() const -> string {
if(label() == "Super GAMEBOY") return "sgb1";
if(label() == "Super GAMEBOY2") return "sgb2";
return "sgb1";
if(label() == "Super GAMEBOY") return "SGB1";
if(label() == "Super GAMEBOY2") return "SGB2";
return "SGB1";
}
}

View File

@ -21,9 +21,10 @@ auto SuperGrafx::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(memory("ROM", data.size(), "program.rom"));
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
return output;
}

View File

@ -27,11 +27,11 @@ auto WonderSwan::manifest() const -> string {
string ramType;
uint ramSize = 0;
switch(metadata[11]) {
case 0x01: ramType = "NVRAM"; ramSize = 8 * 1024; break;
case 0x02: ramType = "NVRAM"; ramSize = 32 * 1024; break;
case 0x03: ramType = "NVRAM"; ramSize = 128 * 1024; break;
case 0x04: ramType = "NVRAM"; ramSize = 256 * 1024; break;
case 0x05: ramType = "NVRAM"; ramSize = 512 * 1024; break;
case 0x01: ramType = "RAM"; ramSize = 8 * 1024; break;
case 0x02: ramType = "RAM"; ramSize = 32 * 1024; break;
case 0x03: ramType = "RAM"; ramSize = 128 * 1024; break;
case 0x04: ramType = "RAM"; ramSize = 256 * 1024; break;
case 0x05: ramType = "RAM"; ramSize = 512 * 1024; break;
case 0x10: ramType = "EEPROM"; ramSize = 128; break;
case 0x20: ramType = "EEPROM"; ramSize = 2048; break;
case 0x50: ramType = "EEPROM"; ramSize = 1024; break;
@ -43,12 +43,15 @@ auto WonderSwan::manifest() const -> string {
string output;
output.append("game\n");
output.append(" sha256: ", Hash::SHA256(data).digest(), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" label: ", Location::prefix(location), "\n");
output.append(" name: ", Location::prefix(location), "\n");
output.append(" orientation: ", !orientation ? "horizontal" : "vertical", "\n");
output.append(memory("ROM", data.size(), "program.rom"));
if(ramType && ramSize) output.append(memory(ramType, ramSize, "save.ram"));
if(hasRTC) output.append(memory("NVRAM", 16, "rtc.ram"));
output.append(" board\n");
output.append(Memory{}.type("ROM").size(data.size()).category("Program").text());
if(ramType && ramSize)
output.append(Memory{}.type(ramType).size(ramSize).category("Save").battery(ramType == "RAM").text());
if(hasRTC)
output.append(Memory{}.type("RTC").size(0x10).category("Time").text());
return output;
}