Update to v106r2 release.

byuu says:

Changelog:

  - Super Famicom: added support for loading manifests without embedded
    mapping information¹
  - genius: initial commit
  - various Makefile cleanups

¹: so the idea here is to try and aim for a stable manifest format,
and to allow direct transposition of icarus/genius database entries into
manifest files. The exact mechanics of how this is going to work is
currently in flux, but we'll get there.

For right now, `Super Famicom.sys` gains `boards.bml`, which is the raw
database from my board-editor tool, and higan itself tries to load
`boards.bml`, match an entry to game/board from the game's `manifest.bml`
file, and then transform it into the format currently used by higan. It
does this only when the game's `manifest.bml` file lacks a board node.
When such a board node exists, it works as previous versions of higan
did.

The only incompatible change right now is information/title is now
located at game/label. I may transition window title display to just use
the filenames instead.

Longer term, some thought is going to need to go into the format of the
`boards.bml` database itself, and at which point in the process I should
be transforming things.

Give it time, we'll refine this into something nicer.
This commit is contained in:
Tim Allen 2018-02-01 19:20:37 +11:00
parent aef8d5e962
commit 2f81b5a3e7
41 changed files with 29372 additions and 13627 deletions

59
genius/GNUmakefile Normal file
View File

@ -0,0 +1,59 @@
build := stable
include ../nall/GNUmakefile
include ../hiro/GNUmakefile
name := genius
flags += -I..
objects := obj/hiro.o
objects += obj/genius.o
objects += $(if $(call streq,$(platform),windows),obj/resource.o)
all: $(objects)
$(strip $(compiler) -o out/$(name) $(objects) $(link) $(hirolink))
ifeq ($(platform),macos)
rm -rf out/$(name).app
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
cp data/$(name).plist out/$(name).app/Contents/Info.plist
sips -s format icns data/$(name).png --out out/$(name).app/Contents/Resources/$(name).icns
endif
obj/hiro.o: ../hiro/hiro.cpp
$(compiler) $(hiroflags) -o obj/hiro.o -c ../hiro/hiro.cpp
obj/genius.o: genius.cpp genius.hpp
$(compiler) $(cppflags) $(flags) -o obj/genius.o -c genius.cpp
obj/resource.o:
$(windres) data/$(name).rc obj/resource.o
clean:
ifeq ($(platform),macos)
rm -rf out/$(name).app
endif
$(call rm,obj/*)
$(call rm,out/*)
install:
ifeq ($(platform),macos)
cp -R out/$(name).app /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/bin/
mkdir -p $(prefix)/share/applications/
mkdir -p $(prefix)/share/icons/
mkdir -p $(prefix)/share/$(name)/
cp out/$(name) $(prefix)/bin/$(name)
cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp data/$(name).png $(prefix)/share/icons/$(name).png
endif
uninstall:
ifeq ($(platform),macos)
rm -rf /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
rm -f $(prefix)/bin/$(name)
rm -f $(prefix)/share/applications/$(name).desktop
rm -f $(prefix)/share/icons/$(name).png
endif

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="genius" version="1.0.0.0" processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>
</dependentAssembly>
</dependency>
<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>false</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>

View File

@ -0,0 +1,8 @@
[Desktop Entry]
Name=genius
Comment=Emulator
Exec=genius
Icon=genius
Terminal=false
Type=Application
Categories=Game;Emulator;

BIN
genius/data/genius.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

18
genius/data/genius.plist Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>org.byuu.genius</string>
<key>CFBundleDisplayName</key>
<string>genius</string>
<key>CFBundleExecutable</key>
<string>genius</string>
<key>CFBundleIconFile</key>
<string>genius.icns</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSSupportsAutomaticGraphicsSwitching</key>
<true/>
</dict>
</plist>

BIN
genius/data/genius.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

2
genius/data/genius.rc Normal file
View File

@ -0,0 +1,2 @@
1 24 "genius.Manifest"
2 ICON DISCARDABLE "genius.ico"

80
genius/data/genius.svg Normal file
View File

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="256mm"
height="256mm"
viewBox="0 0 256 256"
version="1.1"
id="svg8"
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
sodipodi:docname="icarus.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="62.34093"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1920"
inkscape:window-height="1028"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-41)">
<circle
id="path10"
cx="128.0"
cy="169.0"
r="120.0"
style="stroke-width:0.25;fill:#b8b8ff;fill-opacity:1" />
<g
aria-label="氷"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:260.07336426px;line-height:1.25;font-family:KaiTi;-inkscape-font-specification:KaiTi;letter-spacing:0px;word-spacing:0px;fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="text818">
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 130.80961,146.24049 q 5.07956,5.07956 14.22276,15.23868 14.22277,-13.20685 25.39779,-27.42962 12.19094,-15.23867 11.17503,-24.38187 0,-10.15912 10.15912,-4.06365 10.15911,6.09547 14.22276,12.19094 4.06364,5.07956 -2.03182,7.11138 -6.09547,1.01591 -22.35006,14.22276 -15.23867,12.19094 -32.50917,26.4137 13.20685,11.17503 23.36597,20.31823 11.17502,9.14321 24.38187,18.28641 14.22277,8.1273 27.42962,14.22276 14.22276,5.07956 21.33414,7.11139 7.11138,2.03182 -3.04773,5.07955 -9.14321,2.03183 -23.36597,3.04774 -14.22276,0 -21.33414,-2.03182 -6.09547,-3.04774 -11.17503,-8.1273 -4.06365,-5.07956 -24.38188,-27.42961 -19.30232,-23.36597 -31.49326,-39.62055 1.01591,41.65237 2.03182,64.00243 2.03183,22.35005 0,34.54099 -2.03182,12.19094 -8.12729,19.30232 -5.07956,7.11138 -8.12729,4.06365 -2.03182,-2.03183 -7.11138,-11.17503 -5.07956,-8.12729 -16.254587,-15.23867 -11.175027,-8.1273 1.015912,-5.07956 12.190935,2.03182 16.254585,2.03182 4.06365,-1.01591 6.09547,-7.11138 2.03182,-7.11138 2.03182,-46.73193 0,-40.63646 -1.01591,-77.20928 -1.01591,-37.58873 -6.09547,-45.716022 -5.07956,-9.143205 4.06365,-7.111382 10.15911,1.015912 16.25458,5.079558 7.11138,3.047735 4.06365,9.143205 -3.04774,5.079557 -4.06365,15.238673 -1.01591,10.159118 -1.01591,51.811488 z"
id="path822" />
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 88.141325,149.28823 q 5.079558,1.01591 14.222765,7.11138 9.1432,6.09547 4.06364,10.15911 -5.07955,4.06365 -12.190935,18.28641 -6.09547,14.22276 -14.222763,25.39779 -8.127292,10.15912 -19.30232,19.30232 -11.175027,8.12729 -21.334143,12.19094 -9.143204,3.04774 -16.254585,5.07956 -6.095469,1.01591 5.079558,-6.09547 11.175027,-7.11138 21.334143,-17.2705 11.175027,-10.15911 18.286408,-21.33414 8.127293,-12.19094 11.175028,-20.31823 3.047735,-9.14321 3.047735,-14.22276 1.015911,-5.07956 -3.047735,-5.07956 -4.063646,0 -15.238674,4.06364 -10.159116,4.06365 -15.238674,6.09547 -4.063646,2.03183 -13.20685,-3.04773 -8.127293,-6.09547 2.031823,-6.09547 11.175027,-1.01591 24.381878,-5.07956 14.222762,-5.07956 17.270497,-7.11138 4.063646,-3.04773 9.143204,-2.03182 z"
id="path820" />
<path
style="fill:#4050e0;fill-opacity:1;stroke:#4050e0;stroke-width:6;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 63.759447,101.54038 q 9.143204,1.01591 18.286409,5.07956 9.143204,4.06365 11.175027,11.17503 2.031823,7.11138 -1.015912,11.17503 -3.047734,4.06364 -15.238673,-4.06365 -11.175028,-9.1432 -16.254586,-16.25459 -5.079557,-8.12729 3.047735,-7.11138 z"
id="path815" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

475
genius/genius.cpp Normal file
View File

@ -0,0 +1,475 @@
#include <nall/nall.hpp>
using namespace nall;
#include <hiro/hiro.hpp>
using namespace hiro;
#include "genius.hpp"
unique_pointer<ListWindow> listWindow;
unique_pointer<GameWindow> gameWindow;
unique_pointer<MemoryWindow> memoryWindow;
//
ListWindow::ListWindow() {
listWindow = this;
fileMenu.setText("File");
newAction.setText("New").onActivate([&] { newDatabase(); });
openAction.setText("Open ...").onActivate([&] {
if(auto location = BrowserDialog().setParent(*this).setFilters({"*.bml"}).openFile()) {
loadDatabase(location);
}
});
saveAction.setText("Save").onActivate([&] {
if(!location) return saveAsAction.doActivate();
saveDatabase(location);
});
saveAsAction.setText("Save As ...").onActivate([&] {
if(auto location = BrowserDialog().setParent(*this).setFilters({"*.bml"}).saveFile()) {
saveDatabase(location);
}
});
quitAction.setText("Quit").onActivate([&] { quit(); });
helpMenu.setText("Help");
aboutAction.setText("About ...").onActivate([&] {
MessageDialog().setParent(*this).setTitle("About").setText({
"genius v01\n",
"Author: byuu\n",
"Website: https://byuu.org/"
}).information();
});
layout.setMargin(5);
gameList.onActivate([&] { modifyButton.doActivate(); });
gameList.onChange([&] { updateWindow(); });
appendButton.setText("Append").onActivate([&] {
setEnabled(false);
gameWindow->show();
});
modifyButton.setText("Modify").onActivate([&] {
if(auto item = gameList.selected()) {
setEnabled(false);
gameWindow->show(games[item.offset()]);
}
});
removeButton.setText("Remove").onActivate([&] { removeGame(); });
onClose([&] { quit(); });
setSize({960, 600});
reloadList();
updateWindow();
setCentered();
setVisible();
}
auto ListWindow::quit() -> void {
if(!modified || MessageDialog().setParent(*this).setText({
"Are you sure you want to quit without saving your changes?"
}).question() == "Yes") {
Application::quit();
}
}
auto ListWindow::reloadList() -> void {
gameList.reset();
gameList.append(TableViewHeader()
.append(TableViewColumn().setText("Name").setExpandable())
.append(TableViewColumn().setText("Region"))
.append(TableViewColumn().setText("Revision"))
.append(TableViewColumn().setText("Board"))
);
for(auto& game : games) {
gameList.append(TableViewItem()
.append(TableViewCell().setText(game.name))
.append(TableViewCell().setText(game.region))
.append(TableViewCell().setText(game.revision))
.append(TableViewCell().setText(game.board))
);
}
Application::processEvents();
gameList.resizeColumns();
}
auto ListWindow::updateWindow() -> void {
modifyButton.setEnabled((bool)gameList.selected());
removeButton.setEnabled((bool)gameList.selected());
string name = Location::base(location);
if(!name) name = "(Untitled)";
setTitle({modified ? "*" : "", name, " [", games.size(), "] - genius"});
}
auto ListWindow::newDatabase() -> void {
games.reset();
modified = false;
location = "";
reloadList();
updateWindow();
}
auto ListWindow::loadDatabase(string location) -> void {
auto document = BML::unserialize(string::read(location));
games.reset();
for(auto node : document.find("game")) {
Game game;
game.sha256 = node["sha256"].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);
}
games.append(game);
}
modified = false;
this->location = location;
reloadList();
updateWindow();
}
auto ListWindow::saveDatabase(string location) -> void {
file fp{location, file::mode::write};
if(!fp) return MessageDialog().setParent(*this).setText({
"Error: failed to write file.\n\n",
"Name: ", location
}).error(), void();
auto copy = games;
copy.sort([](auto x, auto y) {
return string::icompare(x.name, y.name) < 0;
});
fp.print("database\n");
fp.print(" revision: ", chrono::local::date(), "\n\n");
for(auto& game : copy) {
fp.print("game\n");
fp.print(" sha256: ", game.sha256, "\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("\n");
}
modified = false;
this->location = location;
updateWindow();
}
auto ListWindow::appendGame(Game game) -> void {
modified = true;
auto offset = games.size();
games.append(game);
reloadList();
gameList.item(offset).setSelected().setFocused();
updateWindow();
}
auto ListWindow::modifyGame(Game game) -> void {
if(auto item = gameList.selected()) {
modified = true;
auto offset = item.offset();
games[offset] = game;
reloadList();
gameList.item(offset).setSelected().setFocused();
updateWindow();
}
}
auto ListWindow::removeGame() -> void {
if(auto item = gameList.selected()) {
if(MessageDialog().setParent(*this).setText({
"Are you sure you want to permanently remove this game?\n\n",
"Name: ", item.cell(0).text()
}).question() == "Yes") {
modified = true;
games.remove(item.offset());
reloadList();
updateWindow();
}
}
}
//
GameWindow::GameWindow() {
gameWindow = this;
layout.setMargin(5);
hashLabel.setText("SHA256:");
hashEdit.setFont(Font().setFamily(Font::Mono)).onChange([&] { modified = true, updateWindow(); });
regionLabel.setText("Region:");
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:");
nameEdit.onChange([&] { modified = true, updateWindow(); });
labelLabel.setText("Label:");
labelEdit.onChange([&] { modified = true, updateWindow(); });
noteLabel.setText("Note:");
noteEdit.onChange([&] { modified = true, updateWindow(); });
memoryList.onActivate([&] { modifyButton.doActivate(); });
memoryList.onChange([&] { updateWindow(); });
appendButton.setText("Append").onActivate([&] {
setEnabled(false);
memoryWindow->show();
});
modifyButton.setText("Modify").onActivate([&] {
if(auto item = memoryList.selected()) {
setEnabled(false);
memoryWindow->show(game.memories[item.offset()]);
}
});
removeButton.setText("Remove").onActivate([&] { removeMemory(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({800, 480});
setDismissable();
}
auto GameWindow::show(Game game) -> void {
this->game = game;
modified = false;
create = !game.sha256;
hashEdit.setText(game.sha256).setEditable(create);
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");
reloadList();
updateWindow();
setCentered(*listWindow);
setVisible();
if(create) {
hashEdit.setFocused();
} else {
cancelButton.setFocused();
}
}
auto GameWindow::accept() -> void {
game.sha256 = hashEdit.text().strip();
game.region = regionEdit.text().strip();
game.revision = revisionEdit.text().strip();
game.board = boardEdit.text().strip();
game.name = nameEdit.text().strip();
game.label = labelEdit.text().strip();
game.note = noteEdit.text().strip();
if(create) {
listWindow->appendGame(game);
} else {
listWindow->modifyGame(game);
}
memoryWindow->setVisible(false);
setVisible(false);
listWindow->setEnabled();
listWindow->setFocused();
}
auto GameWindow::cancel() -> void {
if(!modified || MessageDialog().setParent(*this).setText({
"Are you sure you want to discard your changes to this game?"
}).question() == "Yes") {
memoryWindow->setVisible(false);
setVisible(false);
listWindow->setEnabled();
listWindow->setFocused();
}
}
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))
);
}
Application::processEvents();
memoryList.resizeColumns();
}
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})
);
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());
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Game" : "Modify Game Details"});
}
auto GameWindow::appendMemory(Memory memory) -> void {
modified = true;
auto offset = game.memories.size();
game.memories.append(memory);
reloadList();
memoryList.item(offset).setSelected().setFocused();
updateWindow();
}
auto GameWindow::modifyMemory(Memory memory) -> void {
if(auto item = memoryList.selected()) {
modified = true;
auto offset = item.offset();
game.memories[offset] = memory;
reloadList();
memoryList.item(offset).setSelected().setFocused();
updateWindow();
}
}
auto GameWindow::removeMemory() -> void {
if(auto item = memoryList.selected()) {
if(MessageDialog().setParent(*this).setText({
"Are you sure you want to permanently remove this memory?\n\n",
"Name: ", item.cell(2).text()
}).question() == "Yes") {
modified = true;
game.memories.remove(item.offset());
reloadList();
updateWindow();
}
}
}
//
MemoryWindow::MemoryWindow() {
memoryWindow = this;
layout.setMargin(5);
typeLabel.setText("Type:");
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("RAM"));
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(); });
acceptButton.setText("Accept").onActivate([&] { accept(); });
cancelButton.setText("Cancel").onActivate([&] { cancel(); });
onClose([&] { cancel(); });
setSize({280, layout.minimumSize().height()});
setDismissable();
}
auto MemoryWindow::show(Memory memory) -> void {
this->memory = memory;
modified = false;
create = !memory.type;
typeEdit.setText(memory.type);
sizeEdit.setText(memory.size);
nameEdit.setText(memory.name);
updateWindow();
setCentered(*gameWindow);
setVisible();
typeEdit.setFocused();
}
auto MemoryWindow::accept() -> void {
memory.type = typeEdit.text().strip();
memory.size = sizeEdit.text().strip();
memory.name = nameEdit.text().strip();
if(create) {
gameWindow->appendMemory(memory);
} else {
gameWindow->modifyMemory(memory);
}
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
auto MemoryWindow::cancel() -> void {
if(!modified || MessageDialog().setParent(*this).setText({
"Are you sure you want to discard your changes to this memory?"
}).question() == "Yes") {
setVisible(false);
gameWindow->setEnabled();
gameWindow->setFocused();
}
}
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}));
acceptButton.setEnabled(valid);
setTitle({modified ? "*" : "", create ? "Add New Memory" : "Modify Memory Details"});
}
//
#include <nall/main.hpp>
auto nall::main(string_vector) -> void {
Application::setName("genius");
new ListWindow;
new GameWindow;
new MemoryWindow;
Application::run();
}

125
genius/genius.hpp Normal file
View File

@ -0,0 +1,125 @@
struct Memory {
string type;
string size;
string name;
};
struct Game {
string sha256;
string region;
string revision;
string board;
string name;
string label;
string note;
vector<Memory> memories;
};
struct ListWindow : Window {
ListWindow();
auto quit() -> void;
auto reloadList() -> void;
auto updateWindow() -> void;
auto newDatabase() -> void;
auto loadDatabase(string) -> void;
auto saveDatabase(string) -> void;
auto appendGame(Game) -> void;
auto modifyGame(Game) -> void;
auto removeGame() -> void;
private:
bool modified = false;
vector<Game> games;
string location;
MenuBar menuBar{this};
Menu fileMenu{&menuBar};
MenuItem newAction{&fileMenu};
MenuItem openAction{&fileMenu};
MenuItem saveAction{&fileMenu};
MenuItem saveAsAction{&fileMenu};
MenuSeparator quitSeparator{&fileMenu};
MenuItem quitAction{&fileMenu};
Menu helpMenu{&menuBar};
MenuItem aboutAction{&helpMenu};
HorizontalLayout layout{this};
TableView gameList{&layout, Size{~0, ~0}};
VerticalLayout controlLayout{&layout, Size{80, ~0}};
Button appendButton{&controlLayout, Size{~0, 0}};
Button modifyButton{&controlLayout, Size{~0, 0}};
Button removeButton{&controlLayout, Size{~0, 0}};
};
struct GameWindow : Window {
GameWindow();
auto show(Game = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto reloadList() -> void;
auto updateWindow() -> void;
auto appendMemory(Memory) -> void;
auto modifyMemory(Memory) -> void;
auto removeMemory() -> void;
private:
bool modified = false;
bool create = true;
Game game;
VerticalLayout layout{this};
HorizontalLayout hashLayout{&layout, Size{~0, 0}};
Label hashLabel{&hashLayout, Size{50, 0}};
LineEdit hashEdit{&hashLayout, Size{~0, 0}};
HorizontalLayout infoLayout{&layout, Size{~0, 0}};
Label regionLabel{&infoLayout, Size{50, 0}};
LineEdit regionEdit{&infoLayout, Size{~0, 0}};
Label revisionLabel{&infoLayout, Size{0, 0}};
LineEdit revisionEdit{&infoLayout, Size{~0, 0}};
Label boardLabel{&infoLayout, Size{0, 0}};
LineEdit boardEdit{&infoLayout, Size{~0, 0}};
HorizontalLayout nameLayout{&layout, Size{~0, 0}};
Label nameLabel{&nameLayout, Size{50, 0}};
LineEdit nameEdit{&nameLayout, Size{~0, 0}};
HorizontalLayout labelLayout{&layout, Size{~0, 0}};
Label labelLabel{&labelLayout, Size{50, 0}};
LineEdit labelEdit{&labelLayout, Size{~0, 0}};
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}};
};
struct MemoryWindow : Window {
MemoryWindow();
auto show(Memory = {}) -> void;
auto accept() -> void;
auto cancel() -> void;
auto updateWindow() -> void;
private:
bool modified = false;
bool create = true;
Memory memory;
VerticalLayout layout{this};
HorizontalLayout infoLayout{&layout, Size{~0, 0}};
Label typeLabel{&infoLayout, Size{40, 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 controlLayout{&layout, Size{~0, 0}};
Widget spacer{&controlLayout, Size{~0, 0}};
Button acceptButton{&controlLayout, Size{80, 0}};
Button cancelButton{&controlLayout, Size{80, 0}};
};

1
genius/obj/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.o

1
genius/out/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
genius

View File

@ -1,4 +1,4 @@
build := optimize
build := performance
include ../nall/GNUmakefile
binary := application
@ -8,7 +8,6 @@ objects := libco emulator audio video resource
flags += -I. -I..
ifeq ($(platform),windows)
link += $(if $(call streq,$(console),true),-mconsole,-mwindows)
ifeq ($(binary),application)
link += -mthreads -lpthread -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32
link += -Wl,-enable-auto-import
@ -61,5 +60,5 @@ ui := target-$(target)
include $(ui)/GNUmakefile
clean:
-@$(call delete,out/*)
-@$(call delete,obj/*)
$(call rm,out/*)
$(call rm,obj/*)

View File

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

View File

@ -66,6 +66,7 @@ private:
auto loadSufamiTurboB() -> bool;
//load.cpp
auto loadBoard(Markup::Node) -> Markup::Node;
auto loadCartridge(Markup::Node) -> void;
auto loadGameBoy(Markup::Node) -> void;
auto loadBSMemory(Markup::Node) -> void;

View File

@ -1,6 +1,61 @@
auto Cartridge::loadBoard(Markup::Node node) -> Markup::Node {
string output;
auto region = node["game/region"].text();
auto board = node["game/board"].text();
board.trimLeft("SHVC-", 1L);
board.trimLeft("SNSP-", 1L);
board.trimLeft("MAXI-", 1L);
board.trimLeft("MJSC-", 1L);
board.trimLeft("EA-", 1L);
if(auto fp = platform->open(ID::System, "boards.bml", File::Read, File::Required)) {
auto document = BML::unserialize(fp->reads());
for(auto leaf : document.find("board")) {
auto id = leaf["id"].text();
bool matched = id == board;
if(!matched && id.match("*(*)*")) {
auto part = id.transform("()", "||").split("|");
for(auto& revision : part(1).split(",")) {
if(string{part(0), revision, part(2)} == board) matched = true;
}
}
if(!matched) continue;
if(region.endsWith("-USA")
|| region.endsWith("-CAN")
|| region.endsWith("-JPN")
|| region.endsWith("-KOR")
|| region == "NTSC") {
output.append("region=ntsc\n");
} else {
output.append("region=pal\n");
}
uint counter = 0;
for(auto& line : leaf.text().split("\n")) {
if(line.endsWith("rom") || line.endsWith("ram")) {
auto memory = node.find("game/memory");
if(counter < memory.size()) {
line.append(" name=", memory[counter]["name"].text());
line.append(" size=", memory[counter]["size"].text());
if(memory[counter]["type"].text() == "RAM") line.append(" volatile");
counter++;
}
}
output.append(line, "\n");
}
break;
}
}
print(output, "\n");
return BML::unserialize(output);
}
auto Cartridge::loadCartridge(Markup::Node node) -> void {
information.title.cartridge = node["information/title"].text();
information.title.cartridge = node["game/label"].text();
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";

View File

@ -0,0 +1,407 @@
database type=sfc-boards revision=2017-12-29
board id: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 id: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 id: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 id: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 id: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 id: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 id:1A5B-(02,04)
:rom
: map address=00-1f,80-9f:8000-ffff mask=0x8000
:ram
: map address=70-7d,f0-ff:0000-ffff
board id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id:1DC0N-01
:hitachidsp model=HG51B169 frequency=20000000
: map address=00-3f,80-bf:6c00-6fff,7c00-7fff
: rom
: map address=00-3f,80-bf:8000-ffff mask=0x8000
: ram
: map address=70-77:0000-7fff mask=0x8000
: drom
: dram
: map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board id: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 id:1J0N-(01,10,20)
:rom
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
board id: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 id: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 id: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 id:1J5M-(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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id: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 id:2DC0N-01
:hitachidsp model=HG51B169 frequency=20000000
: map address=00-3f,80-bf:6c00-6fff,7c00-7fff
: rom
: map address=00-3f,80-bf:8000-ffff mask=0x8000
: ram
: map address=70-77:0000-7fff mask=0x8000
: drom
: dram
: map address=00-3f,80-bf:6000-6bff,7000-7bff mask=0xf000
board id: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 id:2J0N-(01,10,11,20)
:rom
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
board id: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 id: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 id:3J0N-01
:rom
: map address=00-2f,80-af:8000-ffff
: map address=40-6f,c0-ef:0000-ffff
board id: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 id: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 id: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 id:BJ0N-(01,20)
:rom
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff
board id:BJ1M-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 id: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 id:SGB-R-10
:rom
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
:icd2 revision=1
: map address=00-3f,80-bf:6000-67ff,7000-7fff
: rom
board id:YA0N-01
:rom
: map address=00-7d,80-ff:8000-ffff mask=0x8000
: map address=40-7d,c0-ff:0000-7fff mask=0x8000
board id:YJ0N-01
:rom
: map address=00-3f,80-bf:8000-ffff
: map address=40-7d,c0-ff:0000-ffff

View File

@ -69,7 +69,7 @@ obj/ui-resource.o:
build: $(objects)
$(strip $(compiler) -o out/$(name) $(objects) $(link))
ifeq ($(platform),macos)
@if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi
rm -rf out/$(name).app
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
@ -102,9 +102,9 @@ ifeq ($(shell id -un),root)
$(error "make uninstall should not be run as root")
else ifeq ($(platform),windows)
else ifeq ($(platform),macos)
if [ -d /Applications/$(name).app ]; then rm -r /Applications/$(name).app; fi
rm -rf /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi
if [ -f $(prefix)/share/applications/$(name).desktop ]; then rm $(prefix)/share/applications/$(name).desktop; fi
if [ -f $(prefix)/share/icons/$(name).png ]; then rm $(prefix)/share/icons/$(name).png; fi
rm -f $(prefix)/bin/$(name)
rm -f $(prefix)/share/applications/$(name).desktop
rm -f $(prefix)/share/icons/$(name).png
endif

View File

@ -60,7 +60,7 @@ auto BrowserDialogWindow::accept() -> void {
if(!name && batched) name = batched.left()->cell(0)->text();
if(!name || isFolder(name)) return;
if(file::exists({state.path, name})) {
if(MessageDialog("File already exists; overwrite it?").question() != "Yes") return;
if(MessageDialog("File already exists. Overwrite it?").question() != "Yes") return;
}
response.selected.append(string{state.path, name});
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,9 @@
build := optimize
build := performance
include ../nall/GNUmakefile
include ../hiro/GNUmakefile
name := icarus
flags += -I..
link +=
ifeq ($(platform),windows)
link += -mwindows
endif
objects := obj/hiro.o
objects += obj/icarus.o
@ -17,7 +12,7 @@ objects += $(if $(call streq,$(platform),windows),obj/resource.o)
all: $(objects)
$(strip $(compiler) -o out/$(name) $(objects) $(link) $(hirolink))
ifeq ($(platform),macos)
@if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi
rm -rf out/$(name).app
mkdir -p out/$(name).app/Contents/MacOS/
mkdir -p out/$(name).app/Contents/Resources/
mv out/$(name) out/$(name).app/Contents/MacOS/$(name)
@ -32,14 +27,14 @@ obj/icarus.o: icarus.cpp $(call rwildcard,core/) $(call rwildcard,heuristics/) $
$(compiler) $(cppflags) $(flags) -o obj/icarus.o -c icarus.cpp
obj/resource.o:
$(windres) data/icarus.rc obj/resource.o
$(windres) data/$(name).rc obj/resource.o
clean:
ifeq ($(platform),macos)
@if [ -d out/$(name).app ]; then rm out/$(name).app; fi
rm -rf out/$(name).app
endif
-@$(call delete,obj/*)
-@$(call delete,out/*)
$(call rm,obj/*)
$(call rm,out/*)
install:
ifeq ($(platform),macos)
@ -49,17 +44,17 @@ else ifneq ($(filter $(platform),linux bsd),)
mkdir -p $(prefix)/share/applications/
mkdir -p $(prefix)/share/icons/
mkdir -p $(prefix)/share/$(name)/Database/
if [ -f out/$(name) ]; then cp out/$(name) $(prefix)/bin/$(name); fi
cp -R Database/* $(prefix)/share/$(name)/Database/
cp out/$(name) $(prefix)/bin/$(name)
cp data/$(name).desktop $(prefix)/share/applications/$(name).desktop
cp data/$(name).png $(prefix)/share/icons/$(name).png
cp -R Database/* $(prefix)/share/$(name)/Database/
endif
uninstall:
ifeq ($(platform),macos)
if [ -d /Applications/$(name).app ]; then rm -r /Applications/$(name).app; fi
rm -rf /Applications/$(name).app
else ifneq ($(filter $(platform),linux bsd),)
if [ -f $(prefix)/bin/$(name) ]; then rm $(prefix)/bin/$(name); fi
if [ -f $(prefix)/share/applications/$(name).desktop ]; then rm $(prefix)/share/applications/$(name).desktop; fi
if [ -f $(prefix)/share/icons/$(name).png ]; then rm $(prefix)/share/icons/$(name).png; fi
rm -f $(prefix)/bin/$(name)
rm -f $(prefix)/share/applications/$(name).desktop
rm -f $(prefix)/share/icons/$(name).png
endif

View File

@ -12,13 +12,12 @@ auto Icarus::superFamicomManifest(string location) -> string {
auto Icarus::superFamicomManifest(vector<uint8_t>& buffer, string location) -> string {
string markup;
string digest = Hash::SHA256(buffer.data(), buffer.size()).digest();
string digest = Hash::SHA256(buffer).digest();
if(settings["icarus/UseDatabase"].boolean() && !markup) {
for(auto node : database.superFamicom) {
if(node["sha256"].text() == digest) {
markup.append(node.text(), "\n sha256: ", digest, "\n");
break;
for(auto game : database.superFamicom.find("game")) {
if(game["sha256"].text() == digest) {
return BML::serialize(game);
}
}
}
@ -28,10 +27,10 @@ auto Icarus::superFamicomManifest(vector<uint8_t>& buffer, string location) -> s
SuperFamicomCartridge cartridge{buffer.data(), buffer.size(), hasMSU1};
if(markup = cartridge.markup) {
markup.append("\n");
markup.append("information\n");
markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n");
markup.append(" title: ", Location::prefix(location), "\n");
markup.append("game\n");
markup.append(" sha256: ", digest, "\n");
markup.append(" region: ", cartridge.region == SuperFamicomCartridge::Region::NTSC ? "NTSC" : "PAL", "\n");
markup.append(" label: ", Location::prefix(location), "\n");
markup.append(" note: ", "heuristically generated by icarus\n");
}
}

View File

@ -2,11 +2,11 @@
MAKEFLAGS := Rr
.SUFFIXES:
[0-9] = 0 1 2 3 4 5 6 7 8 9
[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z
[0-9] = 0 1 2 3 4 5 6 7 8 9
[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ?
[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup])
[all] = $([0-9]) $([A-Z]) $([a-z]) $([markup])
[space] :=
[space] +=
@ -15,22 +15,28 @@ ifeq ($(platform),)
uname := $(shell uname -s)
ifeq ($(uname),)
platform := windows
delete = del $(subst /,\,$1)
rm = del /q $(subst /,\,$1)
rmdir = del /s /q $(subst /,\,$1) && if exist $(subst /,\,$1) (rmdir /s /q $(subst /,\,$1))
else ifneq ($(findstring Windows,$(uname)),)
platform := windows
delete = del $(subst /,\,$1)
rm = del /q $(subst /,\,$1)
rmdir = del /s /q $(subst /,\,$1) && if exist $(subst /,\,$1) (rmdir /s /q $(subst /,\,$1))
else ifneq ($(findstring _NT,$(uname)),)
platform := windows
delete = del $(subst /,\,$1)
rm = del /q $(subst /,\,$1)
rmdir = del /s /q $(subst /,\,$1) && if exist $(subst /,\,$1) (rmdir /s /q $(subst /,\,$1))
else ifneq ($(findstring Darwin,$(uname)),)
platform := macos
delete = rm -f $1
rm = rm -f $1
rmdir = rm -rf $1
else ifneq ($(findstring Linux,$(uname)),)
platform := linux
delete = rm -f $1
rm = rm -f $1
rmdir = rm -rf $1
else ifneq ($(findstring BSD,$(uname)),)
platform := bsd
delete = rm -f $1
rm = rm -f $1
rmdir = rm -rf $1
else
$(error unknown platform, please specify manually.)
endif
@ -59,23 +65,17 @@ ifeq ($(compiler),)
endif
endif
# build settings
ifeq ($(build),optimize)
flags += -O3
else ifeq ($(build),release)
flags += -O2
# build optimization levels
ifeq ($(build),debug)
flags += -Og -DBUILD_DEBUG
else ifeq ($(build),stable)
flags += -O1
else ifeq ($(build),debug)
flags += -g
else ifeq ($(build),profile)
flags += -pg
link += -pg
else ifeq ($(build),instrument)
flags += -O3 -fprofile-generate
link += -lgcov
else ifeq ($(build),optimize)
flags += -O3 -fprofile-use
flags += -O1 -DBUILD_STABLE
else ifeq ($(build),size)
flags += -Os -DBUILD_SIZE
else ifeq ($(build),release)
flags += -O2 -DBUILD_RELEASE
else ifeq ($(build),performance)
flags += -O3 -DBUILD_PERFORMANCE
endif
# clang settings

View File

@ -343,7 +343,7 @@ inline auto to_vector(Pair value) -> vector<uint8_t> {
return result;
}
/*
#if 0
inline auto hex(const Pair& value, long precision = 0, char padchar = '0') -> string {
string text;
if(!upper(value)) {
@ -354,7 +354,7 @@ inline auto hex(const Pair& value, long precision = 0, char padchar = '0') -> st
}
return pad(text, precision, padchar);
}
*/
#endif
}

