diff --git a/GNUmakefile b/GNUmakefile index 55721904..8a9928b5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -12,8 +12,8 @@ target := tomoko # console := true # compiler -flags += -I. -O3 -link += +flags += -I. -O3 -fopenmp +link += -fopenmp objects := libco # profile-guided optimization mode @@ -39,15 +39,20 @@ ifeq ($(platform),windows) link += -mwindows endif link += -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32 - link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc + link += -Wl,-enable-auto-import + link += -Wl,-enable-runtime-pseudo-reloc else ifeq ($(platform),macosx) flags += -march=native else ifeq ($(platform),linux) flags += -march=native - link += -Wl,-export-dynamic -lX11 -lXext -ldl + link += -Wl,-export-dynamic + link += -lX11 -lXext -ldl else ifeq ($(platform),bsd) flags += -march=native - link += -Wl,-export-dynamic -lX11 -lXext + link += -Wl,-rpath=/usr/local/lib + link += -Wl,-rpath=/usr/local/lib/gcc49 + link += -Wl,-export-dynamic + link += -lX11 -lXext else $(error unsupported platform.) endif diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index 6c26489b..9f00f55c 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "094.17"; + static const char Version[] = "094.18"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/fc/cartridge/board/board.cpp b/fc/cartridge/board/board.cpp index 4f6afe02..b33ba360 100644 --- a/fc/cartridge/board/board.cpp +++ b/fc/cartridge/board/board.cpp @@ -94,10 +94,10 @@ Board::Board(Markup::Node& document) { auto crom = cartridge["chr/rom"]; auto cram = cartridge["chr/ram"]; - prgrom.size = prom["size"].text().numeral(); - prgram.size = pram["size"].text().numeral(); - chrrom.size = crom["size"].text().numeral(); - chrram.size = cram["size"].text().numeral(); + prgrom.size = prom["size"].decimal(); + prgram.size = pram["size"].decimal(); + chrrom.size = crom["size"].decimal(); + chrram.size = cram["size"].decimal(); if(prgrom.size) prgrom.data = new uint8[prgrom.size](); if(prgram.size) prgram.data = new uint8[prgram.size](); diff --git a/gb/cartridge/cartridge.cpp b/gb/cartridge/cartridge.cpp index b9f0af7a..2d5a1a82 100644 --- a/gb/cartridge/cartridge.cpp +++ b/gb/cartridge/cartridge.cpp @@ -74,9 +74,9 @@ void Cartridge::load(System::Revision revision) { //Super Game Boy core loads memory from Super Famicom core if(revision != System::Revision::SuperGameBoy) { - if(rom["name"]) interface->loadRequest(ID::ROM, rom["name"].text()); - if(ram["name"]) interface->loadRequest(ID::RAM, ram["name"].text()); - if(ram["name"]) memory.append({ID::RAM, ram["name"].text()}); + if(auto name = rom["name"].text()) interface->loadRequest(ID::ROM, name); + if(auto name = ram["name"].text()) interface->loadRequest(ID::RAM, name); + if(auto name = ram["name"].text()) memory.append({ID::RAM, name}); } information.romsize = rom["size"].decimal(); diff --git a/nall/compositor.hpp b/nall/compositor.hpp deleted file mode 100644 index fa83480e..00000000 --- a/nall/compositor.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef NALL_COMPOSITOR_HPP -#define NALL_COMPOSITOR_HPP - -#include - -namespace nall { - -struct compositor { - inline static bool enabled(); - inline static bool enable(bool status); - - #if defined(PLATFORM_XORG) - enum class Compositor : unsigned { Unknown, Metacity, Xfwm4 }; - inline static Compositor detect(); - - inline static bool enabled_metacity(); - inline static bool enable_metacity(bool status); - - inline static bool enabled_xfwm4(); - inline static bool enable_xfwm4(bool status); - #endif -}; - -#if defined(PLATFORM_XORG) - -//Metacity - -bool compositor::enabled_metacity() { - FILE* fp = popen("gconftool-2 --get /apps/metacity/general/compositing_manager", "r"); - if(!fp) return false; - - char buffer[512]; - if(!fgets(buffer, sizeof buffer, fp)) return false; - - if(!memcmp(buffer, "true", 4)) return true; - return false; -} - -bool compositor::enable_metacity(bool status) { - FILE* fp; - if(status) { - fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager true", "r"); - } else { - fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager false", "r"); - } - if(!fp) return false; - pclose(fp); - return true; -} - -//Xfwm4 - -bool compositor::enabled_xfwm4() { - FILE* fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r"); - if(!fp) return false; - - char buffer[512]; - if(!fgets(buffer, sizeof buffer, fp)) return false; - - if(!memcmp(buffer, "true", 4)) return true; - return false; -} - -bool compositor::enable_xfwm4(bool status) { - FILE* fp; - if(status) { - fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r"); - } else { - fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'", "r"); - } - if(!fp) return false; - pclose(fp); - return true; -} - -//General - -compositor::Compositor compositor::detect() { - Compositor result = Compositor::Unknown; - - FILE* fp; - char buffer[512]; - - fp = popen("pidof metacity", "r"); - if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Metacity; - pclose(fp); - - fp = popen("pidof xfwm4", "r"); - if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Xfwm4; - pclose(fp); - - return result; -} - -bool compositor::enabled() { - switch(detect()) { - case Compositor::Metacity: return enabled_metacity(); - case Compositor::Xfwm4: return enabled_xfwm4(); - default: return false; - } -} - -bool compositor::enable(bool status) { - switch(detect()) { - case Compositor::Metacity: return enable_metacity(status); - case Compositor::Xfwm4: return enable_xfwm4(status); - default: return false; - } -} - -#elif defined(PLATFORM_WINDOWS) - -bool compositor::enabled() { - HMODULE module = GetModuleHandleW(L"dwmapi"); - if(module == nullptr) module = LoadLibraryW(L"dwmapi"); - if(module == nullptr) return false; - - auto pDwmIsCompositionEnabled = (HRESULT (WINAPI*)(BOOL*))GetProcAddress(module, "DwmIsCompositionEnabled"); - if(pDwmIsCompositionEnabled == nullptr) return false; - - BOOL result; - if(pDwmIsCompositionEnabled(&result) != S_OK) return false; - return result; -} - -bool compositor::enable(bool status) { - HMODULE module = GetModuleHandleW(L"dwmapi"); - if(module == nullptr) module = LoadLibraryW(L"dwmapi"); - if(module == nullptr) return false; - - auto pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition"); - if(pDwmEnableComposition == nullptr) return false; - - if(pDwmEnableComposition(status) != S_OK) return false; - return true; -} - -#else - -bool compositor::enabled() { - return false; -} - -bool compositor::enable(bool) { - return false; -} - -#endif - -} - -#endif diff --git a/nall/database/sqlite3.hpp b/nall/database/sqlite3.hpp new file mode 100644 index 00000000..bd4b1791 --- /dev/null +++ b/nall/database/sqlite3.hpp @@ -0,0 +1,159 @@ +#ifndef NALL_DATABASE_SQLITE3_HPP +#define NALL_DATABASE_SQLITE3_HPP + +/* SQLite3 C++ RAII wrapper for nall + * + * Note on code below: it is safe (no-op) to call sqlite3_* functions on null sqlite3 objects + */ + +#include + +#include +#include + +namespace nall { namespace Database { + +struct SQLite3 { + struct Statement { + using type = Statement; + + Statement(sqlite3_stmt* stmt) : stmt(stmt) {} + Statement(const Statement& source) { operator=(source); } + Statement(Statement&& source) { operator=(move(source)); } + + auto operator=(const Statement& source) -> type& { stmt = source.stmt, stepped = source.stepped, response = source.response; return *this; } + auto operator=(Statement&& source) -> type& { operator=(source); source.stmt = nullptr, source.stepped = false, source.response = SQLITE_OK; return *this; } + explicit operator bool() { return !finished(); } + + auto bind(unsigned column, nullptr_t) -> type& { sqlite3_bind_null(stmt, 1 + column); return *this; } + auto bind(unsigned column, int32_t value) -> type& { sqlite3_bind_int(stmt, 1 + column, value); return *this; } + auto bind(unsigned column, uint32_t value) -> type& { sqlite3_bind_int(stmt, 1 + column, value); return *this; } + auto bind(unsigned column, int64_t value) -> type& { sqlite3_bind_int64(stmt, 1 + column, value); return *this; } + auto bind(unsigned column, uint64_t value) -> type& { sqlite3_bind_int64(stmt, 1 + column, value); return *this; } + auto bind(unsigned column, double value) -> type& { sqlite3_bind_double(stmt, 1 + column, value); return *this; } + auto bind(unsigned column, const string& value) -> type& { sqlite3_bind_text(stmt, 1 + column, value.data(), value.size(), SQLITE_TRANSIENT); return *this; } + auto bind(unsigned column, const vector& value) -> type& { sqlite3_bind_blob(stmt, 1 + column, value.data(), value.size(), SQLITE_TRANSIENT); return *this; } + + auto integer(unsigned column) -> int64_t { return sqlite3_column_int64(handle(), column); } + auto decimal(unsigned column) -> uint64_t { return sqlite3_column_int64(handle(), column); } + auto real(unsigned column) -> double { return sqlite3_column_double(handle(), column); } + + auto text(unsigned column) -> string { + string result; + if(auto text = sqlite3_column_text(handle(), column)) { + result.resize(sqlite3_column_bytes(handle(), column)); + memory::copy(result.pointer(), text, result.size()); + } + return result; + } + + auto data(unsigned column) -> vector { + vector result; + if(auto data = sqlite3_column_blob(handle(), column)) { + result.resize(sqlite3_column_bytes(handle(), column)); + memory::copy(result.data(), data, result.size()); + } + return result; + } + + auto integer() -> int64_t { return integer(column++); } + auto decimal() -> uint64_t { return decimal(column++); } + auto real() -> double { return real(column++); } + auto text() -> string { return text(column++); } + auto data() -> vector { return data(column++); } + + protected: + auto step() -> bool { stepped = true; response = sqlite3_step(stmt); return response == SQLITE_ROW; } + auto handle() -> sqlite3_stmt* { if(!stepped) step(); return stmt; } + auto finished() -> bool { handle(); return response != SQLITE_ROW; } + auto finalize() -> void { handle(); sqlite3_finalize(stmt); stmt = nullptr; } + + private: + sqlite3_stmt* stmt = nullptr; + bool stepped = false; + int response = SQLITE_OK; + unsigned column = 0; //this value is not copied/moved via operator= + }; + + struct Query : Statement { + Query(sqlite3_stmt* stmt) : Statement(stmt) {} + Query(const Query& source) : Statement(source) {} + Query(Query&& source) : Statement(move(source)) {} + ~Query() { finalize(); } + + auto operator=(const Query& source) -> Query& { return Statement::operator=(source), *this; } + auto operator=(Query&& source) -> Query& { return Statement::operator=(move(source)), *this; } + explicit operator bool() { return !finished(); } + + using Statement::step; + using Statement::finalize; + + struct Iterator { + auto operator*() -> Statement { return Statement(query); } + auto operator!=(const Iterator& source) const -> bool { return finished != source.finished; } + auto operator++() -> Iterator& { finished = !query.step(); return *this; } + Iterator(Query& query, bool finished) : query(query), finished(finished) {} + + protected: + Query& query; + bool finished = false; + }; + + auto begin() -> Iterator { return Iterator(*this, finished()); } + auto end() -> Iterator { return Iterator(*this, true); } + }; + + SQLite3() = default; + SQLite3(const string& filename) { open(filename); } + ~SQLite3() { close(); } + + explicit operator bool() const { return database; } + + auto open(const string& filename) -> bool { + close(); + sqlite3_open(filename, &database); + return database; + } + + auto close() -> void { + sqlite3_close(database); + database = nullptr; + } + + template auto execute(const string& statement, P&&... p) -> Query { + if(!database) return {nullptr}; + + sqlite3_stmt* stmt = nullptr; + sqlite3_prepare_v2(database, statement.data(), statement.size(), &stmt, nullptr); + if(!stmt) { + if(debug) print("[sqlite3_prepare_v2] ", sqlite3_errmsg(database), "\n"); + return {nullptr}; + } + + Query query{stmt}; + _bind(query, 0, forward

