diff --git a/bsnes/Makefile b/bsnes/Makefile index 702371d4..58051cb2 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -1,9 +1,12 @@ include nall/Makefile snes := snes gameboy := gameboy -profile := accuracy +profile := compatibility ui := ui +# debugger +options := + # compiler c := $(compiler) -std=gnu99 cpp := $(subst cc,++,$(compiler)) -std=gnu++0x @@ -18,9 +21,11 @@ objects := libco # profile-guided optimization # flags += -fprofile-use +flags := $(flags) $(foreach o,$(call strupper,$(options)),-D$o) + # platform ifeq ($(platform),x) - link += -s -ldl -lX11 -lXext + link += -ldl -lX11 -lXext else ifeq ($(platform),osx) else ifeq ($(platform),win) link += -mwindows diff --git a/bsnes/nall/string/convert.hpp b/bsnes/nall/string/convert.hpp index ca77db85..603d2e0e 100755 --- a/bsnes/nall/string/convert.hpp +++ b/bsnes/nall/string/convert.hpp @@ -117,38 +117,7 @@ uintmax_t binary(const char *str) { } double fp(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.' || x == ',') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; + return atof(str); } } diff --git a/bsnes/nall/string/platform.hpp b/bsnes/nall/string/platform.hpp index 42c1a756..6ee5e1a9 100755 --- a/bsnes/nall/string/platform.hpp +++ b/bsnes/nall/string/platform.hpp @@ -8,7 +8,6 @@ string realpath(const char *name) { if(::realpath(name, path)) { string result(path); result.transform("\\", "/"); - if(result.endswith("/") == false) result.append("/"); return result; } return ""; diff --git a/bsnes/ruby/ruby.cpp b/bsnes/ruby/ruby.cpp index 8b84c4f4..73b53c28 100755 --- a/bsnes/ruby/ruby.cpp +++ b/bsnes/ruby/ruby.cpp @@ -1,5 +1,4 @@ #include -using namespace nall; #undef mkdir #undef usleep diff --git a/bsnes/ruby/ruby.hpp b/bsnes/ruby/ruby.hpp index 4d1b1a35..4b64f880 100755 --- a/bsnes/ruby/ruby.hpp +++ b/bsnes/ruby/ruby.hpp @@ -1,6 +1,6 @@ /* ruby - version: 0.06 (2009-05-22) + version: 0.06a (2011-02-27) license: public domain */ diff --git a/bsnes/ruby/ruby_impl.cpp b/bsnes/ruby/ruby_impl.cpp index 4b7049e2..ac517a1f 100755 --- a/bsnes/ruby/ruby_impl.cpp +++ b/bsnes/ruby/ruby_impl.cpp @@ -24,6 +24,8 @@ #include #endif +using namespace nall; + /* Video */ #define DeclareVideo(Name) \ diff --git a/bsnes/snes/memory/memory.cpp b/bsnes/snes/memory/memory.cpp index 74fd4086..4513b472 100755 --- a/bsnes/snes/memory/memory.cpp +++ b/bsnes/snes/memory/memory.cpp @@ -44,12 +44,8 @@ void Bus::map( for(unsigned bank = bank_lo; bank <= bank_hi; bank++) { for(unsigned addr = addr_lo; addr <= addr_hi; addr++) { unsigned destaddr = (bank << 16) | addr; - if(mode == MapMode::Linear) { - destaddr = mirror(base + offset, length); - offset = (offset + 1) % length; - } else if(mode == MapMode::Shadow) { - destaddr = mirror(base + destaddr, length); - } + if(mode == MapMode::Linear) destaddr = mirror(base + offset++, length); + if(mode == MapMode::Shadow) destaddr = mirror(base + destaddr, length); lookup[(bank << 16) | addr] = id; target[(bank << 16) | addr] = destaddr; } diff --git a/bsnes/snes/snes.hpp b/bsnes/snes/snes.hpp index f49a32b7..12363d59 100755 --- a/bsnes/snes/snes.hpp +++ b/bsnes/snes/snes.hpp @@ -1,13 +1,11 @@ namespace SNES { namespace Info { static const char Name[] = "bsnes"; - static const char Version[] = "076"; + static const char Version[] = "076.01"; static const unsigned SerializerVersion = 18; } } -//#define DEBUGGER - #include #include diff --git a/bsnes/ui/Makefile b/bsnes/ui/Makefile index d5f72ebd..1cb3891e 100755 --- a/bsnes/ui/Makefile +++ b/bsnes/ui/Makefile @@ -1,7 +1,7 @@ include $(snes)/Makefile include $(gameboy)/Makefile -ui_objects := ui-main ui-general ui-settings ui-tools ui-input ui-utility ui-cartridge ui-debugger +ui_objects := ui-main ui-general ui-settings ui-tools ui-input ui-utility ui-path ui-cartridge ui-debugger ui_objects += ruby phoenix ui_objects += $(if $(call streq,$(platform),win),resource) @@ -68,6 +68,7 @@ obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwild obj/ui-settings.o: $(ui)/settings/settings.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/settings/*) obj/ui-input.o: $(ui)/input/input.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/input/*) obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/utility/*) +obj/ui-path.o: $(ui)/path/path.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/path/*) obj/ui-cartridge.o: $(ui)/cartridge/cartridge.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/cartridge/*) obj/ui-debugger.o: $(ui)/debugger/debugger.cpp $(call rwildcard,$(ui)/*.hpp) $(call rwildcard,$(ui)/debugger/*) diff --git a/bsnes/ui/base.hpp b/bsnes/ui/base.hpp index a5d9745d..449c1cea 100755 --- a/bsnes/ui/base.hpp +++ b/bsnes/ui/base.hpp @@ -28,6 +28,7 @@ struct TopLevelWindow : Window { #include "tools/tools.hpp" #include "input/input.hpp" #include "utility/utility.hpp" +#include "path/path.hpp" #include "cartridge/cartridge.hpp" #if defined(DEBUGGER) diff --git a/bsnes/ui/config.cpp b/bsnes/ui/config.cpp index 72ada91e..9909f7e7 100755 --- a/bsnes/ui/config.cpp +++ b/bsnes/ui/config.cpp @@ -1,12 +1,11 @@ Configuration config; void Configuration::load() { - configuration::load(string(path.user, "bsnes.cfg")); + configuration::load(::path.home("bsnes.cfg")); } void Configuration::save() { - mkdir(path.user, 0755); - configuration::save(string(path.user, "bsnes.cfg")); + configuration::save(::path.home("bsnes.cfg")); } void Configuration::create() { diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index fd156d11..3a6c2a91 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -10,8 +10,8 @@ void Application::main(int argc, char **argv) { config.create(); inputMapper.create(); - config.path.base = realpath(argv[0]); - config.path.user = { userpath(), ".bsnes/" }; + config.path.base = dir(realpath(argv[0])); + config.path.user = userpath(); config.load(); config.save(); @@ -57,6 +57,7 @@ void Application::main(int argc, char **argv) { inputSettings.create(); advancedSettings.create(); cheatEditor.create(); + cheatDatabase.create(); stateManager.create(); #if defined(DEBUGGER) debugger.create(); @@ -158,19 +159,23 @@ int main(int argc, char **argv) { } void Application::loadGeometry() { - geometryConfig.load(string(config.path.user, "bsnes-geometry.cfg")); + geometryConfig.load(path.home("geometry.cfg")); foreach(window, windows) { lstring position; position.split(",", window->position); Geometry geom = window->geometry(); - window->setGeometry({ (signed)integer(position[0]), (signed)integer(position[1]), geom.width, geom.height }); + window->setGeometry({ + (signed)integer(position[0]), (signed)integer(position[1]), + geom.width, geom.height + //(unsigned)decimal(position[2]), (unsigned)decimal(position[3]) + }); } } void Application::saveGeometry() { foreach(window, windows) { Geometry geom = window->geometry(); - window->position = { geom.x, ",", geom.y }; + window->position = { geom.x, ",", geom.y, ",", geom.width, ",", geom.height }; } - geometryConfig.save(string(config.path.user, "bsnes-geometry.cfg")); + geometryConfig.save(path.home("geometry.cfg")); } diff --git a/bsnes/ui/path/path.cpp b/bsnes/ui/path/path.cpp new file mode 100755 index 00000000..d22caa53 --- /dev/null +++ b/bsnes/ui/path/path.cpp @@ -0,0 +1,20 @@ +#include "../base.hpp" +Path path; + +string Path::home(const string &filename) { + string path = { config.path.base, filename }; + if(file::exists(path)) return path; + + path = config.path.user; + #if defined(PLATFORM_X) || defined(PLATFORM_OSX) + path.append(".config/"); + mkdir(path, 0755); + path.append("bsnes/"); + mkdir(path, 0755); + #else + path.append("bsnes/"); + mkdir(path, 0755); + #endif + path.append(filename); + return path; +} diff --git a/bsnes/ui/path/path.hpp b/bsnes/ui/path/path.hpp new file mode 100755 index 00000000..721b3222 --- /dev/null +++ b/bsnes/ui/path/path.hpp @@ -0,0 +1,5 @@ +struct Path { + string home(const string &filename); +}; + +extern Path path; diff --git a/bsnes/ui/tools/cheat-database.cpp b/bsnes/ui/tools/cheat-database.cpp new file mode 100755 index 00000000..fc5d8b5d --- /dev/null +++ b/bsnes/ui/tools/cheat-database.cpp @@ -0,0 +1,93 @@ +CheatDatabase cheatDatabase; + +void CheatDatabase::create() { + application.addWindow(this, "CheatDatabase", "192,192"); + + listView.setCheckable(true); + selectAllButton.setText("Select All"); + unselectAllButton.setText("Unselect All"); + okButton.setText("Ok"); + + layout.setMargin(5); + layout.append(listView, 0, 0, 5); + controlLayout.append(selectAllButton, 100, 0, 5); + controlLayout.append(unselectAllButton, 100, 0); + controlLayout.append(spacerWidget, 0, 0); + controlLayout.append(okButton, 80, 0); + layout.append(controlLayout, 0, Style::ButtonHeight); + setGeometry({ 0, 0, 600, layout.minimumHeight() + 350 }); + append(layout); + + selectAllButton.onTick = [this]() { + foreach(item, this->listData, n) this->listView.setChecked(n, true); + }; + + unselectAllButton.onTick = [this]() { + foreach(item, this->listData, n) this->listView.setChecked(n, false); + }; + + okButton.onTick = { &CheatDatabase::addCodes, this }; +} + +void CheatDatabase::findCodes() { + string data; + data.readfile(path.home("cheats.xml")); + if(auto position = strpos(data, SNES::cartridge.sha256())) { + auto startPosition = strpos((const char*)data + position(), ">"); + auto endPosition = strpos((const char*)data + position(), ""); + string xmlData = { + "\n", + substr((const char*)data + position() + 1, startPosition(), endPosition() - startPosition() - 1), + "\n" + }; + + setTitle(""); + listView.reset(); + listData.reset(); + + xml_element document = xml_parse(xmlData); + foreach(root, document.element) { + if(root.name == "cartridge") foreach(node, root.element) { + if(node.name == "name") setTitle(node.parse()); + else if(node.name == "cheat") { + string description, code; + foreach(element, node.element) { + if(element.name == "description") description = element.parse(); + else if(element.name == "code") code.append(string(element.parse(), "+")); + } + code.rtrim<1>("+"); + code.append("\t"); + code.append(description); + listView.append(description); + listData.append(code); + } + } + } + + setVisible(true); + } else { + MessageWindow::information(cheatEditor, "Sorry, no cheat codes found for this cartridge."); + } +} + +void CheatDatabase::addCodes() { + foreach(code, listData, n) { + if(listView.checked(n)) { + if(auto position = cheatEditor.findUnusedSlot()) { + lstring part; + part.split("\t", code); + SNES::cheat[position()].enabled = false; + SNES::cheat[position()] = part[0]; + cheatEditor.cheatList.setChecked(position(), false); + cheatEditor.cheatText[position()][CheatEditor::CheatCode] = part[0]; + cheatEditor.cheatText[position()][CheatEditor::CheatDesc] = part[1]; + } else { + MessageWindow::warning(*this, "Ran out of empty slots for cheat codes.\nNot all cheat codes were added."); + break; + } + } + } + setVisible(false); + cheatEditor.refresh(); + cheatEditor.synchronize(); +} diff --git a/bsnes/ui/tools/cheat-database.hpp b/bsnes/ui/tools/cheat-database.hpp new file mode 100755 index 00000000..8e375dd5 --- /dev/null +++ b/bsnes/ui/tools/cheat-database.hpp @@ -0,0 +1,16 @@ +struct CheatDatabase : TopLevelWindow { + VerticalLayout layout; + ListView listView; + HorizontalLayout controlLayout; + Button selectAllButton; + Button unselectAllButton; + Widget spacerWidget; + Button okButton; + lstring listData; + + void create(); + void findCodes(); + void addCodes(); +}; + +extern CheatDatabase cheatDatabase; diff --git a/bsnes/ui/tools/cheat-editor.cpp b/bsnes/ui/tools/cheat-editor.cpp index b770cc71..9d969db5 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -100,7 +100,7 @@ void CheatEditor::create() { descLayout.append(descEdit, 0, 0); layout.append(descLayout, 0, Style::LineEditHeight, 5); controlLayout.append(findButton, 100, 0); - controlLayout.append(spacer, 0, 0); + controlLayout.append(spacerWidget, 0, 0); controlLayout.append(clearAllButton, 80, 0, 5); controlLayout.append(clearButton, 80, 0); layout.append(controlLayout, 0, Style::ButtonHeight); @@ -113,46 +113,13 @@ void CheatEditor::create() { cheatList.onChange = { &CheatEditor::synchronize, this }; cheatList.onTick = { &CheatEditor::toggle, this }; codeEdit.onChange = descEdit.onChange = { &CheatEditor::bind, this }; - findButton.onTick = { &CheatEditor::findCodes, this }; + findButton.onTick = { &CheatDatabase::findCodes, &cheatDatabase }; clearAllButton.onTick = { &CheatEditor::clearAll, this }; clearButton.onTick = { &CheatEditor::clear, this }; onClose = []() { - cheatEditor.databaseWindow.setVisible(false); + cheatDatabase.setVisible(false); }; - - //databaseWindow - application.addWindow(&databaseWindow, "CheatDatabase", "192,192"); - - databaseList.setCheckable(true); - databaseSelectAll.setText("Select All"); - databaseUnselectAll.setText("Unselect All"); - databaseOk.setText("Ok"); - - databaseLayout.setMargin(5); - databaseLayout.append(databaseList, 0, 0, 5); - databaseControlLayout.append(databaseSelectAll, 100, 0, 5); - databaseControlLayout.append(databaseUnselectAll, 100, 0); - databaseControlLayout.append(databaseSpacer, 0, 0); - databaseControlLayout.append(databaseOk, 80, 0); - databaseLayout.append(databaseControlLayout, 0, Style::ButtonHeight); - - databaseWindow.setGeometry({ 0, 0, 600, layout.minimumHeight() + 250 }); - databaseWindow.append(databaseLayout); - - databaseSelectAll.onTick = []() { - for(unsigned i = 0; i < cheatEditor.databaseCode.size(); i++) { - cheatEditor.databaseList.setChecked(i, true); - } - }; - - databaseUnselectAll.onTick = []() { - for(unsigned i = 0; i < cheatEditor.databaseCode.size(); i++) { - cheatEditor.databaseList.setChecked(i, false); - } - }; - - databaseOk.onTick = { &CheatEditor::addDatabaseCodes, this }; } void CheatEditor::synchronize() { @@ -201,48 +168,6 @@ void CheatEditor::bind() { refresh(); } -void CheatEditor::findCodes() { - string data; - data.readfile(string(config.path.user, "cheats.xml")); - if(data == "") data.readfile(string(config.path.base, "cheats.xml")); - if(auto position = strpos(data, SNES::cartridge.sha256())) { - auto startPosition = strpos((const char*)data + position(), ">"); - auto endPosition = strpos((const char*)data + position(), ""); - string xmlData = { - "\n", - substr((const char*)data + position() + 1, startPosition(), endPosition() - startPosition() - 1), - "\n" - }; - - databaseWindow.setTitle(""); - databaseList.reset(); - databaseCode.reset(); - - xml_element document = xml_parse(xmlData); - foreach(root, document.element) { - if(root.name == "cartridge") foreach(node, root.element) { - if(node.name == "name") databaseWindow.setTitle(node.parse()); - else if(node.name == "cheat") { - string description, code; - foreach(element, node.element) { - if(element.name == "description") description = element.parse(); - else if(element.name == "code") code.append(string(element.parse(), "+")); - } - code.rtrim<1>("+"); - code.append("\t"); - code.append(description); - databaseList.append(description); - databaseCode.append(code); - } - } - } - - databaseWindow.setVisible(true); - } else { - MessageWindow::information(cheatEditor, "Sorry, no cheat codes found for this cartridge."); - } -} - optional CheatEditor::findUnusedSlot() { for(unsigned i = 0; i < 128; i++) { if(cheatText[i][CheatCode] == "" && cheatText[i][CheatDesc] == "") return { true, i }; @@ -250,28 +175,6 @@ optional CheatEditor::findUnusedSlot() { return { false, 0 }; } -void CheatEditor::addDatabaseCodes() { - for(unsigned n = 0; n < databaseCode.size(); n++) { - if(databaseList.checked(n)) { - if(auto position = findUnusedSlot()) { - lstring part; - part.split("\t", databaseCode[n]); - SNES::cheat[position()].enabled = false; - SNES::cheat[position()] = part[0]; - cheatList.setChecked(position(), false); - cheatText[position()][CheatCode] = part[0]; - cheatText[position()][CheatDesc] = part[1]; - } else { - MessageWindow::warning(databaseWindow, "Ran out of empty slots for cheat codes.\nNot all cheat codes were added."); - break; - } - } - } - databaseWindow.setVisible(false); - refresh(); - synchronize(); -} - void CheatEditor::clearAll() { if(MessageWindow::question(cheatEditor, "Permanently erase all entered cheat codes?", MessageWindow::Buttons::YesNo) == MessageWindow::Response::Yes) { for(unsigned i = 0; i < 128; i++) { diff --git a/bsnes/ui/tools/cheat-editor.hpp b/bsnes/ui/tools/cheat-editor.hpp index e6088ac4..cc55076c 100755 --- a/bsnes/ui/tools/cheat-editor.hpp +++ b/bsnes/ui/tools/cheat-editor.hpp @@ -8,21 +8,11 @@ struct CheatEditor : TopLevelWindow { Label descLabel; LineEdit descEdit; HorizontalLayout controlLayout; - Label spacer; + Widget spacerWidget; Button findButton; Button clearAllButton; Button clearButton; - TopLevelWindow databaseWindow; - VerticalLayout databaseLayout; - ListView databaseList; - HorizontalLayout databaseControlLayout; - Button databaseSelectAll; - Button databaseUnselectAll; - Label databaseSpacer; - Button databaseOk; - lstring databaseCode; - void load(string filename); void save(string filename); void create(); @@ -34,11 +24,11 @@ private: void refresh(); void toggle(unsigned row); void bind(); - void findCodes(); optional findUnusedSlot(); - void addDatabaseCodes(); void clearAll(); void clear(); + + friend class CheatDatabase; }; extern CheatEditor cheatEditor; diff --git a/bsnes/ui/tools/tools.cpp b/bsnes/ui/tools/tools.cpp index 5ec3021d..2c1bec6f 100755 --- a/bsnes/ui/tools/tools.cpp +++ b/bsnes/ui/tools/tools.cpp @@ -1,3 +1,4 @@ #include "../base.hpp" #include "cheat-editor.cpp" +#include "cheat-database.cpp" #include "state-manager.cpp" diff --git a/bsnes/ui/tools/tools.hpp b/bsnes/ui/tools/tools.hpp index e7834f88..4b15a869 100755 --- a/bsnes/ui/tools/tools.hpp +++ b/bsnes/ui/tools/tools.hpp @@ -1,2 +1,3 @@ #include "cheat-editor.hpp" +#include "cheat-database.hpp" #include "state-manager.hpp"