View File

@ -15,10 +15,18 @@ struct array {
}
auto operator[](uint index) -> T& {
#ifdef DEBUG
struct out_of_bounds {};
if(index >= Capacity) throw out_of_bounds{};
#endif
return _pool.t[index];
}
auto operator[](uint index) const -> const T& {
#ifdef DEBUG
struct out_of_bounds {};
if(index >= Capacity) throw out_of_bounds{};
#endif
return _pool.t[index];
}

View File

@ -47,6 +47,10 @@ struct bitvector {
}
auto get(uint position) const -> bool {
#ifdef DEBUG
struct out_of_bounds {};
if(position >= bits) throw out_of_bounds{};
#endif
return pool[position >> 3] & (0x80 >> (position & 7));
}

37
nall/decode/base.hpp Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Decode {
template<uint Bits, typename T> inline auto Base(const string& value) -> T {
static const string format =
Bits == 2 ? "01"
: Bits == 8 ? "01234567"
: Bits == 10 ? "0123456789"
: Bits == 16 ? "0123456789abcdef"
: Bits == 32 ? "0123456789abcdefghijklmnopqrstuv"
: Bits == 34 ? "023456789abcdefghijkmnopqrstuvwxyz" //1l
: Bits == 36 ? "0123456789abcdefghijklmnopqrstuvwxyz"
: Bits == 57 ? "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" //01IOl
: Bits == 62 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
: Bits == 64 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}"
: Bits == 85 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%()+,-.:;=@[]^_`{|}~" //\ "&'*/<>?
: "";
static bool initialized = false;
static uint8_t lookup[256] = {0};
if(!initialized) {
initialized = true;
for(uint n : range(format.size())) {
lookup[format[n]] = n;
}
}
T result = 0;
for(auto byte : value) {
result = result * Bits + lookup[byte];
}
return result;
}
}}

View File

@ -1,23 +0,0 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Decode {
template<typename T> inline auto Base57(const string& value) -> T {
T result = 0;
for(auto n : rrange(value.size())) {
auto byte = value[n];
if(byte >= '2' && byte <= '9') byte -= '2' - 0;
else if(byte >= 'A' && byte <= 'H') byte -= 'A' - 8;
else if(byte >= 'J' && byte <= 'N') byte -= 'J' - 16;
else if(byte >= 'P' && byte <= 'Z') byte -= 'P' - 21;
else if(byte >= 'a' && byte <= 'k') byte -= 'a' - 32;
else if(byte >= 'm' && byte <= 'z') byte -= 'm' - 43;
else return 0;
result = result * 57 + byte;
}
return result;
}
}}

View File

@ -3,23 +3,23 @@
namespace nall { namespace Decode {
inline auto Base64(const string& text) -> vector<uint8_t> {
auto value = [](char n) -> uint8_t {
if(n >= 'A' && n <= 'Z') return n - 'A' + 0;
if(n >= 'a' && n <= 'z') return n - 'a' + 26;
if(n >= '0' && n <= '9') return n - '0' + 52;
if(n == '+' || n == '-') return 62;
if(n == '/' || n == '_') return 63;
return 64; //error code
};
static bool initialized = false;
static uint8_t lookup[256] = {0};
if(!initialized) {
initialized = true;
for(uint n : range(26)) lookup['A' + n] = n;
for(uint n : range(26)) lookup['a' + n] = n + 26;
for(uint n : range(10)) lookup['0' + n] = n + 52;
lookup['+'] = lookup['-'] = 62;
lookup['/'] = lookup['_'] = 63;
}
vector<uint8_t> result;
uint8_t buffer, output;
for(unsigned i = 0; i < text.size(); i++) {
uint8_t buffer = value(text[i]);
if(buffer > 63) break;
for(uint n : range(text.size())) {
uint8_t buffer = lookup[text[n]];
switch(i & 3) {
switch(n & 3) {
case 0:
output = buffer << 2;
break;
@ -40,6 +40,7 @@ inline auto Base64(const string& text) -> vector<uint8_t> {
}
}
if(text.size() & 3) result.append(output | buffer);
return result;
}

33
nall/encode/base.hpp Normal file
View File

@ -0,0 +1,33 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Encode {
template<uint Bits, typename T> inline auto Base(T value) -> string {
static const string format =
Bits == 2 ? "01"
: Bits == 8 ? "01234567"
: Bits == 10 ? "0123456789"
: Bits == 16 ? "0123456789abcdef"
: Bits == 32 ? "0123456789abcdefghijklmnopqrstuv"
: Bits == 34 ? "023456789abcdefghijkmnopqrstuvwxyz" //1l
: Bits == 36 ? "0123456789abcdefghijklmnopqrstuvwxyz"
: Bits == 57 ? "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" //01IOl
: Bits == 62 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
: Bits == 64 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz{}"
: Bits == 85 ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%()+,-.:;=@[]^_`{|}~" //\ "&'*/<>?
: "";
static const uint size = ceil(sizeof(T) * 8 / log2(Bits));
string result;
result.resize(size);
char* data = result.get() + size;
for(auto byte : result) {
*--data = format[value % Bits];
value /= Bits;
}
return result;
}
}}