(p)...); + return query; + } + + auto lastInsertID() const -> uint64_t { + return database ? sqlite3_last_insert_rowid(database) : 0; + } + + auto setDebug(bool debug = true) -> void { + this->debug = debug; + } + +protected: + auto _bind(Query&, unsigned) -> void {} + template auto _bind(Query& query, unsigned column, const T& value, P&&... p) -> void { + query.bind(column, value); + _bind(query, column + 1, forward

(p)...); + } + + bool debug = false; + sqlite3* database = nullptr; +}; + +}} + +#endif diff --git a/nall/zip.hpp b/nall/encode/zip.hpp similarity index 97% rename from nall/zip.hpp rename to nall/encode/zip.hpp index a0f05e30..4ea19020 100644 --- a/nall/zip.hpp +++ b/nall/encode/zip.hpp @@ -6,10 +6,10 @@ #include #include -namespace nall { +namespace nall { namespace Encode { -struct zip { - zip(const string& filename) { +struct ZIP { + ZIP(const string& filename) { fp.open(filename, file::mode::write); time_t currentTime = time(nullptr); tm* info = localtime(¤tTime); @@ -40,7 +40,7 @@ struct zip { fp.write(data, size); //file data } - ~zip() { + ~ZIP() { //central directory unsigned baseOffset = fp.offset(); for(auto& entry : directory) { @@ -90,6 +90,6 @@ protected: vector directory; }; -} +}} #endif diff --git a/nall/nall.hpp b/nall/nall.hpp index a3b96922..861b55d6 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -21,7 +21,7 @@ #include #include #include -//#include +#include #include #include #include @@ -55,7 +55,6 @@ #include #include #include -#include #include #include #include diff --git a/nall/stdint.hpp b/nall/stdint.hpp index b6eed36f..abc0094d 100644 --- a/nall/stdint.hpp +++ b/nall/stdint.hpp @@ -27,6 +27,11 @@ #include #endif +#if defined(__SIZEOF_INT128__) + using int128_t = signed __int128; + using uint128_t = unsigned __int128; +#endif + namespace nall { static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); diff --git a/nall/string/base.hpp b/nall/string/base.hpp index 338ac3a3..98337f06 100644 --- a/nall/string/base.hpp +++ b/nall/string/base.hpp @@ -211,8 +211,6 @@ public: auto operator> (const char* s) const -> bool { return strcmp(data(), s) > 0; } auto operator>=(const char* s) const -> bool { return strcmp(data(), s) >= 0; } - auto operator+=(const string& s) -> type& { return append(s); } - string(const string& source) : string() { operator=(source); } string(string&& source) : string() { operator=(std::move(source)); } diff --git a/nall/string/markup/bml.hpp b/nall/string/markup/bml.hpp index 08d28973..3df074ed 100644 --- a/nall/string/markup/bml.hpp +++ b/nall/string/markup/bml.hpp @@ -14,26 +14,26 @@ using SharedNode = shared_pointer; struct ManagedNode : Markup::ManagedNode { protected: //test to verify if a valid character for a node name - bool valid(char p) const { //A-Z, a-z, 0-9, -. + auto valid(char p) const -> bool { //A-Z, a-z, 0-9, -. return p - 'A' < 26u || p - 'a' < 26u || p - '0' < 10u || p - '-' < 2u; } //determine indentation level, without incrementing pointer - unsigned readDepth(const char* p) { + auto readDepth(const char* p) -> unsigned { unsigned depth = 0; while(p[depth] == '\t' || p[depth] == ' ') depth++; return depth; } //determine indentation level - unsigned parseDepth(const char*& p) { + auto parseDepth(const char*& p) -> unsigned { unsigned depth = readDepth(p); p += depth; return depth; } //read name - void parseName(const char*& p) { + auto parseName(const char*& p) -> void { unsigned length = 0; while(valid(p[length])) length++; if(length == 0) throw "Invalid node name"; @@ -41,7 +41,7 @@ protected: p += length; } - void parseData(const char*& p) { + auto parseData(const char*& p) -> void { if(*p == '=' && *(p + 1) == '\"') { unsigned length = 2; while(p[length] && p[length] != '\n' && p[length] != '\"') length++; @@ -63,7 +63,7 @@ protected: } //read all attributes for a node - void parseAttributes(const char*& p) { + auto parseAttributes(const char*& p) -> void { while(*p && *p != '\n') { if(*p != ' ') throw "Invalid node name"; while(*p == ' ') p++; //skip excess spaces @@ -81,7 +81,7 @@ protected: } //read a node and all of its child nodes - void parseNode(const lstring& text, unsigned& y) { + auto parseNode(const lstring& text, unsigned& y) -> void { const char* p = text[y++]; _metadata = parseDepth(p); parseName(p); @@ -106,22 +106,32 @@ protected: } //read top-level nodes - void parse(const string& document) { - lstring text = string{document}.replace("\r", "").split("\n"); - - //remove empty lines and comment lines - for(unsigned y = 0; y < text.size();) { - unsigned x = 0; + auto parse(string document) -> void { + //in order to simplify the parsing logic; we do an initial pass to normalize the data + //the below code will turn '\r\n' into '\n'; skip empty lines; and skip comment lines + char* p = document.pointer(), *output = p; + while(*p) { + char* origin = p; bool empty = true; - while(x < text[y].size()) { - if(text[y][x] == ' ' || text[y][x] == '\t') { x++; continue; } - empty = (text[y][x + 0] == '/' && text[y][x + 1] == '/'); + while(*p) { + //scan for first non-whitespace character. if it's a line feed or comment; skip the line + if(p[0] == ' ' || p[0] == '\t') { p++; continue; } + empty = p[0] == '\r' || p[0] == '\n' || (p[0] == '/' && p[1] == '/'); break; } - if(empty) text.remove(y); - else y++; - } + while(*p) { + if(p[0] == '\r') p[0] = '\n'; //turns '\r\n' into '\n\n' (second '\n' will be skipped) + if(*p++ == '\n') break; //include '\n' in the output to be copied + } + if(empty) continue; + memory::move(output, origin, p - origin); + output += p - origin; + } + document.resize(document.size() - (p - output)).rtrim("\n"); + if(document.size() == 0) return; //empty document + + auto text = document.split("\n"); unsigned y = 0; while(y < text.size()) { SharedNode node(new ManagedNode); diff --git a/nall/string/platform.hpp b/nall/string/platform.hpp index c438bbfd..b0ffa9d8 100644 --- a/nall/string/platform.hpp +++ b/nall/string/platform.hpp @@ -75,7 +75,7 @@ auto configpath() -> string { // c:/users/username/appdata/local/ auto localpath() -> string { #if defined(PLATFORM_WINDOWS) - whcar_t path[PATH_MAX] = L""; + wchar_t path[PATH_MAX] = L""; SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); string result = (const char*)utf8_t(path); result.transform("\\", "/"); diff --git a/sfc/cartridge/cartridge.cpp b/sfc/cartridge/cartridge.cpp index 074f9fa9..f427233a 100644 --- a/sfc/cartridge/cartridge.cpp +++ b/sfc/cartridge/cartridge.cpp @@ -124,9 +124,9 @@ void Cartridge::load_super_game_boy() { GameBoy::cartridge.information.markup = information.markup.gameBoy; GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy); - if(rom["name"]) interface->loadRequest(ID::SuperGameBoyROM, rom["name"].text()); - if(ram["name"]) interface->loadRequest(ID::SuperGameBoyRAM, ram["name"].text()); - if(ram["name"]) memory.append({ID::SuperGameBoyRAM, ram["name"].text()}); + if(auto name = rom["name"].text()) interface->loadRequest(ID::SuperGameBoyROM, name); + if(auto name = ram["name"].text()) interface->loadRequest(ID::SuperGameBoyRAM, name); + if(auto name = ram["name"].text()) memory.append({ID::SuperGameBoyRAM, name}); } void Cartridge::load_satellaview() { diff --git a/sfc/cartridge/markup.cpp b/sfc/cartridge/markup.cpp index cd621416..ff83fea7 100644 --- a/sfc/cartridge/markup.cpp +++ b/sfc/cartridge/markup.cpp @@ -147,7 +147,7 @@ void Cartridge::parse_markup_sufamiturbo(Markup::Node root, bool slot) { } for(auto node : root.find("map")) { - SufamiTurboCartridge &cart = (slot == 0 ? sufamiturboA : sufamiturboB); + SufamiTurboCartridge& cart = (slot == 0 ? sufamiturboA : sufamiturboB); if(node["id"].text() == "rom") { if(cart.rom.size() == 0) continue; @@ -234,9 +234,12 @@ void Cartridge::parse_markup_sa1(Markup::Node root) { if(!root) return; has_sa1 = true; - parse_markup_memory(sa1.rom, root["rom"], ID::SA1ROM, false); - parse_markup_memory(sa1.bwram, root["ram"].at(0), ID::SA1BWRAM, true); - parse_markup_memory(sa1.iram, root["ram"].at(1), ID::SA1IRAM, true); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + parse_markup_memory(sa1.rom, rom(0), ID::SA1ROM, false); + parse_markup_memory(sa1.bwram, ram(0), ID::SA1BWRAM, true); + parse_markup_memory(sa1.iram, ram(1), ID::SA1IRAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { @@ -270,8 +273,11 @@ void Cartridge::parse_markup_superfx(Markup::Node root) { if(!root) return; has_superfx = true; - parse_markup_memory(superfx.rom, root["rom"], ID::SuperFXROM, false); - parse_markup_memory(superfx.ram, root["ram"], ID::SuperFXRAM, true); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + parse_markup_memory(superfx.rom, rom(0), ID::SuperFXROM, false); + parse_markup_memory(superfx.ram, ram(0), ID::SuperFXRAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { @@ -300,9 +306,12 @@ void Cartridge::parse_markup_armdsp(Markup::Node root) { if(!root) return; has_armdsp = true; - string programROMName = root["rom"].at(0)["name"].text(); - string dataROMName = root["rom"].at(1)["name"].text(); - string dataRAMName = root["ram/name"].text(); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + string programROMName = rom(0)["name"].text(); + string dataROMName = rom(1)["name"].text(); + string dataRAMName = ram(0)["name"].text(); interface->loadRequest(ID::ArmDSPPROM, programROMName); interface->loadRequest(ID::ArmDSPDROM, dataROMName); @@ -324,8 +333,11 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) { if(!root) return; has_hitachidsp = true; - parse_markup_memory(hitachidsp.rom, root["rom"].at(0), ID::HitachiDSPROM, false); - parse_markup_memory(hitachidsp.ram, root["ram"].at(1), ID::HitachiDSPRAM, true); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + parse_markup_memory(hitachidsp.rom, rom(0), ID::HitachiDSPROM, false); + parse_markup_memory(hitachidsp.ram, ram(0), ID::HitachiDSPRAM, true); for(auto& word : hitachidsp.dataROM) word = 0x000000; for(auto& word : hitachidsp.dataRAM) word = 0x00; @@ -334,8 +346,8 @@ void Cartridge::parse_markup_hitachidsp(Markup::Node root, unsigned roms) { if(hitachidsp.Frequency == 0) hitachidsp.frequency = 20000000; hitachidsp.Roms = roms; - string dataROMName = root["rom"].at(1)["name"].text(); - string dataRAMName = root["ram"].at(1)["name"].text(); + string dataROMName = rom(1)["name"].text(); + string dataRAMName = ram(1)["name"].text(); interface->loadRequest(ID::HitachiDSPDROM, dataROMName); if(dataRAMName.empty() == false) { @@ -380,9 +392,12 @@ void Cartridge::parse_markup_necdsp(Markup::Node root) { : root["model"].text() == "uPD96050" ? NECDSP::Revision::uPD96050 : NECDSP::Revision::uPD7725; - string programROMName = root["rom"].at(0)["name"].text(); - string dataROMName = root["rom"].at(1)["name"].text(); - string dataRAMName = root["ram/name"].text(); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + string programROMName = rom(0)["name"].text(); + string dataROMName = rom(1)["name"].text(); + string dataRAMName = ram(0)["name"].text(); if(necdsp.revision == NECDSP::Revision::uPD7725) { interface->loadRequest(ID::Nec7725DSPPROM, programROMName); @@ -456,9 +471,12 @@ void Cartridge::parse_markup_spc7110(Markup::Node root) { if(!root) return; has_spc7110 = true; - parse_markup_memory(spc7110.prom, root["rom"].at(0), ID::SPC7110PROM, false); - parse_markup_memory(spc7110.drom, root["rom"].at(1), ID::SPC7110DROM, false); - parse_markup_memory(spc7110.ram, root["ram"], ID::SPC7110RAM, true); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + parse_markup_memory(spc7110.prom, rom(0), ID::SPC7110PROM, false); + parse_markup_memory(spc7110.drom, rom(1), ID::SPC7110DROM, false); + parse_markup_memory(spc7110.ram, ram(0), ID::SPC7110RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") { @@ -485,8 +503,11 @@ void Cartridge::parse_markup_sdd1(Markup::Node root) { if(!root) return; has_sdd1 = true; - parse_markup_memory(sdd1.rom, root["rom"], ID::SDD1ROM, false); - parse_markup_memory(sdd1.ram, root["ram"], ID::SDD1RAM, true); + auto rom = root.find("rom"); + auto ram = root.find("ram"); + + parse_markup_memory(sdd1.rom, rom(0), ID::SDD1ROM, false); + parse_markup_memory(sdd1.ram, ram(0), ID::SDD1RAM, true); for(auto node : root.find("map")) { if(node["id"].text() == "io") {