View File

@ -1,19 +0,0 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Encode {
template<typename T> inline auto Base57(T value) -> string {
static const char lookup[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const uint size = ceil(sizeof(T) * 8 / log2(57));
string result;
for(auto n : range(size)) {
result.append(lookup[value % 57]);
value /= 57;
}
return result;
}
}}

View File

@ -2,14 +2,15 @@
namespace nall { namespace Encode {
inline auto Base64(const void* vdata, unsigned size, const string& format = "MIME") -> string {
auto data = (const uint8_t*)vdata;
vector<uint8_t> result;
char lookup[65];
for(unsigned n = 0; n < 26; n++) lookup[ 0 + n] = 'A' + n;
for(unsigned n = 0; n < 26; n++) lookup[26 + n] = 'a' + n;
for(unsigned n = 0; n < 10; n++) lookup[52 + n] = '0' + n;
inline auto Base64(const void* vdata, uint size, const string& format = "MIME") -> string {
static bool initialized = false;
static char lookup[65] = {0};
if(!initialized) {
initialized = true;
for(uint n : range(26)) lookup[n + 0] = 'A' + n;
for(uint n : range(26)) lookup[n + 26] = 'a' + n;
for(uint n : range(10)) lookup[n + 52] = '0' + n;
}
if(format == "MIME") {
lookup[62] = '+';
@ -21,37 +22,36 @@ inline auto Base64(const void* vdata, unsigned size, const string& format = "MIM
lookup[64] = 0;
} else return "";
unsigned overflow = (3 - (size % 3)) % 3; //bytes to round to nearest multiple of 3
auto data = (const uint8_t*)vdata;
uint overflow = (3 - (size % 3)) % 3; //bytes to round to nearest multiple of 3
string result;
uint8_t buffer;
for(unsigned i = 0; i < size; i++) {
switch(i % 3) {
for(uint n : range(size)) {
switch(n % 3) {
case 0:
buffer = data[i] >> 2;
result.append(lookup[buffer]);
buffer = (data[i] & 3) << 4;
buffer = data[n] >> 2;
result.append(lookup[buffer]);
buffer = (data[n] & 3) << 4;
break;
case 1:
buffer |= data[i] >> 4;
result.right() = lookup[buffer];
buffer = (data[i] & 15) << 2;
buffer |= data[n] >> 4;
result.append(lookup[buffer]);
buffer = (data[n] & 15) << 2;
break;
case 2:
buffer |= data[i] >> 6;
result.right() = lookup[buffer];
buffer = (data[i] & 63);
buffer |= data[n] >> 6;
result.append(lookup[buffer]);
buffer = (data[n] & 63);
result.append(lookup[buffer]);
break;
}
}
if(overflow) result.append(lookup[buffer]);
if(lookup[64]) {
if(overflow >= 1) result.append(lookup[64]);
if(overflow >= 2) result.append(lookup[64]);
while(result.size() % 4) result.append(lookup[64]);
}
return result;

View File

@ -3,21 +3,21 @@
namespace nall {
using uint = unsigned;
struct Intrinsics {
enum class Compiler : uint { Clang, GCC, VisualCPP, Unknown };
enum class Compiler : uint { Clang, GCC, Microsoft, Unknown };
enum class Platform : uint { Windows, MacOS, Linux, BSD, Unknown };
enum class API : uint { Windows, Posix, Unknown };
enum class Display : uint { Windows, Quartz, Xorg, Unknown };
enum class DisplayServer : uint { Windows, Quartz, Xorg, Unknown };
enum class Processor : uint { x86, amd64, ARM, PPC32, PPC64, Unknown };
enum class Endian : uint { LSB, MSB, Unknown };
enum class Build : uint { Debug, Stable, Size, Release, Performance };
static inline auto compiler() -> Compiler;
static inline auto platform() -> Platform;
static inline auto api() -> API;
static inline auto display() -> Display;
static inline auto processor() -> Processor;
static inline auto endian() -> Endian;
};
static inline constexpr auto compiler() -> Compiler;
static inline constexpr auto platform() -> Platform;
static inline constexpr auto api() -> API;
static inline constexpr auto display() -> DisplayServer;
static inline constexpr auto processor() -> Processor;
static inline constexpr auto endian() -> Endian;
static inline constexpr auto build() -> Build;
}
/* Compiler detection */
@ -26,7 +26,7 @@ namespace nall {
#if defined(__clang__)
#define COMPILER_CLANG
auto Intrinsics::compiler() -> Compiler { return Compiler::Clang; }
constexpr auto compiler() -> Compiler { return Compiler::Clang; }
#pragma clang diagnostic ignored "-Wunknown-pragmas"
#pragma clang diagnostic ignored "-Wempty-body"
@ -42,20 +42,20 @@ namespace nall {
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#elif defined(__GNUC__)
#define COMPILER_GCC
auto Intrinsics::compiler() -> Compiler { return Compiler::GCC; }
constexpr auto compiler() -> Compiler { return Compiler::GCC; }
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#pragma GCC diagnostic ignored "-Wswitch-bool"
#elif defined(_MSC_VER)
#define COMPILER_VISUALCPP
auto Intrinsics::compiler() -> Compiler { return Compiler::VisualCPP; }
#define COMPILER_MICROSOFT
constexpr auto compiler() -> Compiler { return Compiler::Microsoft; }
#pragma warning(disable:4996) //libc "deprecation" warnings
#else
#warning "unable to detect compiler"
#define COMPILER_UNKNOWN
auto Intrinsics::compiler() -> Compiler { return Compiler::Unknown; }
constexpr auto compiler() -> Compiler { return Compiler::Unknown; }
#endif
}
@ -68,38 +68,38 @@ namespace nall {
#define PLATFORM_WINDOWS
#define API_WINDOWS
#define DISPLAY_WINDOWS
auto Intrinsics::platform() -> Platform { return Platform::Windows; }
auto Intrinsics::api() -> API { return API::Windows; }
auto Intrinsics::display() -> Display { return Display::Windows; }
constexpr auto platform() -> Platform { return Platform::Windows; }
constexpr auto api() -> API { return API::Windows; }
constexpr auto display() -> DisplayServer { return DisplayServer::Windows; }
#elif defined(__APPLE__)
#define PLATFORM_MACOS
#define API_POSIX
#define DISPLAY_QUARTZ
auto Intrinsics::platform() -> Platform { return Platform::MacOS; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Quartz; }
constexpr auto platform() -> Platform { return Platform::MacOS; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Quartz; }
#elif defined(linux) || defined(__linux__)
#define PLATFORM_LINUX
#define API_POSIX
#define DISPLAY_XORG
auto Intrinsics::platform() -> Platform { return Platform::Linux; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Xorg; }
constexpr auto platform() -> Platform { return Platform::Linux; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Xorg; }
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define PLATFORM_BSD
#define API_POSIX
#define DISPLAY_XORG
auto Intrinsics::platform() -> Platform { return Platform::BSD; }
auto Intrinsics::api() -> API { return API::Posix; }
auto Intrinsics::display() -> Display { return Display::Xorg; }
constexpr auto platform() -> Platform { return Platform::BSD; }
constexpr auto api() -> API { return API::Posix; }
constexpr auto display() -> DisplayServer { return DisplayServer::Xorg; }
#else
#warning "unable to detect platform"
#define PLATFORM_UNKNOWN
#define API_UNKNOWN
#define DISPLAY_UNKNOWN
auto Intrinsics::platform() -> Platform { return Platform::Unknown; }
auto Intrinsics::api() -> API { return API::Unknown; }
auto Intrinsics::display() -> Display { return Display::Unknown; }
constexpr auto platform() -> Platform { return Platform::Unknown; }
constexpr auto api() -> API { return API::Unknown; }
constexpr auto display() -> DisplayServer { return DisplayServer::Unknown; }
#endif
}
@ -112,29 +112,29 @@ namespace nall {
#include <sys/endian.h>
#endif
/* Processor Detection */
/* Processor detection */
namespace nall {
#if defined(__i386__) || defined(_M_IX86)
#define PROCESSOR_X86
auto Intrinsics::processor() -> Processor { return Processor::x86; }
constexpr auto processor() -> Processor { return Processor::x86; }
#elif defined(__amd64__) || defined(_M_AMD64)
#define PROCESSOR_AMD64
auto Intrinsics::processor() -> Processor { return Processor::amd64; }
constexpr auto processor() -> Processor { return Processor::amd64; }
#elif defined(__arm__)
#define PROCESSOR_ARM
auto Intrinsics::processor() -> Processor { return Processor::ARM; }
constexpr auto processor() -> Processor { return Processor::ARM; }
#elif defined(__ppc64__) || defined(_ARCH_PPC64)
#define PROCESSOR_PPC64
auto Intrinsics::processor() -> Processor { return Processor::PPC64; }
constexpr auto processor() -> Processor { return Processor::PPC64; }
#elif defined(__ppc__) || defined(_ARCH_PPC) || defined(_M_PPC)
#define PROCESSOR_PPC32
auto Intrinsics::processor() -> Processor { return Processor::PPC32; }
constexpr auto processor() -> Processor { return Processor::PPC32; }
#else
#warning "unable to detect processor"
#define PROCESSOR_UNKNOWN
auto Intrinsics::processor() -> Processor { return Processor::Unknown; }
constexpr auto processor() -> Processor { return Processor::Unknown; }
#endif
}
@ -145,14 +145,44 @@ namespace nall {
#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64)
#define ENDIAN_LSB
auto Intrinsics::endian() -> Endian { return Endian::LSB; }
constexpr auto endian() -> Endian { return Endian::LSB; }
#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || defined(__BIG_ENDIAN__) || defined(__powerpc__) || defined(_M_PPC)
#define ENDIAN_MSB
auto Intrinsics::endian() -> Endian { return Endian::MSB; }
constexpr auto endian() -> Endian { return Endian::MSB; }
#else
#warning "unable to detect endian"
#define ENDIAN_UNKNOWN
auto Intrinsics::endian() -> Endian { return Endian::Unknown; }
constexpr auto endian() -> Endian { return Endian::Unknown; }
#endif
}
/* Build optimization level detection */
#undef DEBUG
#undef NDEBUG
namespace nall {
#if defined(BUILD_DEBUG)
#define DEBUG
constexpr auto build() -> Build { return Build::Debug; }
#elif defined(BUILD_STABLE)
#define DEBUG
constexpr auto build() -> Build { return Build::Stable; }
#elif defined(BUILD_SIZE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Size; }
#elif defined(BUILD_RELEASE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Release; }
#elif defined(BUILD_PERFORMANCE)
#define NDEBUG
constexpr auto build() -> Build { return Build::Performance; }
#else
//default to debug mode
#define DEBUG
constexpr auto build() -> Build { return Build::Debug; }
#endif
}

View File

@ -58,6 +58,7 @@
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/decode/base.hpp>
#include <nall/decode/base64.hpp>
#include <nall/decode/bmp.hpp>
#include <nall/decode/gzip.hpp>
@ -65,6 +66,7 @@
#include <nall/decode/png.hpp>
#include <nall/decode/url.hpp>
#include <nall/decode/zip.hpp>
#include <nall/encode/base.hpp>
#include <nall/encode/base64.hpp>
#include <nall/encode/url.hpp>
#include <nall/hash/crc16.hpp>

View File

@ -54,7 +54,7 @@ namespace Math {
#include <poll.h>
#endif
#if defined(COMPILER_VISUALCPP)
#if defined(COMPILER_MICROSOFT)
#define va_copy(dest, src) ((dest) = (src))
#endif
@ -104,7 +104,7 @@ namespace Math {
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#define neverinline __attribute__((noinline))
#define alwaysinline inline __attribute__((always_inline))
#elif defined(COMPILER_VISUALCPP)
#elif defined(COMPILER_MICROSOFT)
#define neverinline __declspec(noinline)
#define alwaysinline inline __forceinline
#else

View File

@ -174,8 +174,8 @@ public:
inline auto real() const -> double;
//core.hpp
inline auto operator[](int) const -> const char&;
inline auto operator()(int, char) const -> char;
inline auto operator[](uint) const -> const char&;
inline auto operator()(uint, char) const -> char;
template<typename... P> inline auto assign(P&&...) -> type&;
template<typename T, typename... P> inline auto prepend(const T&, P&&...) -> type&;
template<typename... P> inline auto prepend(const nall::string_format&, P&&...) -> type&;

View File

@ -15,13 +15,16 @@
namespace nall {
auto string::operator[](int position) const -> const char& {
//if(position > size() + 1) throw;
auto string::operator[](uint position) const -> const char& {
#ifdef DEBUG
struct out_of_bounds {};
if(position >= size() + 1) throw out_of_bounds{};
#endif
return data()[position];
}
auto string::operator()(int position, char fallback) const -> char {
if(position > size() + 1) return fallback;
auto string::operator()(uint position, char fallback) const -> char {
if(position >= size() + 1) return fallback;
return data()[position];
}

View File

@ -84,11 +84,14 @@ auto string::size(int length, char fill) -> string& {
auto slice(string_view self, int offset, int length) -> string {
string result;
if(offset < self.size()) {
if(offset < 0) offset = self.size() - abs(offset);
if(offset >= 0 && offset < self.size()) {
if(length < 0) length = self.size() - offset;
if(length >= 0) {
result.resize(length);
memory::copy(result.get(), self.data() + offset, length);
}
}
return result;
}

View File

@ -3,10 +3,18 @@
namespace nall {
template<typename T> auto vector<T>::operator[](uint offset) -> T& {
#ifdef DEBUG
struct out_of_bounds {};
if(offset >= size()) throw out_of_bounds{};
#endif
return _pool[offset];
}
template<typename T> auto vector<T>::operator[](uint offset) const -> const T& {
#ifdef DEBUG
struct out_of_bounds {};
if(offset >= size()) throw out_of_bounds{};
#endif
return _pool[offset];
}

View File

@ -1,14 +1,5 @@
#pragma once
/* ruby
* author: byuu
* license: ISC
* version: 0.16 (2017-07-08)
*
* ruby is a cross-platform hardware abstraction layer.
* it provides a common interface to video, audio and input devices.
*/
#include <nall/nall.hpp>
namespace ruby {