diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index 053662e8..385db7d7 100755 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -3,7 +3,7 @@ namespace Emulator { static const char Name[] = "higan"; - static const char Version[] = "092.06"; + static const char Version[] = "092.07"; static const char Author[] = "byuu"; static const char License[] = "GPLv3"; static const char Website[] = "http://byuu.org/"; diff --git a/higan/nall/config.hpp b/higan/nall/config.hpp index 94be7dc1..dc579181 100755 --- a/higan/nall/config.hpp +++ b/higan/nall/config.hpp @@ -1,126 +1,103 @@ #ifndef NALL_CONFIG_HPP #define NALL_CONFIG_HPP +#include #include #include -#include namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; +namespace Configuration { - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; +struct Node { + string name; + string desc; + enum class Type : unsigned { Null, Bool, Signed, Unsigned, Double, String } type = Type::Null; + void* data = nullptr; + vector children; - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; + bool empty() const { + return data == nullptr; } - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - inline string get() const { - switch(type) { - case boolean_t: return { *(bool*)data }; - case signed_t: return { *(signed*)data }; - case unsigned_t: return { *(unsigned*)data }; - case double_t: return { *(double*)data }; - case string_t: return { "\"", *(string*)data, "\"" }; - } - return "???"; - } - - inline void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = integer(s); break; - case unsigned_t: *(unsigned*)data = decimal(s); break; - case double_t: *(double*)data = fp(s); break; - case string_t: s.trim("\""); *(string*)data = s; break; - } - } - }; - vector list; - - template - inline void append(T &data, const char *name, const char *desc = "") { - item_t item = { (uintptr_t)&data, name, desc }; - if(configuration_traits::is_boolean::value) item.type = boolean_t; - else if(configuration_traits::is_signed::value) item.type = signed_t; - else if(configuration_traits::is_unsigned::value) item.type = unsigned_t; - else if(configuration_traits::is_double::value) item.type = double_t; - else if(configuration_traits::is_string::value) item.type = string_t; - else item.type = unknown_t; - list.append(item); + string get() const { + switch(type) { + case Type::Bool: return {*(bool*)data}; + case Type::Signed: return {*(signed*)data}; + case Type::Unsigned: return {*(unsigned*)data}; + case Type::Double: return {*(double*)data}; + case Type::String: return {*(string*)data}; } + return ""; + } - //deprecated - template - inline void attach(T &data, const char *name, const char *desc = "") { - append(data, name, desc); + void set(const string& value) { + switch(type) { + case Type::Bool: *(bool*)data = (value == "true"); break; + case Type::Signed: *(signed*)data = integer(value); break; + case Type::Unsigned: *(unsigned*)data = decimal(value); break; + case Type::Double: *(double*)data = fp(value); break; + case Type::String: *(string*)data = value; break; } + } - inline virtual bool load(const string &filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); + void assign() { type = Type::Null; data = nullptr; } + void assign(bool& bind) { type = Type::Bool; data = (void*)&bind; } + void assign(signed& bind) { type = Type::Signed; data = (void*)&bind; } + void assign(unsigned& bind) { type = Type::Unsigned; data = (void*)&bind; } + void assign(double& bind) { type = Type::Double; data = (void*)&bind; } + void assign(string& bind) { type = Type::String; data = (void*)&bind; } + void assign(const Node& node) { operator=(node); } - for(unsigned i = 0; i < line.size(); i++) { - if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0; - if(!qstrpos(line[i], " = ")) continue; + template void append(T& data, const string& name, const string& desc = "") { + Node node; + node.assign(data); + node.name = name; + node.desc = desc; + children.append(node); + } - lstring part; - part.qsplit(" = ", line[i]); - part[0].trim(); - part[1].trim(); + void load(Markup::Node path) { + for(auto& child : children) { + auto leaf = path[child.name]; + if(!leaf.exists()) continue; + if(!child.empty()) child.set(leaf.data.trim<1>(" ", "\r")); + child.load(leaf); + } + } - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; + void save(file& fp, unsigned depth = 0) { + for(auto& child : children) { + if(child.desc) { + for(unsigned n = 0; n < depth; n++) fp.print(" "); + fp.print("//", child.desc, "\n"); } + for(unsigned n = 0; n < depth; n++) fp.print(" "); + fp.print(child.name); + if(!child.empty()) fp.print(": ", child.get()); + fp.print("\n"); + child.save(fp, depth + 1); + if(depth == 0) fp.print("\n"); } + } +}; - inline virtual bool save(const string &filename) const { - file fp; - if(fp.open(filename, file::mode::write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output.append(list[i].name, " = ", list[i].get()); - if(list[i].desc != "") output.append(" # ", list[i].desc); - output.append("\r\n"); - fp.print(output); - } +struct Document : Node { + bool load(const string& filename) { + if(!file::exists(filename)) return false; + auto document = Markup::Document(string::read(filename)); + Node::load(document); + return true; + } - fp.close(); - return true; - } else { - return false; - } - } - }; + bool save(const string& filename) { + file fp(filename, file::mode::write); + if(!fp.open()) return false; + Node::save(fp); + return true; + } +}; + +} } #endif diff --git a/higan/nall/set.hpp b/higan/nall/group.hpp old mode 100755 new mode 100644 similarity index 65% rename from higan/nall/set.hpp rename to higan/nall/group.hpp index c6d3d06e..dd49231b --- a/higan/nall/set.hpp +++ b/higan/nall/group.hpp @@ -1,46 +1,25 @@ -#ifndef NALL_SET_HPP -#define NALL_SET_HPP +#ifndef NALL_GROUP_HPP +#define NALL_GROUP_HPP -//set -//* unordered -//* intended for unique items -//* dynamic growth -//* reference-based variant +//group: a vector of unique references #include #include #include #include -#include #include -#include #include -#include namespace nall { -template struct set; - -template struct set::value>::type> { +template struct group { struct exception_out_of_bounds{}; - -protected: - T *pool; - unsigned poolsize, objectsize; - -public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } -}; - -//reference set -template struct set::value>::type> { - struct exception_out_of_bounds{}; - -protected: typedef typename std::remove_reference::type T; - T **pool; - unsigned poolsize, objectsize; + +protected: + T** pool = nullptr; + unsigned poolsize = 0; + unsigned objectsize = 0; public: unsigned size() const { return objectsize; } @@ -94,27 +73,26 @@ public: return {false, 0u}; } - template set(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) { + template group(Args&&... args) { construct(std::forward(args)...); } - ~set() { + ~group() { reset(); } - set& operator=(const set &source) { + group& operator=(const group& source) { if(&source == this) return *this; - if(pool) free(pool); - objectsize = source.objectsize; - poolsize = source.poolsize; - pool = (T**)malloc(sizeof(T*) * poolsize); + reset(); + reserve(source.poolsize); + resize(source.objectsize); memcpy(pool, source.pool, sizeof(T*) * objectsize); return *this; } - set& operator=(const set &&source) { + group& operator=(const group&& source) { if(&source == this) return *this; - if(pool) free(pool); + reset(); pool = source.pool; poolsize = source.poolsize; objectsize = source.objectsize; @@ -129,12 +107,12 @@ public: } struct iterator { - bool operator!=(const iterator &source) const { return position != source.position; } + bool operator!=(const iterator& source) const { return position != source.position; } T& operator*() { return source.operator[](position); } iterator& operator++() { position++; return *this; } - iterator(const set &source, unsigned position) : source(source), position(position) {} + iterator(const group& source, unsigned position) : source(source), position(position) {} private: - const set &source; + const group& source; unsigned position; }; @@ -145,8 +123,8 @@ public: private: void construct() {} - void construct(const set &source) { operator=(source); } - void construct(const set &&source) { operator=(std::move(source)); } + void construct(const group& source) { operator=(source); } + void construct(const group&& source) { operator=(std::move(source)); } template void construct(T& data, Args&&... args) { append(data); construct(std::forward(args)...); diff --git a/higan/nall/lzss.hpp b/higan/nall/lzss.hpp deleted file mode 100755 index d595f911..00000000 --- a/higan/nall/lzss.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include -#include - -namespace nall { - -//19:5 pulldown -//8:1 marker: d7-d0 -//length: { 4 - 35 }, offset: { 1 - 0x80000 } -//4-byte file size header -//little-endian encoding -struct lzss { - inline void source(const uint8_t *data, unsigned size); - inline bool source(const string &filename); - inline unsigned size() const; - inline bool compress(const string &filename); - inline bool decompress(uint8_t *targetData, unsigned targetSize); - inline bool decompress(const string &filename); - -protected: - struct Node { - unsigned offset; - Node *next; - inline Node() : offset(0), next(nullptr) {} - inline ~Node() { if(next) delete next; } - } *tree[65536]; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - -public: - inline lzss() : sourceData(nullptr), sourceSize(0) {} -}; - -void lzss::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -bool lzss::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - sourceData = sourceFile.data(); - sourceSize = sourceFile.size(); - return true; -} - -unsigned lzss::size() const { - unsigned size = 0; - if(sourceSize < 4) return size; - for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n; - return size; -} - -bool lzss::compress(const string &filename) { - file targetFile; - if(targetFile.open(filename, file::mode::write) == false) return false; - - for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n); - for(unsigned n = 0; n < 65536; n++) tree[n] = nullptr; - - uint8_t buffer[25]; - unsigned sourceOffset = 0; - - while(sourceOffset < sourceSize) { - uint8_t mask = 0x00; - unsigned bufferOffset = 1; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - uint16_t symbol = sourceData[sourceOffset + 0]; - if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8; - Node *node = tree[symbol]; - unsigned maxLength = 0, maxOffset = 0; - - while(node) { - if(node->offset < sourceOffset - 0x80000) { - //out-of-range: all subsequent nodes will also be, so free up their memory - if(node->next) { delete node->next; node->next = nullptr; } - break; - } - - unsigned length = 0, x = sourceOffset, y = node->offset; - while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset; - if(length == 35) break; - - node = node->next; - } - - //attach current symbol to top of tree for subsequent searches - node = new Node; - node->offset = sourceOffset; - node->next = tree[symbol]; - tree[symbol] = node; - - if(maxLength < 4) { - buffer[bufferOffset++] = sourceData[sourceOffset++]; - } else { - unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset); - for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n; - mask |= 0x80 >> iteration; - sourceOffset += maxLength; - } - } - - buffer[0] = mask; - targetFile.write(buffer, bufferOffset); - } - - sourceFile.close(); - targetFile.close(); - return true; -} - -bool lzss::decompress(uint8_t *targetData, unsigned targetSize) { - if(targetSize < size()) return false; - - unsigned sourceOffset = 4, targetOffset = 0; - while(sourceOffset < sourceSize) { - uint8_t mask = sourceData[sourceOffset++]; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - if((mask & (0x80 >> iteration)) == 0) { - targetData[targetOffset++] = sourceData[sourceOffset++]; - } else { - unsigned code = 0; - for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n; - unsigned length = (code >> 19) + 4; - unsigned offset = targetOffset - 1 - (code & 0x7ffff); - while(length--) targetData[targetOffset++] = targetData[offset++]; - } - } - } -} - -bool lzss::decompress(const string &filename) { - if(sourceSize < 4) return false; - unsigned targetSize = size(); - - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - fp.truncate(targetSize); - fp.close(); - - filemap targetFile; - if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; - uint8_t *targetData = targetFile.data(); - - bool result = decompress(targetData, targetSize); - sourceFile.close(); - targetFile.close(); - return result; -} - -} - -#endif diff --git a/higan/nall/nall.hpp b/higan/nall/nall.hpp index e24212d3..563d0d49 100755 --- a/higan/nall/nall.hpp +++ b/higan/nall/nall.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #include #include -#include #include #include #include diff --git a/higan/nall/string/base.hpp b/higan/nall/string/base.hpp index a5e405fc..2ce49540 100755 --- a/higan/nall/string/base.hpp +++ b/higan/nall/string/base.hpp @@ -29,6 +29,7 @@ namespace nall { inline static string time(); inline static string datetime(); + inline void reset(); inline void reserve(unsigned); inline void resize(unsigned); inline void clear(char); diff --git a/higan/nall/string/core.hpp b/higan/nall/string/core.hpp index 043c575b..e6a2dd1a 100755 --- a/higan/nall/string/core.hpp +++ b/higan/nall/string/core.hpp @@ -11,6 +11,11 @@ static void istring(string &output, const T &value, Args&&... args) { istring(output, std::forward(args)...); } +void string::reset() { + resize(64); + *data = 0; +} + void string::reserve(unsigned size_) { if(size_ > size) resize(size_); } diff --git a/higan/nall/string/markup/bml.hpp b/higan/nall/string/markup/bml.hpp index 26bf6685..f6174103 100644 --- a/higan/nall/string/markup/bml.hpp +++ b/higan/nall/string/markup/bml.hpp @@ -1,7 +1,7 @@ #ifdef NALL_STRING_INTERNAL_HPP //BML v1.0 parser -//revision 0.02 +//revision 0.03 namespace nall { namespace BML { @@ -9,8 +9,8 @@ namespace BML { struct Node : Markup::Node { protected: //test to verify if a valid character for a node name - bool valid(char p) const { //A-Z, a-z, 0-9, -./ - return p - 'A' < 26u || p - 'a' < 26u || p - '0' < 10u || p - '-' < 3u; + bool valid(char p) const { //A-Z, a-z, 0-9, -. + return p - 'A' < 26u || p - 'a' < 26u || p - '0' < 10u || p - '-' < 2u; } //determine indentation level, without incrementing pointer @@ -41,13 +41,13 @@ protected: unsigned length = 2; while(p[length] && p[length] != '\n' && p[length] != '\"') length++; if(p[length] != '\"') throw "Unescaped value"; - data = substr(p, 2, length - 2); + data = {substr(p, 2, length - 2), "\n"}; p += length + 1; } else if(*p == '=') { unsigned length = 1; while(p[length] && p[length] != '\n' && p[length] != '\"' && p[length] != ' ') length++; if(p[length] == '\"') throw "Illegal character in value"; - data = substr(p, 1, length - 1); + data = {substr(p, 1, length - 1), "\n"}; p += length; } else if(*p == ':') { unsigned length = 1; @@ -62,6 +62,7 @@ protected: while(*p && *p != '\n') { if(*p != ' ') throw "Invalid node name"; while(*p == ' ') p++; //skip excess spaces + if(*(p + 0) == '/' && *(p + 1) == '/') break; //skip comments Node node; node.attribute = true; @@ -70,35 +71,30 @@ protected: if(length == 0) throw "Invalid attribute name"; node.name = substr(p, 0, length); node.parseData(p += length); + node.data.rtrim<1>("\n"); children.append(node); } } - //read a node and all of its children nodes - void parseNode(const char *&p) { + //read a node and all of its child nodes + void parseNode(const lstring &text, unsigned &y) { + const char *p = text[y++]; level = parseDepth(p); parseName(p); parseData(p); parseAttributes(p); - if(*p && *p++ != '\n') throw "Missing line feed"; - while(*p) { - if(*p == '\n') { p++; continue; } - - unsigned depth = readDepth(p); + while(y < text.size()) { + unsigned depth = readDepth(text[y]); if(depth <= level) break; - if(p[depth] == ':') { - p += depth; - unsigned length = 0; - while(p[length] && p[length] != '\n') length++; - data.append(substr(p, 1, length - 1), "\n"); - p += length; + if(text[y][depth] == ':') { + data.append(substr(text[y++], depth + 1), "\n"); continue; } Node node; - node.parseNode(p); + node.parseNode(text, y); children.append(node); } @@ -106,10 +102,27 @@ protected: } //read top-level nodes - void parse(const char *p) { - while(*p) { + void parse(const string &document) { + lstring text = document.split("\n"); + + //remove empty lines and comment lines + for(unsigned y = 0; y < text.size();) { + text[y].rtrim<1>("\n"); + unsigned x = 0; + bool empty = true; + while(text[y][x]) { + if(text[y][x] == ' ' || text[y][x] == '\t') { x++; continue; } + empty = (text[y][x + 0] == '/' && text[y][x + 1] == '/'); + break; + } + if(empty) text.remove(y); + else y++; + } + + unsigned y = 0; + while(y < text.size()) { Node node; - node.parseNode(p); + node.parseNode(text, y); if(node.level > 0) throw "Root nodes cannot be indented"; children.append(node); } @@ -121,15 +134,13 @@ protected: struct Document : Node { string error; - bool load(string document) { - name = "{root}", data = ""; + bool load(const string &document) { + name = "", data = ""; try { - document.replace("\r", ""); - while(document.position("\n\n")) document.replace("\n\n", "\n"); parse(document); - } catch(const char *perror) { - error = perror; + } catch(const char *error) { + this->error = error; children.reset(); return false; } diff --git a/higan/nall/string/platform.hpp b/higan/nall/string/platform.hpp index 406de0bb..098bc0f9 100755 --- a/higan/nall/string/platform.hpp +++ b/higan/nall/string/platform.hpp @@ -80,7 +80,7 @@ string sharedpath() { #elif defined(PLATFORM_OSX) result = "/Library/Application Support/"; #else - result = "/etc/"; + result = "/usr/share/"; #endif if(result.empty()) result = "."; if(result.endswith("/") == false) result.append("/"); diff --git a/higan/nall/windows/registry.hpp b/higan/nall/windows/registry.hpp index cb035e19..fee79c3a 100755 --- a/higan/nall/windows/registry.hpp +++ b/higan/nall/windows/registry.hpp @@ -5,6 +5,7 @@ #include #include +#undef interface #ifndef KEY_WOW64_64KEY #define KEY_WOW64_64KEY 0x0100 #endif diff --git a/higan/nall/xorg/guard.hpp b/higan/nall/xorg/guard.hpp index a1282683..9b528866 100755 --- a/higan/nall/xorg/guard.hpp +++ b/higan/nall/xorg/guard.hpp @@ -4,6 +4,7 @@ #define None #undef XlibNone #define XlibNone 0L +#define Bool XlibBool #define Button1 XlibButton1 #define Button2 XlibButton2 #define Button3 XlibButton3 @@ -17,6 +18,7 @@ #undef NALL_XORG_GUARD_HPP #undef None +#undef Bool #undef Button1 #undef Button2 #undef Button3 diff --git a/higan/phoenix/cocoa/action/radio-item.cpp b/higan/phoenix/cocoa/action/radio-item.cpp index 7e10f949..7686fc55 100644 --- a/higan/phoenix/cocoa/action/radio-item.cpp +++ b/higan/phoenix/cocoa/action/radio-item.cpp @@ -34,7 +34,7 @@ void pRadioItem::setChecked() { } } -void pRadioItem::setGroup(const set &group) { +void pRadioItem::setGroup(const group &group) { } void pRadioItem::setText(const string &text) { diff --git a/higan/phoenix/cocoa/action/radio-item.hpp b/higan/phoenix/cocoa/action/radio-item.hpp index 4fe52f3b..64924a6d 100644 --- a/higan/phoenix/cocoa/action/radio-item.hpp +++ b/higan/phoenix/cocoa/action/radio-item.hpp @@ -14,7 +14,7 @@ struct pRadioItem : public pAction { bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {} diff --git a/higan/phoenix/cocoa/widget/radio-button.cpp b/higan/phoenix/cocoa/widget/radio-button.cpp index cad99ba9..c8fabdde 100644 --- a/higan/phoenix/cocoa/widget/radio-button.cpp +++ b/higan/phoenix/cocoa/widget/radio-button.cpp @@ -47,7 +47,7 @@ void pRadioButton::setGeometry(const Geometry &geometry) { }); } -void pRadioButton::setGroup(const set &group) { +void pRadioButton::setGroup(const group &group) { } void pRadioButton::setText(const string &text) { diff --git a/higan/phoenix/cocoa/widget/radio-button.hpp b/higan/phoenix/cocoa/widget/radio-button.hpp index 6f58ab72..aeafe4f4 100644 --- a/higan/phoenix/cocoa/widget/radio-button.hpp +++ b/higan/phoenix/cocoa/widget/radio-button.hpp @@ -16,7 +16,7 @@ struct pRadioButton : public pWidget { Size minimumSize(); void setChecked(); void setGeometry(const Geometry &geometry); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioButton(RadioButton &radioButton) : pWidget(radioButton), radioButton(radioButton) {} diff --git a/higan/phoenix/core/core.cpp b/higan/phoenix/core/core.cpp index 9c542fd4..4bc275af 100755 --- a/higan/phoenix/core/core.cpp +++ b/higan/phoenix/core/core.cpp @@ -525,7 +525,7 @@ Action::~Action() { //Menu //==== -void Menu::append(const set &list) { +void Menu::append(const group &list) { for(auto &action : list) { if(state.action.append(action)) { action.state.menu = this; @@ -534,7 +534,7 @@ void Menu::append(const set &list) { } } -void Menu::remove(const set &list) { +void Menu::remove(const group &list) { for(auto &action : list) { if(state.action.remove(action)) { action.state.menu = nullptr; @@ -639,7 +639,7 @@ CheckItem::~CheckItem() { //RadioItem //========= -void RadioItem::group(const set &list) { +void RadioItem::group(const nall::group &list) { for(auto &item : list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } @@ -1261,7 +1261,7 @@ ProgressBar::~ProgressBar() { //RadioButton //=========== -void RadioButton::group(const set &list) { +void RadioButton::group(const nall::group &list) { for(auto &item : list) item.p.setGroup(item.state.group = list); if(list.size()) list[0].setChecked(); } diff --git a/higan/phoenix/core/core.hpp b/higan/phoenix/core/core.hpp index 018d7295..c6456b9e 100755 --- a/higan/phoenix/core/core.hpp +++ b/higan/phoenix/core/core.hpp @@ -1,9 +1,10 @@ #include #include +#include #include +#include #include #include -#include #include #include #include @@ -279,8 +280,8 @@ struct Menu : private nall::base_from_member, Action { template void append(Args&... args) { append({args...}); } template void remove(Args&... args) { remove({args...}); } - void append(const nall::set &list); - void remove(const nall::set &list); + void append(const nall::group &list); + void remove(const nall::group &list); void setImage(const nall::image &image = nall::image{}); void setText(const nall::string &text); @@ -326,7 +327,7 @@ struct CheckItem : private nall::base_from_member, Action { struct RadioItem : private nall::base_from_member, Action { template static void group(Args&... args) { group({args...}); } - static void group(const nall::set &list); + static void group(const nall::group &list); nall::function onActivate; @@ -577,7 +578,7 @@ struct ProgressBar : private nall::base_from_member, Widget { struct RadioButton : private nall::base_from_member, Widget { template static void group(Args&... args) { group({args...}); } - static void group(const nall::set &list); + static void group(const nall::group &list); nall::function onActivate; diff --git a/higan/phoenix/core/state.hpp b/higan/phoenix/core/state.hpp index 35d70da3..87140074 100755 --- a/higan/phoenix/core/state.hpp +++ b/higan/phoenix/core/state.hpp @@ -27,8 +27,8 @@ struct Window::State { Color backgroundColor = {0, 0, 0, 255}; bool fullScreen = false; Geometry geometry = {128, 128, 256, 256}; - set layout; - set menu; + group layout; + group menu; string menuFont; bool menuVisible = false; bool modal = false; @@ -38,7 +38,7 @@ struct Window::State { bool statusVisible = false; string title; bool visible = false; - set widget; + group widget; string widgetFont; }; @@ -50,7 +50,7 @@ struct Action::State { }; struct Menu::State { - set action; + group action; nall::image image = {0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0}; string text; }; @@ -67,7 +67,7 @@ struct CheckItem::State { struct RadioItem::State { bool checked = true; - set group; + nall::group group; string text; }; @@ -152,7 +152,7 @@ struct ProgressBar::State { struct RadioButton::State { bool checked = true; - set group; + nall::group group; string text; }; diff --git a/higan/phoenix/gtk/action/radio-item.cpp b/higan/phoenix/gtk/action/radio-item.cpp index a1b2bcfd..13fc129e 100755 --- a/higan/phoenix/gtk/action/radio-item.cpp +++ b/higan/phoenix/gtk/action/radio-item.cpp @@ -16,7 +16,7 @@ void pRadioItem::setChecked() { locked = false; } -void pRadioItem::setGroup(const set &group) { +void pRadioItem::setGroup(const group &group) { for(unsigned n = 0; n < group.size(); n++) { if(n == 0) continue; GSList *currentGroup = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(group[0].p.widget)); diff --git a/higan/phoenix/gtk/platform.hpp b/higan/phoenix/gtk/platform.hpp index ed589c81..ec2f01d4 100755 --- a/higan/phoenix/gtk/platform.hpp +++ b/higan/phoenix/gtk/platform.hpp @@ -11,16 +11,21 @@ struct pApplication { static void initialize(); }; -struct Settings : public configuration { +struct Settings : Configuration::Document { bidirectional_map keymap; - unsigned frameGeometryX; - unsigned frameGeometryY; - unsigned frameGeometryWidth; - unsigned frameGeometryHeight; - unsigned menuGeometryHeight; - unsigned statusGeometryHeight; - unsigned windowBackgroundColor; + struct Geometry : Configuration::Node { + unsigned frameX; + unsigned frameY; + unsigned frameWidth; + unsigned frameHeight; + unsigned menuHeight; + unsigned statusHeight; + } geometry; + + struct Window : Configuration::Node { + unsigned backgroundColor; + } window; void load(); void save(); @@ -209,7 +214,7 @@ struct pRadioItem : public pAction { bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {} @@ -442,7 +447,7 @@ struct pRadioButton : public pWidget { bool checked(); Size minimumSize(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioButton(RadioButton &radioButton) : pWidget(radioButton), radioButton(radioButton) {} diff --git a/higan/phoenix/gtk/settings.cpp b/higan/phoenix/gtk/settings.cpp index bd8950d5..dd1d21be 100755 --- a/higan/phoenix/gtk/settings.cpp +++ b/higan/phoenix/gtk/settings.cpp @@ -3,27 +3,27 @@ namespace phoenix { static Settings *settings = nullptr; void Settings::load() { - string path = {userpath(), ".config/phoenix/gtk.cfg"}; - configuration::load(path); + string path = {userpath(), ".config/phoenix/gtk.bml"}; + Configuration::Document::load(path); } void Settings::save() { - string path = { userpath(), ".config/" }; - mkdir(path, 0755); - path.append("phoenix/"); - mkdir(path, 0755); - path.append("gtk.cfg"); - configuration::save(path); + string path = {userpath(), ".config/phoenix/"}; + directory::create(path, 0755); + path.append("gtk.bml"); + Configuration::Document::save(path); } Settings::Settings() { - append(frameGeometryX = 4, "frameGeometryX"); - append(frameGeometryY = 24, "frameGeometryY"); - append(frameGeometryWidth = 8, "frameGeometryWidth"); - append(frameGeometryHeight = 28, "frameGeometryHeight"); - append(menuGeometryHeight = 20, "menuGeometryHeight"); - append(statusGeometryHeight = 20, "statusGeometryHeight"); - append(windowBackgroundColor = 0xedeceb, "windowBackgroundColor"); + geometry.append(geometry.frameX = 4, "FrameX"); + geometry.append(geometry.frameY = 24, "FrameY"); + geometry.append(geometry.frameWidth = 8, "FrameWidth"); + geometry.append(geometry.frameHeight = 28, "FrameHeight"); + geometry.append(geometry.menuHeight = 20, "MenuHeight"); + geometry.append(geometry.statusHeight = 20, "StatusHeight"); + append(geometry, "Geometry"); + window.append(window.backgroundColor = 0xedeceb, "BackgroundColor"); + append(window, "Window"); } } diff --git a/higan/phoenix/gtk/widget/radio-button.cpp b/higan/phoenix/gtk/widget/radio-button.cpp index cdcddcc6..c883cc06 100644 --- a/higan/phoenix/gtk/widget/radio-button.cpp +++ b/higan/phoenix/gtk/widget/radio-button.cpp @@ -20,7 +20,7 @@ void pRadioButton::setChecked() { parent().locked = false; } -void pRadioButton::setGroup(const set &group) { +void pRadioButton::setGroup(const group &group) { parent().locked = true; if(radioButton.state.group.size() == 0 || &radioButton.state.group[0].p == this) return; gtk_radio_button_set_group( diff --git a/higan/phoenix/gtk/window.cpp b/higan/phoenix/gtk/window.cpp index be190fdf..accbbddd 100755 --- a/higan/phoenix/gtk/window.cpp +++ b/higan/phoenix/gtk/window.cpp @@ -42,13 +42,13 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win if(window->state.fullScreen == false) { //update geometry settings - settings->frameGeometryX = client.x - border.x; - settings->frameGeometryY = client.y - border.y; - settings->frameGeometryWidth = border.width - client.width; - settings->frameGeometryHeight = border.height - client.height; + settings->geometry.frameX = client.x - border.x; + settings->geometry.frameY = client.y - border.y; + settings->geometry.frameWidth = border.width - client.width; + settings->geometry.frameHeight = border.height - client.height; if(window->state.backgroundColorOverride == false) { GdkColor color = widget->style->bg[GTK_STATE_NORMAL]; - settings->windowBackgroundColor + settings->window.backgroundColor = ((uint8_t)(color.red >> 8) << 16) + ((uint8_t)(color.green >> 8) << 8) + ((uint8_t)(color.blue >> 8) << 0); @@ -154,9 +154,9 @@ void pWindow::append(Widget &widget) { Color pWindow::backgroundColor() { if(window.state.backgroundColorOverride) return window.state.backgroundColor; return { - (uint8_t)(settings->windowBackgroundColor >> 16), - (uint8_t)(settings->windowBackgroundColor >> 8), - (uint8_t)(settings->windowBackgroundColor >> 0), + (uint8_t)(settings->window.backgroundColor >> 16), + (uint8_t)(settings->window.backgroundColor >> 8), + (uint8_t)(settings->window.backgroundColor >> 0), 255 }; } @@ -170,10 +170,10 @@ Geometry pWindow::frameMargin() { }; return { - settings->frameGeometryX, - settings->frameGeometryY + menuHeight(), - settings->frameGeometryWidth, - settings->frameGeometryHeight + menuHeight() + statusHeight() + settings->geometry.frameX, + settings->geometry.frameY + menuHeight(), + settings->geometry.frameWidth, + settings->geometry.frameHeight + menuHeight() + statusHeight() }; } @@ -291,13 +291,13 @@ void pWindow::setVisible(bool visible) { if(gtk_widget_get_visible(menu)) { GtkAllocation allocation; gtk_widget_get_allocation(menu, &allocation); - settings->menuGeometryHeight = allocation.height; + settings->geometry.menuHeight = allocation.height; } if(gtk_widget_get_visible(status)) { GtkAllocation allocation; gtk_widget_get_allocation(status, &allocation); - settings->statusGeometryHeight = allocation.height; + settings->geometry.statusHeight = allocation.height; } } } @@ -370,11 +370,11 @@ void pWindow::constructor() { } unsigned pWindow::menuHeight() { - return window.state.menuVisible ? settings->menuGeometryHeight : 0; + return window.state.menuVisible ? settings->geometry.menuHeight : 0; } unsigned pWindow::statusHeight() { - return window.state.statusVisible ? settings->statusGeometryHeight : 0; + return window.state.statusVisible ? settings->geometry.statusHeight : 0; } } diff --git a/higan/phoenix/nall/Makefile b/higan/phoenix/nall/Makefile deleted file mode 100644 index 02b604c8..00000000 --- a/higan/phoenix/nall/Makefile +++ /dev/null @@ -1,131 +0,0 @@ -# Makefile -# author: byuu -# license: public domain - -[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]) -[space] := -[space] += - -##### -# platform detection -##### - -ifeq ($(platform),) - uname := $(shell uname -a) - ifeq ($(uname),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Windows,$(uname)),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring CYGWIN,$(uname)),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Darwin,$(uname)),) - platform := osx - delete = rm -f $1 - else - platform := x - delete = rm -f $1 - endif -endif - -ifeq ($(compiler),) - ifeq ($(platform),win) - compiler := g++ - flags := - link := - else ifeq ($(platform),osx) - compiler := clang - flags := -w -stdlib=libc++ - link := -lc++ -lobjc - else - compiler := g++-4.7 - flags := - link := - endif - - cflags := -x c -std=gnu99 - objcflags := -x objective-c -std=gnu99 - cppflags := -x c++ -std=gnu++11 - objcppflags := -x objective-c++ -std=gnu++11 -endif - -ifeq ($(arch),x86) - flags := -m32 $(flags) - link := -m32 $(link) -endif - -ifeq ($(prefix),) - prefix := /usr/local -endif - -##### -# function rwildcard(directory, pattern) -##### -rwildcard = \ - $(strip \ - $(filter $(if $2,$2,%), \ - $(foreach f, \ - $(wildcard $1*), \ - $(eval t = $(call rwildcard,$f/)) \ - $(if $t,$t,$f) \ - ) \ - ) \ - ) - -##### -# function strtr(source, from, to) -##### -strtr = \ - $(eval __temp := $1) \ - $(strip \ - $(foreach c, \ - $(join $(addsuffix :,$2),$3), \ - $(eval __temp := \ - $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) - -##### -# function strupper(source) -##### -strupper = $(call strtr,$1,$([a-z]),$([A-Z])) - -##### -# function strlower(source) -##### -strlower = $(call strtr,$1,$([A-Z]),$([a-z])) - -##### -# function strlen(source) -##### -strlen = \ - $(eval __temp := $(subst $([space]),_,$1)) \ - $(words \ - $(strip \ - $(foreach c, \ - $([all]), \ - $(eval __temp := \ - $(subst $c,$c ,$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) \ - ) - -##### -# function streq(source) -##### -streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1) - -##### -# function strne(source) -##### -strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,) diff --git a/higan/phoenix/nall/algorithm.hpp b/higan/phoenix/nall/algorithm.hpp deleted file mode 100644 index 037f0bb7..00000000 --- a/higan/phoenix/nall/algorithm.hpp +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } -} - -#endif diff --git a/higan/phoenix/nall/any.hpp b/higan/phoenix/nall/any.hpp deleted file mode 100644 index 7661a2a4..00000000 --- a/higan/phoenix/nall/any.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include - -namespace nall { - struct any { - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename type_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(nullptr) {} - ~any() { if(container) delete container; } - template any(const T& value_) : container(nullptr) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return nullptr; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return nullptr; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/higan/phoenix/nall/atoi.hpp b/higan/phoenix/nall/atoi.hpp deleted file mode 100644 index 26756c79..00000000 --- a/higan/phoenix/nall/atoi.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_ATOI_HPP -#define NALL_ATOI_HPP - -#include - -namespace nall { - -//note: this header is intended to form the base for user-defined literals; -//once they are supported by GCC. eg: -//unsigned operator "" b(const char *s) { return binary(s); } -//-> signed data = 1001b; -//(0b1001 is nicer, but is not part of the C++ standard) - -constexpr inline uintmax_t binary_(const char *s, uintmax_t sum = 0) { - return ( - *s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') : - sum - ); -} - -constexpr inline uintmax_t octal_(const char *s, uintmax_t sum = 0) { - return ( - *s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') : - sum - ); -} - -constexpr inline uintmax_t decimal_(const char *s, uintmax_t sum = 0) { - return ( - *s >= '0' && *s <= '9' ? decimal_(s + 1, (sum * 10) + *s - '0') : - sum - ); -} - -constexpr inline uintmax_t hex_(const char *s, uintmax_t sum = 0) { - return ( - *s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) : - *s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) : - *s >= '0' && *s <= '9' ? hex_(s + 1, (sum << 4) | *s - '0') : - sum - ); -} - -// - -constexpr inline uintmax_t binary(const char *s) { - return ( - *s == '0' && *(s + 1) == 'B' ? binary_(s + 2) : - *s == '0' && *(s + 1) == 'b' ? binary_(s + 2) : - *s == '%' ? binary_(s + 1) : - binary_(s) - ); -} - -constexpr inline uintmax_t octal(const char *s) { - return ( - octal_(s) - ); -} - -constexpr inline intmax_t integer(const char *s) { - return ( - *s == '+' ? +decimal_(s + 1) : - *s == '-' ? -decimal_(s + 1) : - decimal_(s) - ); -} - -constexpr inline uintmax_t decimal(const char *s) { - return ( - decimal_(s) - ); -} - -constexpr inline uintmax_t hex(const char *s) { - return ( - *s == '0' && *(s + 1) == 'X' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'x' ? hex_(s + 2) : - *s == '$' ? hex_(s + 1) : - hex_(s) - ); -} - -constexpr inline intmax_t numeral(const char *s) { - return ( - *s == '0' && *(s + 1) == 'X' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'x' ? hex_(s + 2) : - *s == '0' && *(s + 1) == 'B' ? binary_(s + 2) : - *s == '0' && *(s + 1) == 'b' ? binary_(s + 2) : - *s == '0' ? octal_(s + 1) : - *s == '+' ? +decimal_(s + 1) : - *s == '-' ? -decimal_(s + 1) : - decimal_(s) - ); -} - -inline double fp(const char *s) { - return atof(s); -} - -} - -#endif diff --git a/higan/phoenix/nall/base64.hpp b/higan/phoenix/nall/base64.hpp deleted file mode 100644 index daf3fa60..00000000 --- a/higan/phoenix/nall/base64.hpp +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - struct base64 { - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 8](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - break; - } - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - break; - } - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - break; - } - - } - - i++; - } - - return true; - } - - static string encode(const string &data) { - char *buffer = nullptr; - encode(buffer, (const uint8_t*)(const char*)data, data.length()); - string result = buffer; - delete[] buffer; - return result; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength + 1](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - - case 0: { - output[o] = x << 2; - break; - } - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - break; - } - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - break; - } - - case 3: { - output[o++] |= x; - break; - } - - } - } - - outlength = o; - return true; - } - - static string decode(const string &data) { - uint8_t *buffer = nullptr; - unsigned size = 0; - decode(buffer, size, (const char*)data); - string result = (const char*)buffer; - delete[] buffer; - return result; - } - - private: - static char enc(uint8_t n) { - //base64 for URL encodings (URL = -_, MIME = +/) - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/higan/phoenix/nall/beat/archive.hpp b/higan/phoenix/nall/beat/archive.hpp deleted file mode 100644 index ef7294cf..00000000 --- a/higan/phoenix/nall/beat/archive.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#ifndef NALL_BEAT_ARCHIVE_HPP -#define NALL_BEAT_ARCHIVE_HPP - -#include - -namespace nall { - -struct beatArchive : beatBase { - bool create(const string &beatname, string pathname, const string &metadata = "") { - if(fp.open(beatname, file::mode::write) == false) return false; - if(pathname.endswith("/") == false) pathname.append("/"); - - checksum = ~0; - writeString("BPA1"); - writeNumber(metadata.length()); - writeString(metadata); - - lstring list; - ls(list, pathname, pathname); - for(auto &name : list) { - if(name.endswith("/")) { - name.rtrim<1>("/"); - writeNumber(0 | ((name.length() - 1) << 1)); - writeString(name); - } else { - file stream; - if(stream.open({pathname, name}, file::mode::read) == false) return false; - writeNumber(1 | ((name.length() - 1) << 1)); - writeString(name); - unsigned size = stream.size(); - writeNumber(size); - uint32_t checksum = ~0; - while(size--) { - uint8_t data = stream.read(); - write(data); - checksum = crc32_adjust(checksum, data); - } - writeChecksum(~checksum); - } - } - - writeChecksum(~checksum); - fp.close(); - return true; - } - - bool unpack(const string &beatname, string pathname) { - if(fp.open(beatname, file::mode::read) == false) return false; - if(pathname.endswith("/") == false) pathname.append("/"); - - checksum = ~0; - if(readString(4) != "BPA1") return false; - unsigned length = readNumber(); - while(length--) read(); - - directory::create(pathname); - while(fp.offset() < fp.size() - 4) { - unsigned data = readNumber(); - string name = readString((data >> 1) + 1); - if(name.position("\\") || name.position("../")) return false; //block path exploits - - if((data & 1) == 0) { - directory::create({pathname, name}); - } else { - file stream; - if(stream.open({pathname, name}, file::mode::write) == false) return false; - unsigned size = readNumber(); - uint32_t checksum = ~0; - while(size--) { - uint8_t data = read(); - stream.write(data); - checksum = crc32_adjust(checksum, data); - } - if(readChecksum(~checksum) == false) return false; - } - } - - return readChecksum(~checksum); - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/beat/base.hpp b/higan/phoenix/nall/beat/base.hpp deleted file mode 100644 index 8e0001be..00000000 --- a/higan/phoenix/nall/beat/base.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef NALL_BEAT_BASE_HPP -#define NALL_BEAT_BASE_HPP - -namespace nall { - -struct beatBase { -protected: - file fp; - uint32_t checksum; - - void ls(lstring &list, const string &path, const string &basepath) { - lstring paths = directory::folders(path); - for(auto &pathname : paths) { - list.append(string{path, pathname}.ltrim<1>(basepath)); - ls(list, {path, pathname}, basepath); - } - - lstring files = directory::files(path); - for(auto &filename : files) { - list.append(string{path, filename}.ltrim<1>(basepath)); - } - } - - void write(uint8_t data) { - fp.write(data); - checksum = crc32_adjust(checksum, data); - } - - void writeNumber(uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) return write(0x80 | x); - write(x); - data--; - } - } - - void writeString(const string &text) { - unsigned length = text.length(); - for(unsigned n = 0; n < length; n++) write(text[n]); - } - - void writeChecksum(uint32_t checksum) { - write(checksum >> 0); - write(checksum >> 8); - write(checksum >> 16); - write(checksum >> 24); - } - - uint8_t read() { - uint8_t data = fp.read(); - checksum = crc32_adjust(checksum, data); - return data; - } - - uint64_t readNumber() { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - } - - string readString(unsigned length) { - string text; - text.reserve(length + 1); - for(unsigned n = 0; n < length; n++) { - text[n] = fp.read(); - checksum = crc32_adjust(checksum, text[n]); - } - text[length] = 0; - return text; - } - - bool readChecksum(uint32_t source) { - uint32_t checksum = 0; - checksum |= read() << 0; - checksum |= read() << 8; - checksum |= read() << 16; - checksum |= read() << 24; - return checksum == source; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/beat/delta.hpp b/higan/phoenix/nall/beat/delta.hpp deleted file mode 100644 index 3fc400fa..00000000 --- a/higan/phoenix/nall/beat/delta.hpp +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef NALL_BEAT_DELTA_HPP -#define NALL_BEAT_DELTA_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpsdelta { - inline void source(const uint8_t *data, unsigned size); - inline void target(const uint8_t *data, unsigned size); - - inline bool source(const string &filename); - inline bool target(const string &filename); - inline bool create(const string &filename, const string &metadata = ""); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - enum : unsigned { Granularity = 1 }; - - struct Node { - unsigned offset; - Node *next; - inline Node() : offset(0), next(nullptr) {} - inline ~Node() { if(next) delete next; } - }; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - const uint8_t *targetData; - unsigned targetSize; -}; - -void bpsdelta::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpsdelta::target(const uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpsdelta::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpsdelta::target(const string &filename) { - if(targetFile.open(filename, filemap::mode::read) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -bool bpsdelta::create(const string &filename, const string &metadata) { - file modifyFile; - if(modifyFile.open(filename, file::mode::write) == false) return false; - - uint32_t sourceChecksum = ~0, modifyChecksum = ~0; - unsigned sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; - - auto write = [&](uint8_t data) { - modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - write('B'); - write('P'); - write('S'); - write('1'); - - encode(sourceSize); - encode(targetSize); - - unsigned markupSize = metadata.length(); - encode(markupSize); - for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); - - Node *sourceTree[65536], *targetTree[65536]; - for(unsigned n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr; - - //source tree creation - for(unsigned offset = 0; offset < sourceSize; offset++) { - uint16_t symbol = sourceData[offset + 0]; - sourceChecksum = crc32_adjust(sourceChecksum, symbol); - if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8; - Node *node = new Node; - node->offset = offset; - node->next = sourceTree[symbol]; - sourceTree[symbol] = node; - } - - unsigned targetReadLength = 0; - - auto targetReadFlush = [&]() { - if(targetReadLength) { - encode(TargetRead | ((targetReadLength - 1) << 2)); - unsigned offset = outputOffset - targetReadLength; - while(targetReadLength) write(targetData[offset++]), targetReadLength--; - } - }; - - while(outputOffset < targetSize) { - unsigned maxLength = 0, maxOffset = 0, mode = TargetRead; - - uint16_t symbol = targetData[outputOffset + 0]; - if(outputOffset < targetSize - 1) symbol |= targetData[outputOffset + 1] << 8; - - { //source read - unsigned length = 0, offset = outputOffset; - while(offset < sourceSize && offset < targetSize && sourceData[offset] == targetData[offset]) { - length++; - offset++; - } - if(length > maxLength) maxLength = length, mode = SourceRead; - } - - { //source copy - Node *node = sourceTree[symbol]; - while(node) { - unsigned length = 0, x = node->offset, y = outputOffset; - while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = SourceCopy; - node = node->next; - } - } - - { //target copy - Node *node = targetTree[symbol]; - while(node) { - unsigned length = 0, x = node->offset, y = outputOffset; - while(y < targetSize && targetData[x++] == targetData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset, mode = TargetCopy; - node = node->next; - } - - //target tree append - node = new Node; - node->offset = outputOffset; - node->next = targetTree[symbol]; - targetTree[symbol] = node; - } - - { //target read - if(maxLength < 4) { - maxLength = min((unsigned)Granularity, targetSize - outputOffset); - mode = TargetRead; - } - } - - if(mode != TargetRead) targetReadFlush(); - - switch(mode) { - case SourceRead: - encode(SourceRead | ((maxLength - 1) << 2)); - break; - case TargetRead: - //delay write to group sequential TargetRead commands into one - targetReadLength += maxLength; - break; - case SourceCopy: - case TargetCopy: - encode(mode | ((maxLength - 1) << 2)); - signed relativeOffset; - if(mode == SourceCopy) { - relativeOffset = maxOffset - sourceRelativeOffset; - sourceRelativeOffset = maxOffset + maxLength; - } else { - relativeOffset = maxOffset - targetRelativeOffset; - targetRelativeOffset = maxOffset + maxLength; - } - encode((relativeOffset < 0) | (abs(relativeOffset) << 1)); - break; - } - - outputOffset += maxLength; - } - - targetReadFlush(); - - sourceChecksum = ~sourceChecksum; - for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); - for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - modifyFile.close(); - return true; -} - -} - -#endif diff --git a/higan/phoenix/nall/beat/linear.hpp b/higan/phoenix/nall/beat/linear.hpp deleted file mode 100644 index 078aae34..00000000 --- a/higan/phoenix/nall/beat/linear.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef NALL_BEAT_LINEAR_HPP -#define NALL_BEAT_LINEAR_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpslinear { - inline void source(const uint8_t *data, unsigned size); - inline void target(const uint8_t *data, unsigned size); - - inline bool source(const string &filename); - inline bool target(const string &filename); - inline bool create(const string &filename, const string &metadata = ""); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - enum : unsigned { Granularity = 1 }; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - const uint8_t *targetData; - unsigned targetSize; -}; - -void bpslinear::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpslinear::target(const uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpslinear::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpslinear::target(const string &filename) { - if(targetFile.open(filename, filemap::mode::read) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -bool bpslinear::create(const string &filename, const string &metadata) { - file modifyFile; - if(modifyFile.open(filename, file::mode::write) == false) return false; - - uint32_t modifyChecksum = ~0; - unsigned targetRelativeOffset = 0, outputOffset = 0; - - auto write = [&](uint8_t data) { - modifyFile.write(data); - modifyChecksum = crc32_adjust(modifyChecksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - unsigned targetReadLength = 0; - - auto targetReadFlush = [&]() { - if(targetReadLength) { - encode(TargetRead | ((targetReadLength - 1) << 2)); - unsigned offset = outputOffset - targetReadLength; - while(targetReadLength) write(targetData[offset++]), targetReadLength--; - } - }; - - write('B'); - write('P'); - write('S'); - write('1'); - - encode(sourceSize); - encode(targetSize); - - unsigned markupSize = metadata.length(); - encode(markupSize); - for(unsigned n = 0; n < markupSize; n++) write(metadata[n]); - - while(outputOffset < targetSize) { - unsigned sourceLength = 0; - for(unsigned n = 0; outputOffset + n < min(sourceSize, targetSize); n++) { - if(sourceData[outputOffset + n] != targetData[outputOffset + n]) break; - sourceLength++; - } - - unsigned rleLength = 0; - for(unsigned n = 1; outputOffset + n < targetSize; n++) { - if(targetData[outputOffset] != targetData[outputOffset + n]) break; - rleLength++; - } - - if(rleLength >= 4) { - //write byte to repeat - targetReadLength++; - outputOffset++; - targetReadFlush(); - - //copy starting from repetition byte - encode(TargetCopy | ((rleLength - 1) << 2)); - unsigned relativeOffset = (outputOffset - 1) - targetRelativeOffset; - encode(relativeOffset << 1); - outputOffset += rleLength; - targetRelativeOffset = outputOffset - 1; - } else if(sourceLength >= 4) { - targetReadFlush(); - encode(SourceRead | ((sourceLength - 1) << 2)); - outputOffset += sourceLength; - } else { - targetReadLength += Granularity; - outputOffset += Granularity; - } - } - - targetReadFlush(); - - uint32_t sourceChecksum = crc32_calculate(sourceData, sourceSize); - for(unsigned n = 0; n < 32; n += 8) write(sourceChecksum >> n); - uint32_t targetChecksum = crc32_calculate(targetData, targetSize); - for(unsigned n = 0; n < 32; n += 8) write(targetChecksum >> n); - uint32_t outputChecksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - modifyFile.close(); - return true; -} - -} - -#endif diff --git a/higan/phoenix/nall/beat/metadata.hpp b/higan/phoenix/nall/beat/metadata.hpp deleted file mode 100644 index 58e6ab0a..00000000 --- a/higan/phoenix/nall/beat/metadata.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef NALL_BEAT_METADATA_HPP -#define NALL_BEAT_METADATA_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpsmetadata { - inline bool load(const string &filename); - inline bool save(const string &filename, const string &metadata); - inline string metadata() const; - -protected: - file sourceFile; - string metadataString; -}; - -bool bpsmetadata::load(const string &filename) { - if(sourceFile.open(filename, file::mode::read) == false) return false; - - auto read = [&]() -> uint8_t { - return sourceFile.read(); - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - if(read() != 'B') return false; - if(read() != 'P') return false; - if(read() != 'S') return false; - if(read() != '1') return false; - decode(); - decode(); - unsigned metadataSize = decode(); - char data[metadataSize + 1]; - for(unsigned n = 0; n < metadataSize; n++) data[n] = read(); - data[metadataSize] = 0; - metadataString = (const char*)data; - - return true; -} - -bool bpsmetadata::save(const string &filename, const string &metadata) { - file targetFile; - if(targetFile.open(filename, file::mode::write) == false) return false; - if(sourceFile.open() == false) return false; - sourceFile.seek(0); - - auto read = [&]() -> uint8_t { - return sourceFile.read(); - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - uint32_t checksum = ~0; - - auto write = [&](uint8_t data) { - targetFile.write(data); - checksum = crc32_adjust(checksum, data); - }; - - auto encode = [&](uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - }; - - for(unsigned n = 0; n < 4; n++) write(read()); - encode(decode()); - encode(decode()); - unsigned sourceLength = decode(); - unsigned targetLength = metadata.length(); - encode(targetLength); - sourceFile.seek(sourceLength, file::index::relative); - for(unsigned n = 0; n < targetLength; n++) write(metadata[n]); - unsigned length = sourceFile.size() - sourceFile.offset() - 4; - for(unsigned n = 0; n < length; n++) write(read()); - uint32_t outputChecksum = ~checksum; - for(unsigned n = 0; n < 32; n += 8) write(outputChecksum >> n); - - targetFile.close(); - return true; -} - -string bpsmetadata::metadata() const { - return metadataString; -} - -} - -#endif diff --git a/higan/phoenix/nall/beat/multi.hpp b/higan/phoenix/nall/beat/multi.hpp deleted file mode 100644 index cddf5d6b..00000000 --- a/higan/phoenix/nall/beat/multi.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#ifndef NALL_BEAT_MULTI_HPP -#define NALL_BEAT_MULTI_HPP - -#include -#include -#include - -namespace nall { - -struct bpsmulti { - enum : unsigned { - CreatePath = 0, - CreateFile = 1, - ModifyFile = 2, - MirrorFile = 3, - }; - - enum : unsigned { - OriginSource = 0, - OriginTarget = 1, - }; - - bool create(const string &patchName, const string &sourcePath, const string &targetPath, bool delta = false, const string &metadata = "") { - if(fp.open()) fp.close(); - fp.open(patchName, file::mode::write); - checksum = ~0; - - writeString("BPM1"); //signature - writeNumber(metadata.length()); - writeString(metadata); - - lstring sourceList, targetList; - ls(sourceList, sourcePath, sourcePath); - ls(targetList, targetPath, targetPath); - - for(auto &targetName : targetList) { - if(targetName.endswith("/")) { - targetName.rtrim<1>("/"); - writeNumber(CreatePath | ((targetName.length() - 1) << 2)); - writeString(targetName); - } else if(auto position = sourceList.find(targetName)) { //if sourceName == targetName - file sp, dp; - sp.open({sourcePath, targetName}, file::mode::read); - dp.open({targetPath, targetName}, file::mode::read); - - bool identical = sp.size() == dp.size(); - uint32_t cksum = ~0; - - for(unsigned n = 0; n < sp.size(); n++) { - uint8_t byte = sp.read(); - if(identical && byte != dp.read()) identical = false; - cksum = crc32_adjust(cksum, byte); - } - - if(identical) { - writeNumber(MirrorFile | ((targetName.length() - 1) << 2)); - writeString(targetName); - writeNumber(OriginSource); - writeChecksum(~cksum); - } else { - writeNumber(ModifyFile | ((targetName.length() - 1) << 2)); - writeString(targetName); - writeNumber(OriginSource); - - if(delta == false) { - bpslinear patch; - patch.source({sourcePath, targetName}); - patch.target({targetPath, targetName}); - patch.create({temppath(), "temp.bps"}); - } else { - bpsdelta patch; - patch.source({sourcePath, targetName}); - patch.target({targetPath, targetName}); - patch.create({temppath(), "temp.bps"}); - } - - auto buffer = file::read({temppath(), "temp.bps"}); - writeNumber(buffer.size()); - for(auto &byte : buffer) write(byte); - } - } else { - writeNumber(CreateFile | ((targetName.length() - 1) << 2)); - writeString(targetName); - auto buffer = file::read({targetPath, targetName}); - writeNumber(buffer.size()); - for(auto &byte : buffer) write(byte); - writeChecksum(crc32_calculate(buffer.data(), buffer.size())); - } - } - - //checksum - writeChecksum(~checksum); - fp.close(); - return true; - } - - bool apply(const string &patchName, const string &sourcePath, const string &targetPath) { - directory::remove(targetPath); //start with a clean directory - directory::create(targetPath); - - if(fp.open()) fp.close(); - fp.open(patchName, file::mode::read); - checksum = ~0; - - if(readString(4) != "BPM1") return false; - auto metadataLength = readNumber(); - while(metadataLength--) read(); - - while(fp.offset() < fp.size() - 4) { - auto encoding = readNumber(); - unsigned action = encoding & 3; - unsigned targetLength = (encoding >> 2) + 1; - string targetName = readString(targetLength); - - if(action == CreatePath) { - directory::create({targetPath, targetName, "/"}); - } else if(action == CreateFile) { - file fp; - fp.open({targetPath, targetName}, file::mode::write); - auto fileSize = readNumber(); - while(fileSize--) fp.write(read()); - uint32_t cksum = readChecksum(); - } else if(action == ModifyFile) { - auto encoding = readNumber(); - string originPath = encoding & 1 ? targetPath : sourcePath; - string sourceName = (encoding >> 1) == 0 ? targetName : readString(encoding >> 1); - auto patchSize = readNumber(); - vector buffer; - buffer.resize(patchSize); - for(unsigned n = 0; n < patchSize; n++) buffer[n] = read(); - bpspatch patch; - patch.modify(buffer.data(), buffer.size()); - patch.source({originPath, sourceName}); - patch.target({targetPath, targetName}); - if(patch.apply() != bpspatch::result::success) return false; - } else if(action == MirrorFile) { - auto encoding = readNumber(); - string originPath = encoding & 1 ? targetPath : sourcePath; - string sourceName = (encoding >> 1) == 0 ? targetName : readString(encoding >> 1); - file::copy({originPath, sourceName}, {targetPath, targetName}); - uint32_t cksum = readChecksum(); - } - } - - uint32_t cksum = ~checksum; - if(read() != (uint8_t)(cksum >> 0)) return false; - if(read() != (uint8_t)(cksum >> 8)) return false; - if(read() != (uint8_t)(cksum >> 16)) return false; - if(read() != (uint8_t)(cksum >> 24)) return false; - - fp.close(); - return true; - } - -protected: - file fp; - uint32_t checksum; - - //create() functions - void ls(lstring &list, const string &path, const string &basepath) { - lstring paths = directory::folders(path); - for(auto &pathname : paths) { - list.append(string{path, pathname}.ltrim<1>(basepath)); - ls(list, {path, pathname}, basepath); - } - - lstring files = directory::files(path); - for(auto &filename : files) { - list.append(string{path, filename}.ltrim<1>(basepath)); - } - } - - void write(uint8_t data) { - fp.write(data); - checksum = crc32_adjust(checksum, data); - } - - void writeNumber(uint64_t data) { - while(true) { - uint64_t x = data & 0x7f; - data >>= 7; - if(data == 0) { - write(0x80 | x); - break; - } - write(x); - data--; - } - } - - void writeString(const string &text) { - unsigned length = text.length(); - for(unsigned n = 0; n < length; n++) write(text[n]); - } - - void writeChecksum(uint32_t cksum) { - write(cksum >> 0); - write(cksum >> 8); - write(cksum >> 16); - write(cksum >> 24); - } - - //apply() functions - uint8_t read() { - uint8_t data = fp.read(); - checksum = crc32_adjust(checksum, data); - return data; - } - - uint64_t readNumber() { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - } - - string readString(unsigned length) { - string text; - text.reserve(length + 1); - for(unsigned n = 0; n < length; n++) text[n] = read(); - text[length] = 0; - return text; - } - - uint32_t readChecksum() { - uint32_t checksum = 0; - checksum |= read() << 0; - checksum |= read() << 8; - checksum |= read() << 16; - checksum |= read() << 24; - return checksum; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/beat/patch.hpp b/higan/phoenix/nall/beat/patch.hpp deleted file mode 100644 index 8c6de75b..00000000 --- a/higan/phoenix/nall/beat/patch.hpp +++ /dev/null @@ -1,219 +0,0 @@ -#ifndef NALL_BEAT_PATCH_HPP -#define NALL_BEAT_PATCH_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -struct bpspatch { - inline bool modify(const uint8_t *data, unsigned size); - inline void source(const uint8_t *data, unsigned size); - inline void target(uint8_t *data, unsigned size); - - inline bool modify(const string &filename); - inline bool source(const string &filename); - inline bool target(const string &filename); - - inline string metadata() const; - inline unsigned size() const; - - enum result : unsigned { - unknown, - success, - patch_too_small, - patch_invalid_header, - source_too_small, - target_too_small, - source_checksum_invalid, - target_checksum_invalid, - patch_checksum_invalid, - }; - - inline result apply(); - -protected: - enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy }; - - filemap modifyFile; - const uint8_t *modifyData; - unsigned modifySize; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - - filemap targetFile; - uint8_t *targetData; - unsigned targetSize; - - unsigned modifySourceSize; - unsigned modifyTargetSize; - unsigned modifyMarkupSize; - string metadataString; -}; - -bool bpspatch::modify(const uint8_t *data, unsigned size) { - if(size < 19) return false; - modifyData = data; - modifySize = size; - - unsigned offset = 4; - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = modifyData[offset++]; - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - modifySourceSize = decode(); - modifyTargetSize = decode(); - modifyMarkupSize = decode(); - - char buffer[modifyMarkupSize + 1]; - for(unsigned n = 0; n < modifyMarkupSize; n++) buffer[n] = modifyData[offset++]; - buffer[modifyMarkupSize] = 0; - metadataString = (const char*)buffer; - - return true; -} - -void bpspatch::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -void bpspatch::target(uint8_t *data, unsigned size) { - targetData = data; - targetSize = size; -} - -bool bpspatch::modify(const string &filename) { - if(modifyFile.open(filename, filemap::mode::read) == false) return false; - return modify(modifyFile.data(), modifyFile.size()); -} - -bool bpspatch::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - source(sourceFile.data(), sourceFile.size()); - return true; -} - -bool bpspatch::target(const string &filename) { - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - fp.truncate(modifyTargetSize); - fp.close(); - - if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; - target(targetFile.data(), targetFile.size()); - return true; -} - -string bpspatch::metadata() const { - return metadataString; -} - -unsigned bpspatch::size() const { - return modifyTargetSize; -} - -bpspatch::result bpspatch::apply() { - if(modifySize < 19) return result::patch_too_small; - - uint32_t modifyChecksum = ~0, targetChecksum = ~0; - unsigned modifyOffset = 0, sourceRelativeOffset = 0, targetRelativeOffset = 0, outputOffset = 0; - - auto read = [&]() -> uint8_t { - uint8_t data = modifyData[modifyOffset++]; - modifyChecksum = crc32_adjust(modifyChecksum, data); - return data; - }; - - auto decode = [&]() -> uint64_t { - uint64_t data = 0, shift = 1; - while(true) { - uint8_t x = read(); - data += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - data += shift; - } - return data; - }; - - auto write = [&](uint8_t data) { - targetData[outputOffset++] = data; - targetChecksum = crc32_adjust(targetChecksum, data); - }; - - if(read() != 'B') return result::patch_invalid_header; - if(read() != 'P') return result::patch_invalid_header; - if(read() != 'S') return result::patch_invalid_header; - if(read() != '1') return result::patch_invalid_header; - - modifySourceSize = decode(); - modifyTargetSize = decode(); - modifyMarkupSize = decode(); - for(unsigned n = 0; n < modifyMarkupSize; n++) read(); - - if(modifySourceSize > sourceSize) return result::source_too_small; - if(modifyTargetSize > targetSize) return result::target_too_small; - - while(modifyOffset < modifySize - 12) { - unsigned length = decode(); - unsigned mode = length & 3; - length = (length >> 2) + 1; - - switch(mode) { - case SourceRead: - while(length--) write(sourceData[outputOffset]); - break; - case TargetRead: - while(length--) write(read()); - break; - case SourceCopy: - case TargetCopy: - signed offset = decode(); - bool negative = offset & 1; - offset >>= 1; - if(negative) offset = -offset; - - if(mode == SourceCopy) { - sourceRelativeOffset += offset; - while(length--) write(sourceData[sourceRelativeOffset++]); - } else { - targetRelativeOffset += offset; - while(length--) write(targetData[targetRelativeOffset++]); - } - break; - } - } - - uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0; - for(unsigned n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n; - for(unsigned n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n; - uint32_t checksum = ~modifyChecksum; - for(unsigned n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n; - - uint32_t sourceChecksum = crc32_calculate(sourceData, modifySourceSize); - targetChecksum = ~targetChecksum; - - if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid; - if(targetChecksum != modifyTargetChecksum) return result::target_checksum_invalid; - if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid; - - return result::success; -} - -} - -#endif diff --git a/higan/phoenix/nall/bit.hpp b/higan/phoenix/nall/bit.hpp deleted file mode 100644 index 63403eb0..00000000 --- a/higan/phoenix/nall/bit.hpp +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -#include - -namespace nall { - template - inline uintmax_t uclamp(const uintmax_t x) { - enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template - inline uintmax_t uclip(const uintmax_t x) { - enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; - return (x & m); - } - - template - inline intmax_t sclamp(const intmax_t x) { - enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 }; - return (x > m) ? m : (x < -b) ? -b : x; - } - - template - inline intmax_t sclip(const intmax_t x) { - enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; - return ((x & m) ^ b) - b; - } - - namespace bit { - constexpr inline uintmax_t mask(const char *s, uintmax_t sum = 0) { - return ( - *s == '0' || *s == '1' ? mask(s + 1, (sum << 1) | 1) : - *s == ' ' || *s == '_' ? mask(s + 1, sum) : - *s ? mask(s + 1, sum << 1) : - sum - ); - } - - constexpr inline uintmax_t test(const char *s, uintmax_t sum = 0) { - return ( - *s == '0' || *s == '1' ? test(s + 1, (sum << 1) | (*s - '0')) : - *s == ' ' || *s == '_' ? test(s + 1, sum) : - *s ? test(s + 1, sum << 1) : - sum - ); - } - - //lowest(0b1110) == 0b0010 - constexpr inline uintmax_t lowest(const uintmax_t x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - constexpr inline uintmax_t clear_lowest(const uintmax_t x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - constexpr inline uintmax_t set_lowest(const uintmax_t x) { - return x | (x + 1); - } - - //count number of bits set in a byte - inline unsigned count(uintmax_t x) { - unsigned count = 0; - do count += x & 1; while(x >>= 1); - return count; - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline uintmax_t round(uintmax_t x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/higan/phoenix/nall/bmp.hpp b/higan/phoenix/nall/bmp.hpp deleted file mode 100644 index 4950bd39..00000000 --- a/higan/phoenix/nall/bmp.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef NALL_BMP_HPP -#define NALL_BMP_HPP - -#include - -//BMP reader / writer -//note: only 24-bit RGB and 32-bit ARGB uncompressed images supported - -namespace nall { - -struct bmp { - inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height); - inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false); -}; - -bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) { - file fp; - if(fp.open(filename, file::mode::read) == false) return false; - if(fp.size() < 0x36) return false; - - if(fp.readm(2) != 0x424d) return false; - fp.seek(0x000a); - unsigned offset = fp.readl(4); - unsigned dibsize = fp.readl(4); - if(dibsize != 40) return false; - signed headerWidth = fp.readl(4); - if(headerWidth < 0) return false; - signed headerHeight = fp.readl(4); - fp.readl(2); - unsigned bitsPerPixel = fp.readl(2); - if(bitsPerPixel != 24 && bitsPerPixel != 32) return false; - unsigned compression = fp.readl(4); - if(compression != 0) return false; - fp.seek(offset); - - bool noFlip = headerHeight < 0; - width = headerWidth, height = abs(headerHeight); - data = new uint32_t[width * height]; - - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - for(unsigned y = 0; y < height; y++) { - uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width; - for(unsigned x = 0; x < width; x++, p++) { - *p = fp.readl(bytesPerPixel); - if(bytesPerPixel == 3) *p |= 255 << 24; - } - if(paddingLength) fp.readl(paddingLength); - } - - fp.close(); - return true; -} - -bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) { - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - - unsigned bitsPerPixel = alpha ? 32 : 24; - unsigned bytesPerPixel = bitsPerPixel / 8; - unsigned alignedWidth = width * bytesPerPixel; - unsigned paddingLength = 0; - unsigned imageSize = alignedWidth * height; - unsigned fileSize = 0x36 + imageSize; - while(alignedWidth % 4) alignedWidth++, paddingLength++; - - fp.writem(0x424d, 2); //signature - fp.writel(fileSize, 4); //file size - fp.writel(0, 2); //reserved - fp.writel(0, 2); //reserved - fp.writel(0x36, 4); //offset - - fp.writel(40, 4); //DIB size - fp.writel(width, 4); //width - fp.writel(-height, 4); //height - fp.writel(1, 2); //color planes - fp.writel(bitsPerPixel, 2); //bits per pixel - fp.writel(0, 4); //compression method (BI_RGB) - fp.writel(imageSize, 4); //image data size - fp.writel(3780, 4); //horizontal resolution - fp.writel(3780, 4); //vertical resolution - fp.writel(0, 4); //palette size - fp.writel(0, 4); //important color count - - for(unsigned y = 0; y < height; y++) { - const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch); - for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel); - if(paddingLength) fp.writel(0, paddingLength); - } - - fp.close(); - return true; -} - -} - -#endif diff --git a/higan/phoenix/nall/compositor.hpp b/higan/phoenix/nall/compositor.hpp deleted file mode 100644 index c5aa8757..00000000 --- a/higan/phoenix/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_X) - 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_X) - -//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/higan/phoenix/nall/config.hpp b/higan/phoenix/nall/config.hpp deleted file mode 100644 index 94be7dc1..00000000 --- a/higan/phoenix/nall/config.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - inline string get() const { - switch(type) { - case boolean_t: return { *(bool*)data }; - case signed_t: return { *(signed*)data }; - case unsigned_t: return { *(unsigned*)data }; - case double_t: return { *(double*)data }; - case string_t: return { "\"", *(string*)data, "\"" }; - } - return "???"; - } - - inline void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = integer(s); break; - case unsigned_t: *(unsigned*)data = decimal(s); break; - case double_t: *(double*)data = fp(s); break; - case string_t: s.trim("\""); *(string*)data = s; break; - } - } - }; - vector list; - - template - inline void append(T &data, const char *name, const char *desc = "") { - item_t item = { (uintptr_t)&data, name, desc }; - if(configuration_traits::is_boolean::value) item.type = boolean_t; - else if(configuration_traits::is_signed::value) item.type = signed_t; - else if(configuration_traits::is_unsigned::value) item.type = unsigned_t; - else if(configuration_traits::is_double::value) item.type = double_t; - else if(configuration_traits::is_string::value) item.type = string_t; - else item.type = unknown_t; - list.append(item); - } - - //deprecated - template - inline void attach(T &data, const char *name, const char *desc = "") { - append(data, name, desc); - } - - inline virtual bool load(const string &filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0; - if(!qstrpos(line[i], " = ")) continue; - - lstring part; - part.qsplit(" = ", line[i]); - part[0].trim(); - part[1].trim(); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - inline virtual bool save(const string &filename) const { - file fp; - if(fp.open(filename, file::mode::write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output.append(list[i].name, " = ", list[i].get()); - if(list[i].desc != "") output.append(" # ", list[i].desc); - output.append("\r\n"); - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/higan/phoenix/nall/crc16.hpp b/higan/phoenix/nall/crc16.hpp deleted file mode 100644 index cd6e72fd..00000000 --- a/higan/phoenix/nall/crc16.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef NALL_CRC16_HPP -#define NALL_CRC16_HPP - -#include - -namespace nall { - inline uint16_t crc16_adjust(uint16_t crc16, uint8_t data) { - for(unsigned n = 0; n < 8; n++) { - if((crc16 & 1) ^ (data & 1)) crc16 = (crc16 >> 1) ^ 0x8408; - else crc16 >>= 1; - data >>= 1; - } - return crc16; - } - - inline uint16_t crc16_calculate(const uint8_t *data, unsigned length) { - uint16_t crc16 = ~0; - for(unsigned n = 0; n < length; n++) { - crc16 = crc16_adjust(crc16, data[n]); - } - return ~crc16; - } -} - -#endif diff --git a/higan/phoenix/nall/crc32.hpp b/higan/phoenix/nall/crc32.hpp deleted file mode 100644 index ad36fbf6..00000000 --- a/higan/phoenix/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/higan/phoenix/nall/directory.hpp b/higan/phoenix/nall/directory.hpp deleted file mode 100644 index 5617ee4e..00000000 --- a/higan/phoenix/nall/directory.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef NALL_DIRECTORY_HPP -#define NALL_DIRECTORY_HPP - -#include -#include -#include -#include -#include - -#if defined(PLATFORM_WINDOWS) - #include -#else - #include - #include - #include -#endif - -namespace nall { - -struct directory { - static bool create(const string &pathname, unsigned permissions = 0755); //recursive - static bool remove(const string &pathname); //recursive - static bool exists(const string &pathname); - - static lstring folders(const string &pathname, const string &pattern = "*") { - lstring folders = directory::ufolders(pathname, pattern); - folders.sort(); - return folders; - } - - static lstring files(const string &pathname, const string &pattern = "*") { - lstring files = directory::ufiles(pathname, pattern); - files.sort(); - return files; - } - - static lstring contents(const string &pathname, const string &pattern = "*") { - lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files - lstring files = directory::ufiles(pathname, pattern); - folders.sort(); - files.sort(); - for(auto &file : files) folders.append(file); - return folders; - } - - static lstring ifolders(const string &pathname, const string &pattern = "*") { - lstring folders = ufolders(pathname, pattern); - folders.isort(); - return folders; - } - - static lstring ifiles(const string &pathname, const string &pattern = "*") { - lstring files = ufiles(pathname, pattern); - files.isort(); - return files; - } - - static lstring icontents(const string &pathname, const string &pattern = "*") { - lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files - lstring files = directory::ufiles(pathname, pattern); - folders.isort(); - files.isort(); - for(auto &file : files) folders.append(file); - return folders; - } - -private: - //internal functions; these return unsorted lists - static lstring ufolders(const string &pathname, const string &pattern = "*"); - static lstring ufiles(const string &pathname, const string &pattern = "*"); -}; - -#if defined(PLATFORM_WINDOWS) - inline bool directory::create(const string &pathname, unsigned permissions) { - string path; - lstring list = string{pathname}.transform("\\", "/").rtrim<1>("/").split("/"); - bool result = true; - for(auto &part : list) { - path.append(part, "/"); - result &= (_wmkdir(utf16_t(path)) == 0); - } - return result; - } - - inline bool directory::remove(const string &pathname) { - lstring list = directory::contents(pathname); - for(auto &name : list) { - if(name.endswith("/")) directory::remove({pathname, name}); - else file::remove({pathname, name}); - } - return _wrmdir(utf16_t(pathname)) == 0; - } - - inline bool directory::exists(const string &pathname) { - string name = pathname; - name.trim<1>("\""); - DWORD result = GetFileAttributes(utf16_t(name)); - if(result == INVALID_FILE_ATTRIBUTES) return false; - return (result & FILE_ATTRIBUTE_DIRECTORY); - } - - inline lstring directory::ufolders(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - while(FindNextFile(handle, &data) != false) { - if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) { - if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - } - FindClose(handle); - } - for(auto &name : list) name.append("/"); //must append after sorting - return list; - } - - inline lstring directory::ufiles(const string &pathname, const string &pattern) { - lstring list; - string path = pathname; - path.transform("/", "\\"); - if(!strend(path, "\\")) path.append("\\"); - path.append("*"); - HANDLE handle; - WIN32_FIND_DATA data; - handle = FindFirstFile(utf16_t(path), &data); - if(handle != INVALID_HANDLE_VALUE) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - while(FindNextFile(handle, &data) != false) { - if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { - string name = (const char*)utf8_t(data.cFileName); - if(wildcard(name, pattern)) list.append(name); - } - } - FindClose(handle); - } - return list; - } -#else - inline bool directory::create(const string &pathname, unsigned permissions) { - string path; - lstring list = string{pathname}.rtrim<1>("/").split("/"); - bool result = true; - for(auto &part : list) { - path.append(part, "/"); - result &= (mkdir(path, permissions) == 0); - } - return result; - } - - inline bool directory::remove(const string &pathname) { - lstring list = directory::contents(pathname); - for(auto &name : list) { - if(name.endswith("/")) directory::remove({pathname, name}); - else file::remove({pathname, name}); - } - return rmdir(pathname) == 0; - } - - inline bool directory::exists(const string &pathname) { - DIR *dp = opendir(pathname); - if(!dp) return false; - closedir(dp); - return true; - } - - inline lstring directory::ufolders(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if(ep->d_type & DT_DIR) { - if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); - } - } - closedir(dp); - } - for(auto &name : list) name.append("/"); //must append after sorting - return list; - } - - inline lstring directory::ufiles(const string &pathname, const string &pattern) { - lstring list; - DIR *dp; - struct dirent *ep; - dp = opendir(pathname); - if(dp) { - while(ep = readdir(dp)) { - if(!strcmp(ep->d_name, ".")) continue; - if(!strcmp(ep->d_name, "..")) continue; - if((ep->d_type & DT_DIR) == 0) { - if(wildcard(ep->d_name, pattern)) list.append(ep->d_name); - } - } - closedir(dp); - } - return list; - } -#endif - -} - -#endif diff --git a/higan/phoenix/nall/dl.hpp b/higan/phoenix/nall/dl.hpp deleted file mode 100644 index 4732918c..00000000 --- a/higan/phoenix/nall/dl.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WINDOWS) - #include - #include -#endif - -namespace nall { - struct library { - explicit operator bool() const { return open(); } - bool open() const { return handle; } - bool open(const char*, const char* = ""); - bool open_absolute(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return nullptr; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY); - if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)dlopen(name, RTLD_LAZY); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return nullptr; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WINDOWS) - inline bool library::open(const char *name, const char *path) { - if(handle) close(); - string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(filepath)); - return handle; - } - - inline bool library::open_absolute(const char *name) { - if(handle) close(); - handle = (uintptr_t)LoadLibraryW(utf16_t(name)); - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return nullptr; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*, const char*) { return false; } - inline bool library::open_absolute(const char*) { return false; } - inline void* library::sym(const char*) { return nullptr; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/higan/phoenix/nall/dsp.hpp b/higan/phoenix/nall/dsp.hpp deleted file mode 100644 index a2400ec7..00000000 --- a/higan/phoenix/nall/dsp.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef NALL_DSP_HPP -#define NALL_DSP_HPP - -#include -#ifdef __SSE__ - #include -#endif - -#define NALL_DSP_INTERNAL_HPP -#include -#undef NALL_DSP_INTERNAL_HPP - -#endif diff --git a/higan/phoenix/nall/dsp/buffer.hpp b/higan/phoenix/nall/dsp/buffer.hpp deleted file mode 100644 index 19bc561d..00000000 --- a/higan/phoenix/nall/dsp/buffer.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct Buffer { - double **sample = nullptr; - uint16_t rdoffset = 0; - uint16_t wroffset = 0; - unsigned channels = 0; - - void setChannels(unsigned channels) { - if(sample) { - for(unsigned c = 0; c < this->channels; c++) { - if(sample[c]) delete[] sample[c]; - } - delete[] sample; - } - - this->channels = channels; - if(channels == 0) return; - - sample = new double*[channels]; - for(unsigned c = 0; c < channels; c++) { - sample[c] = new double[65536](); - } - } - - inline double& read(unsigned channel, signed offset = 0) { - return sample[channel][(uint16_t)(rdoffset + offset)]; - } - - inline double& write(unsigned channel, signed offset = 0) { - return sample[channel][(uint16_t)(wroffset + offset)]; - } - - inline void clear() { - for(unsigned c = 0; c < channels; c++) { - for(unsigned n = 0; n < 65536; n++) { - sample[c][n] = 0; - } - } - rdoffset = 0; - wroffset = 0; - } - - Buffer() { - } - - ~Buffer() { - setChannels(0); - } -}; - -#endif diff --git a/higan/phoenix/nall/dsp/core.hpp b/higan/phoenix/nall/dsp/core.hpp deleted file mode 100644 index 969b60d1..00000000 --- a/higan/phoenix/nall/dsp/core.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -#include -#include -#include - -namespace nall { - -//precision: can be float, double or long double -#define real float - -struct DSP; - -struct Resampler { - DSP &dsp; - real frequency; - - virtual void setFrequency() = 0; - virtual void clear() = 0; - virtual void sample() = 0; - Resampler(DSP &dsp) : dsp(dsp) {} -}; - -struct DSP { - enum class ResampleEngine : unsigned { - Nearest, - Linear, - Cosine, - Cubic, - Hermite, - Average, - Sinc, - }; - - inline void setChannels(unsigned channels); - inline void setPrecision(unsigned precision); - inline void setFrequency(real frequency); //inputFrequency - inline void setVolume(real volume); - inline void setBalance(real balance); - - inline void setResampler(ResampleEngine resamplingEngine); - inline void setResamplerFrequency(real frequency); //outputFrequency - - inline void sample(signed channel[]); - inline bool pending(); - inline void read(signed channel[]); - - inline void clear(); - inline DSP(); - inline ~DSP(); - -protected: - friend class ResampleNearest; - friend class ResampleLinear; - friend class ResampleCosine; - friend class ResampleCubic; - friend class ResampleAverage; - friend class ResampleHermite; - friend class ResampleSinc; - - struct Settings { - unsigned channels; - unsigned precision; - real frequency; - real volume; - real balance; - - //internal - real intensity; - real intensityInverse; - } settings; - - Resampler *resampler = nullptr; - inline void write(real channel[]); - - #include "buffer.hpp" - Buffer buffer; - Buffer output; - - inline void adjustVolume(); - inline void adjustBalance(); - inline signed clamp(const unsigned bits, const signed x); -}; - -#include "resample/nearest.hpp" -#include "resample/linear.hpp" -#include "resample/cosine.hpp" -#include "resample/cubic.hpp" -#include "resample/hermite.hpp" -#include "resample/average.hpp" -#include "resample/sinc.hpp" -#include "settings.hpp" - -void DSP::sample(signed channel[]) { - for(unsigned c = 0; c < settings.channels; c++) { - buffer.write(c) = (real)channel[c] * settings.intensityInverse; - } - buffer.wroffset++; - resampler->sample(); -} - -bool DSP::pending() { - return output.rdoffset != output.wroffset; -} - -void DSP::read(signed channel[]) { - adjustVolume(); - adjustBalance(); - - for(unsigned c = 0; c < settings.channels; c++) { - channel[c] = clamp(settings.precision, output.read(c) * settings.intensity); - } - output.rdoffset++; -} - -void DSP::write(real channel[]) { - for(unsigned c = 0; c < settings.channels; c++) { - output.write(c) = channel[c]; - } - output.wroffset++; -} - -void DSP::adjustVolume() { - for(unsigned c = 0; c < settings.channels; c++) { - output.read(c) *= settings.volume; - } -} - -void DSP::adjustBalance() { - if(settings.channels != 2) return; //TODO: support > 2 channels - if(settings.balance < 0.0) output.read(1) *= 1.0 + settings.balance; - if(settings.balance > 0.0) output.read(0) *= 1.0 - settings.balance; -} - -signed DSP::clamp(const unsigned bits, const signed x) { - const signed b = 1U << (bits - 1); - const signed m = (1U << (bits - 1)) - 1; - return (x > m) ? m : (x < -b) ? -b : x; -} - -void DSP::clear() { - buffer.clear(); - output.clear(); - resampler->clear(); -} - -DSP::DSP() { - setResampler(ResampleEngine::Hermite); - setResamplerFrequency(44100.0); - - setChannels(2); - setPrecision(16); - setFrequency(44100.0); - setVolume(1.0); - setBalance(0.0); - - clear(); -} - -DSP::~DSP() { - if(resampler) delete resampler; -} - -#undef real - -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/average.hpp b/higan/phoenix/nall/dsp/resample/average.hpp deleted file mode 100644 index 867b13bf..00000000 --- a/higan/phoenix/nall/dsp/resample/average.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleAverage : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - inline void sampleLinear(); - ResampleAverage(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleAverage::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleAverage::clear() { - fraction = 0.0; -} - -void ResampleAverage::sample() { - //can only average if input frequency >= output frequency - if(step < 1.0) return sampleLinear(); - - fraction += 1.0; - - real scalar = 1.0; - if(fraction > step) scalar = 1.0 - (fraction - step); - - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) += dsp.buffer.read(c) * scalar; - } - - if(fraction >= step) { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) /= step; - } - dsp.output.wroffset++; - - fraction -= step; - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) = dsp.buffer.read(c) * fraction; - } - } - - dsp.buffer.rdoffset++; -} - -void ResampleAverage::sampleLinear() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/cosine.hpp b/higan/phoenix/nall/dsp/resample/cosine.hpp deleted file mode 100644 index 3363d5f6..00000000 --- a/higan/phoenix/nall/dsp/resample/cosine.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleCosine : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleCosine(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleCosine::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleCosine::clear() { - fraction = 0.0; -} - -void ResampleCosine::sample() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - mu = (1.0 - cos(mu * 3.14159265)) / 2.0; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/cubic.hpp b/higan/phoenix/nall/dsp/resample/cubic.hpp deleted file mode 100644 index bc4cc955..00000000 --- a/higan/phoenix/nall/dsp/resample/cubic.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleCubic : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleCubic(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleCubic::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleCubic::clear() { - fraction = 0.0; -} - -void ResampleCubic::sample() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -3); - real b = dsp.buffer.read(n, -2); - real c = dsp.buffer.read(n, -1); - real d = dsp.buffer.read(n, -0); - - real mu = fraction; - - real A = d - c - a + b; - real B = a - b - A; - real C = c - a; - real D = b; - - channel[n] = A * (mu * 3) + B * (mu * 2) + C * mu + D; - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/hermite.hpp b/higan/phoenix/nall/dsp/resample/hermite.hpp deleted file mode 100644 index 0cc9ba0e..00000000 --- a/higan/phoenix/nall/dsp/resample/hermite.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleHermite : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleHermite(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleHermite::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleHermite::clear() { - fraction = 0.0; -} - -void ResampleHermite::sample() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -3); - real b = dsp.buffer.read(n, -2); - real c = dsp.buffer.read(n, -1); - real d = dsp.buffer.read(n, -0); - - const real tension = 0.0; //-1 = low, 0 = normal, +1 = high - const real bias = 0.0; //-1 = left, 0 = even, +1 = right - - real mu1, mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu1 = fraction; - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; - m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; - m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; - m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - channel[n] = (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/lib/sinc.hpp b/higan/phoenix/nall/dsp/resample/lib/sinc.hpp deleted file mode 100644 index 67c793d6..00000000 --- a/higan/phoenix/nall/dsp/resample/lib/sinc.hpp +++ /dev/null @@ -1,600 +0,0 @@ -// If these types are changed to anything other than "float", you should comment out the SSE detection directives below -// so that the SSE code is not used. - -typedef float resample_coeff_t; // note: sizeof(resample_coeff_t) must be == to a power of 2, and not larger than 16 -typedef float resample_samp_t; - - -// ...but don't comment this single RESAMPLE_SSEREGPARM define out when disabling SSE. -#define RESAMPLE_SSEREGPARM - -#if defined(__SSE__) - #define SINCRESAMPLE_USE_SSE 1 - #ifndef __x86_64__ - #undef RESAMPLE_SSEREGPARM - #define RESAMPLE_SSEREGPARM __attribute__((sseregparm)) - #endif -#else - // TODO: altivec here -#endif - -namespace ResampleUtility -{ - inline void kaiser_window(double* io, int count, double beta); - inline void gen_sinc(double* out, int size, double cutoff, double kaiser); - inline void gen_sinc_os(double* out, int size, double cutoff, double kaiser); - inline void normalize(double* io, int size, double gain = 1.0); - - inline void* make_aligned(void* ptr, unsigned boundary); // boundary must be a power of 2 -} - -class SincResampleHR -{ - private: - - inline void Init(unsigned ratio_arg, double desired_bandwidth, double beta, double d); - - inline void write(resample_samp_t sample) RESAMPLE_SSEREGPARM; - inline resample_samp_t read(void) RESAMPLE_SSEREGPARM; - inline bool output_avail(void); - - private: - - inline resample_samp_t mac(const resample_samp_t *wave, const resample_coeff_t *coeff, unsigned count); - - unsigned ratio; - unsigned num_convolutions; - - resample_coeff_t *coeffs; - std::vector coeffs_mem; - - // second half of ringbuffer should be copy of first half. - resample_samp_t *rb; - std::vector rb_mem; - - signed rb_readpos; - signed rb_writepos; - signed rb_in; - signed rb_eff_size; - - friend class SincResample; -}; - -class SincResample -{ - public: - - enum - { - QUALITY_LOW = 0, - QUALITY_MEDIUM = 2, - QUALITY_HIGH = 4 - }; - - inline SincResample(double input_rate, double output_rate, double desired_bandwidth, unsigned quality = QUALITY_HIGH); - - inline void write(resample_samp_t sample) RESAMPLE_SSEREGPARM; - inline resample_samp_t read(void) RESAMPLE_SSEREGPARM; - inline bool output_avail(void); - - private: - - inline void Init(double input_rate, double output_rate, double desired_bandwidth, double beta, double d, unsigned pn_nume, unsigned phases_min); - - inline resample_samp_t mac(const resample_samp_t *wave, const resample_coeff_t *coeffs_a, const resample_coeff_t *coeffs_b, const double ffract, unsigned count) RESAMPLE_SSEREGPARM; - - unsigned num_convolutions; - unsigned num_phases; - - unsigned step_int; - double step_fract; - - double input_pos_fract; - - - std::vector coeffs; // Pointers into coeff_mem. - std::vector coeff_mem; - - - std::vector rb; // second half should be copy of first half. - signed rb_readpos; - signed rb_writepos; - signed rb_in; - - bool hr_used; - SincResampleHR hr; -}; - - -// -// Code: -// -//#include "resample.hpp" - -#if 0 -namespace bit -{ - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } -} -#endif - -void SincResampleHR::Init(unsigned ratio_arg, double desired_bandwidth, double beta, double d) -{ - const unsigned align_boundary = 16; - std::vector coeffs_tmp; - double cutoff; // 1.0 = f/2 - - ratio = ratio_arg; - - //num_convolutions = ((unsigned)ceil(d / ((1.0 - desired_bandwidth) / ratio)) + 1) &~ 1; // round up to be even - num_convolutions = ((unsigned)ceil(d / ((1.0 - desired_bandwidth) / ratio)) | 1); - - cutoff = (1.0 / ratio) - (d / num_convolutions); - -//printf("%d %d %.20f\n", ratio, num_convolutions, cutoff); - assert(num_convolutions > ratio); - - - // Generate windowed sinc of POWER - coeffs_tmp.resize(num_convolutions); - //ResampleUtility::gen_sinc(&coeffs_tmp[0], num_convolutions, cutoff, beta); - ResampleUtility::gen_sinc_os(&coeffs_tmp[0], num_convolutions, cutoff, beta); - ResampleUtility::normalize(&coeffs_tmp[0], num_convolutions); - - // Copy from coeffs_tmp to coeffs~ - // We multiply many coefficients at a time in the mac loop, so make sure the last few that don't really - // exist are allocated, zero'd mem. - - coeffs_mem.resize(((num_convolutions + 7) &~ 7) * sizeof(resample_coeff_t) + (align_boundary - 1)); - coeffs = (resample_coeff_t *)ResampleUtility::make_aligned(&coeffs_mem[0], align_boundary); - - - for(unsigned i = 0; i < num_convolutions; i++) - coeffs[i] = coeffs_tmp[i]; - - rb_eff_size = nall::bit::round(num_convolutions * 2) >> 1; - rb_readpos = 0; - rb_writepos = 0; - rb_in = 0; - - rb_mem.resize(rb_eff_size * 2 * sizeof(resample_samp_t) + (align_boundary - 1)); - rb = (resample_samp_t *)ResampleUtility::make_aligned(&rb_mem[0], align_boundary); -} - - -inline bool SincResampleHR::output_avail(void) -{ - return(rb_in >= (signed)num_convolutions); -} - -inline void SincResampleHR::write(resample_samp_t sample) -{ - assert(!output_avail()); - - rb[rb_writepos] = sample; - rb[rb_writepos + rb_eff_size] = sample; - rb_writepos = (rb_writepos + 1) & (rb_eff_size - 1); - rb_in++; -} - -resample_samp_t SincResampleHR::mac(const resample_samp_t *wave, const resample_coeff_t *coeff, unsigned count) -{ -#if SINCRESAMPLE_USE_SSE - __m128 accum_veca[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - - resample_samp_t accum; - - for(unsigned c = 0; c < count; c += 8) - { - for(unsigned i = 0; i < 2; i++) - { - __m128 co[2]; - __m128 w[2]; - - co[i] = _mm_load_ps(&coeff[c + i * 4]); - w[i] = _mm_load_ps(&wave[c + i * 4]); - - w[i] = _mm_mul_ps(w[i], co[i]); - - accum_veca[i] = _mm_add_ps(w[i], accum_veca[i]); - } - } - - __m128 accum_vec = _mm_add_ps(accum_veca[0], accum_veca[1]); //_mm_add_ps(_mm_add_ps(accum_veca[0], accum_veca[1]), _mm_add_ps(accum_veca[2], accum_veca[3])); - - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (1 << 0) | (0 << 2) | (1 << 4) | (0 << 6))); - - _mm_store_ss(&accum, accum_vec); - - return accum; -#else - resample_samp_t accum[4] = { 0, 0, 0, 0 }; - - for(unsigned c = 0; c < count; c+= 4) - { - accum[0] += wave[c + 0] * coeff[c + 0]; - accum[1] += wave[c + 1] * coeff[c + 1]; - accum[2] += wave[c + 2] * coeff[c + 2]; - accum[3] += wave[c + 3] * coeff[c + 3]; - } - - return (accum[0] + accum[1]) + (accum[2] + accum[3]); // don't mess with parentheses(assuming compiler doesn't already, which it may... - -#endif -} - - -resample_samp_t SincResampleHR::read(void) -{ - assert(output_avail()); - resample_samp_t ret; - - ret = mac(&rb[rb_readpos], &coeffs[0], num_convolutions); - - rb_readpos = (rb_readpos + ratio) & (rb_eff_size - 1); - rb_in -= ratio; - - return ret; -} - - -SincResample::SincResample(double input_rate, double output_rate, double desired_bandwidth, unsigned quality) -{ - const struct - { - double beta; - double d; - unsigned pn_nume; - unsigned phases_min; - } qtab[5] = - { - { 5.658, 3.62, 4096, 4 }, - { 6.764, 4.32, 8192, 4 }, - { 7.865, 5.0, 16384, 8 }, - { 8.960, 5.7, 32768, 16 }, - { 10.056, 6.4, 65536, 32 } - }; - - // Sanity checks - assert(ceil(input_rate) > 0); - assert(ceil(output_rate) > 0); - assert(ceil(input_rate / output_rate) <= 1024); - assert(ceil(output_rate / input_rate) <= 1024); - - // The simplistic number-of-phases calculation code doesn't work well enough for when desired_bandwidth is close to 1.0 and when - // upsampling. - assert(desired_bandwidth >= 0.25 && desired_bandwidth < 0.96); - assert(quality >= 0 && quality <= 4); - - hr_used = false; - -#if 1 - // Round down to the nearest multiple of 4(so wave buffer remains aligned) - // It also adjusts the effective intermediate sampling rate up slightly, so that the upper frequencies below f/2 - // aren't overly attenuated so much. In the future, we might want to do an FFT or something to choose the intermediate rate more accurately - // to virtually eliminate over-attenuation. - unsigned ioratio_rd = (unsigned)floor(input_rate / (output_rate * (1.0 + (1.0 - desired_bandwidth) / 2) )) & ~3; - - if(ioratio_rd >= 8) - { - hr.Init(ioratio_rd, desired_bandwidth, qtab[quality].beta, qtab[quality].d); //10.056, 6.4); - hr_used = true; - - input_rate /= ioratio_rd; - } -#endif - - Init(input_rate, output_rate, desired_bandwidth, qtab[quality].beta, qtab[quality].d, qtab[quality].pn_nume, qtab[quality].phases_min); -} - -void SincResample::Init(double input_rate, double output_rate, double desired_bandwidth, double beta, double d, unsigned pn_nume, unsigned phases_min) -{ - const unsigned max_mult_atatime = 8; // multiply "granularity". must be power of 2. - const unsigned max_mult_minus1 = (max_mult_atatime - 1); - const unsigned conv_alignment_bytes = 16; // must be power of 2 - const double input_to_output_ratio = input_rate / output_rate; - const double output_to_input_ratio = output_rate / input_rate; - double cutoff; // 1.0 = input_rate / 2 - std::vector coeff_init_buffer; - - // Round up num_convolutions to be even. - if(output_rate > input_rate) - num_convolutions = ((unsigned)ceil(d / (1.0 - desired_bandwidth)) + 1) & ~1; - else - num_convolutions = ((unsigned)ceil(d / (output_to_input_ratio * (1.0 - desired_bandwidth))) + 1) & ~1; - - if(output_rate > input_rate) // Upsampling - cutoff = desired_bandwidth; - else // Downsampling - cutoff = output_to_input_ratio * desired_bandwidth; - - // Round up to be even. - num_phases = (std::max(pn_nume / num_convolutions, phases_min) + 1) &~1; - - // Adjust cutoff to account for the multiple phases. - cutoff = cutoff / num_phases; - - assert((num_convolutions & 1) == 0); - assert((num_phases & 1) == 0); - -// fprintf(stderr, "num_convolutions=%u, num_phases=%u, total expected coeff byte size=%lu\n", num_convolutions, num_phases, -// (long)((num_phases + 2) * ((num_convolutions + max_mult_minus1) & ~max_mult_minus1) * sizeof(float) + conv_alignment_bytes)); - - coeff_init_buffer.resize(num_phases * num_convolutions); - - coeffs.resize(num_phases + 1 + 1); - - coeff_mem.resize((num_phases + 1 + 1) * ((num_convolutions + max_mult_minus1) &~ max_mult_minus1) * sizeof(resample_coeff_t) + conv_alignment_bytes); - - // Assign aligned pointers into coeff_mem - { - resample_coeff_t *base_ptr = (resample_coeff_t *)ResampleUtility::make_aligned(&coeff_mem[0], conv_alignment_bytes); - - for(unsigned phase = 0; phase < (num_phases + 1 + 1); phase++) - { - coeffs[phase] = base_ptr + (((num_convolutions + max_mult_minus1) & ~max_mult_minus1) * phase); - } - } - - ResampleUtility::gen_sinc(&coeff_init_buffer[0], num_phases * num_convolutions, cutoff, beta); - ResampleUtility::normalize(&coeff_init_buffer[0], num_phases * num_convolutions, num_phases); - - // Reorder coefficients to allow for more efficient convolution. - for(int phase = -1; phase < ((int)num_phases + 1); phase++) - { - for(int conv = 0; conv < (int)num_convolutions; conv++) - { - double coeff; - - if(phase == -1 && conv == 0) - coeff = 0; - else if(phase == (int)num_phases && conv == ((int)num_convolutions - 1)) - coeff = 0; - else - coeff = coeff_init_buffer[conv * num_phases + phase]; - - coeffs[phase + 1][conv] = coeff; - } - } - - // Free a bit of mem - coeff_init_buffer.resize(0); - - step_int = floor(input_to_output_ratio); - step_fract = input_to_output_ratio - step_int; - - input_pos_fract = 0; - - // Do NOT use rb.size() later in the code, since it'll include the padding. - // We should only need one "max_mult_minus1" here, not two, since it won't matter if it over-reads(due to doing "max_mult_atatime" multiplications at a time - // rather than just 1, in which case this over-read wouldn't happen), from the first half into the duplicated half, - // since those corresponding coefficients will be zero anyway; this is just to handle the case of reading off the end of the duplicated half to - // prevent illegal memory accesses. - rb.resize(num_convolutions * 2 + max_mult_minus1); - - rb_readpos = 0; - rb_writepos = 0; - rb_in = 0; -} - -resample_samp_t SincResample::mac(const resample_samp_t *wave, const resample_coeff_t *coeffs_a, const resample_coeff_t *coeffs_b, const double ffract, unsigned count) -{ - resample_samp_t accum = 0; -#if SINCRESAMPLE_USE_SSE - __m128 accum_vec_a[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - __m128 accum_vec_b[2] = { _mm_set1_ps(0), _mm_set1_ps(0) }; - - for(unsigned c = 0; c < count; c += 8) //8) //4) - { - __m128 coeff_a[2]; - __m128 coeff_b[2]; - __m128 w[2]; - __m128 result_a[2], result_b[2]; - - for(unsigned i = 0; i < 2; i++) - { - coeff_a[i] = _mm_load_ps(&coeffs_a[c + (i * 4)]); - coeff_b[i] = _mm_load_ps(&coeffs_b[c + (i * 4)]); - w[i] = _mm_loadu_ps(&wave[c + (i * 4)]); - - result_a[i] = _mm_mul_ps(coeff_a[i], w[i]); - result_b[i] = _mm_mul_ps(coeff_b[i], w[i]); - - accum_vec_a[i] = _mm_add_ps(result_a[i], accum_vec_a[i]); - accum_vec_b[i] = _mm_add_ps(result_b[i], accum_vec_b[i]); - } - } - - __m128 accum_vec, av_a, av_b; - __m128 mult_a_vec = _mm_set1_ps(1.0 - ffract); - __m128 mult_b_vec = _mm_set1_ps(ffract); - - av_a = _mm_mul_ps(mult_a_vec, /*accum_vec_a[0]);*/ _mm_add_ps(accum_vec_a[0], accum_vec_a[1])); - av_b = _mm_mul_ps(mult_b_vec, /*accum_vec_b[0]);*/ _mm_add_ps(accum_vec_b[0], accum_vec_b[1])); - - accum_vec = _mm_add_ps(av_a, av_b); - - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (3 << 0) | (2 << 2) | (1 << 4) | (0 << 6))); - accum_vec = _mm_add_ps(accum_vec, _mm_shuffle_ps(accum_vec, accum_vec, (1 << 0) | (0 << 2) | (1 << 4) | (0 << 6))); - - _mm_store_ss(&accum, accum_vec); -#else - resample_coeff_t mult_a = 1.0 - ffract; - resample_coeff_t mult_b = ffract; - - for(unsigned c = 0; c < count; c += 4) - { - accum += wave[c + 0] * (coeffs_a[c + 0] * mult_a + coeffs_b[c + 0] * mult_b); - accum += wave[c + 1] * (coeffs_a[c + 1] * mult_a + coeffs_b[c + 1] * mult_b); - accum += wave[c + 2] * (coeffs_a[c + 2] * mult_a + coeffs_b[c + 2] * mult_b); - accum += wave[c + 3] * (coeffs_a[c + 3] * mult_a + coeffs_b[c + 3] * mult_b); - } -#endif - - return accum; -} - -inline bool SincResample::output_avail(void) -{ - return(rb_in >= (int)num_convolutions); -} - -resample_samp_t SincResample::read(void) -{ - assert(output_avail()); - double phase = input_pos_fract * num_phases - 0.5; - signed phase_int = (signed)floor(phase); - double phase_fract = phase - phase_int; - unsigned phase_a = num_phases - 1 - phase_int; - unsigned phase_b = phase_a - 1; - resample_samp_t ret; - - ret = mac(&rb[rb_readpos], &coeffs[phase_a + 1][0], &coeffs[phase_b + 1][0], phase_fract, num_convolutions); - - unsigned int_increment = step_int; - - input_pos_fract += step_fract; - int_increment += floor(input_pos_fract); - input_pos_fract -= floor(input_pos_fract); - - rb_readpos = (rb_readpos + int_increment) % num_convolutions; - rb_in -= int_increment; - - return ret; -} - -inline void SincResample::write(resample_samp_t sample) -{ - assert(!output_avail()); - - if(hr_used) - { - hr.write(sample); - - if(hr.output_avail()) - { - sample = hr.read(); - } - else - { - return; - } - } - - rb[rb_writepos + 0 * num_convolutions] = sample; - rb[rb_writepos + 1 * num_convolutions] = sample; - rb_writepos = (rb_writepos + 1) % num_convolutions; - rb_in++; -} - -void ResampleUtility::kaiser_window( double* io, int count, double beta) -{ - int const accuracy = 24; //16; //12; - - double* end = io + count; - - double beta2 = beta * beta * (double) -0.25; - double to_fract = beta2 / ((double) count * count); - double i = 0; - double rescale = 0; // Doesn't need an initializer, to shut up gcc - - for ( ; io < end; ++io, i += 1 ) - { - double x = i * i * to_fract - beta2; - double u = x; - double k = x + 1; - - double n = 2; - do - { - u *= x / (n * n); - n += 1; - k += u; - } - while ( k <= u * (1 << accuracy) ); - - if ( !i ) - rescale = 1 / k; // otherwise values get large - - *io *= k * rescale; - } -} - -void ResampleUtility::gen_sinc(double* out, int size, double cutoff, double kaiser) -{ - assert( size % 2 == 0 ); // size must be even - - int const half_size = size / 2; - double* const mid = &out [half_size]; - - // Generate right half of sinc - for ( int i = 0; i < half_size; i++ ) - { - double angle = (i * 2 + 1) * (M_PI / 2); - mid [i] = sin( angle * cutoff ) / angle; - } - - kaiser_window( mid, half_size, kaiser ); - - // Mirror for left half - for ( int i = 0; i < half_size; i++ ) - out [i] = mid [half_size - 1 - i]; -} - -void ResampleUtility::gen_sinc_os(double* out, int size, double cutoff, double kaiser) -{ - assert( size % 2 == 1); // size must be odd - - for(int i = 0; i < size; i++) - { - if(i == (size / 2)) - out[i] = 2 * M_PI * (cutoff / 2); //0.078478; //1.0; //sin(2 * M_PI * (cutoff / 2) * (i - size / 2)) / (i - (size / 2)); - else - out[i] = sin(2 * M_PI * (cutoff / 2) * (i - size / 2)) / (i - (size / 2)); - -// out[i] *= 0.3635819 - 0.4891775 * cos(2 * M_PI * i / (size - 1)) + 0.1365995 * cos(4 * M_PI * i / (size - 1)) - 0.0106411 * cos(6 * M_PI * i / (size - 1)); -//0.42 - 0.5 * cos(2 * M_PI * i / (size - 1)) + 0.08 * cos(4 * M_PI * i / (size - 1)); - -// printf("%d %f\n", i, out[i]); - } - - kaiser_window(&out[size / 2], size / 2 + 1, kaiser); - - // Mirror for left half - for ( int i = 0; i < size / 2; i++ ) - out [i] = out [size - 1 - i]; - -} - -void ResampleUtility::normalize(double* io, int size, double gain) -{ - double sum = 0; - for ( int i = 0; i < size; i++ ) - sum += io [i]; - - double scale = gain / sum; - for ( int i = 0; i < size; i++ ) - io [i] *= scale; -} - -void* ResampleUtility::make_aligned(void* ptr, unsigned boundary) -{ - unsigned char* null_ptr = (unsigned char *)nullptr; - unsigned char* uc_ptr = (unsigned char *)ptr; - - uc_ptr += (boundary - ((uc_ptr - null_ptr) & (boundary - 1))) & (boundary - 1); - - //while((uc_ptr - null_ptr) & (boundary - 1)) - // uc_ptr++; - - //printf("%16llx %16llx\n", (unsigned long long)ptr, (unsigned long long)uc_ptr); - - assert((uc_ptr - (unsigned char *)ptr) < boundary && (uc_ptr >= (unsigned char *)ptr)); - - return uc_ptr; -} diff --git a/higan/phoenix/nall/dsp/resample/linear.hpp b/higan/phoenix/nall/dsp/resample/linear.hpp deleted file mode 100644 index 3c2dc9e6..00000000 --- a/higan/phoenix/nall/dsp/resample/linear.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleLinear : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleLinear(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleLinear::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleLinear::clear() { - fraction = 0.0; -} - -void ResampleLinear::sample() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = a * (1.0 - mu) + b * mu; - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/nearest.hpp b/higan/phoenix/nall/dsp/resample/nearest.hpp deleted file mode 100644 index 14b401eb..00000000 --- a/higan/phoenix/nall/dsp/resample/nearest.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -struct ResampleNearest : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - ResampleNearest(DSP &dsp) : Resampler(dsp) {} - - real fraction; - real step; -}; - -void ResampleNearest::setFrequency() { - fraction = 0.0; - step = dsp.settings.frequency / frequency; -} - -void ResampleNearest::clear() { - fraction = 0.0; -} - -void ResampleNearest::sample() { - while(fraction <= 1.0) { - real channel[dsp.settings.channels]; - - for(unsigned n = 0; n < dsp.settings.channels; n++) { - real a = dsp.buffer.read(n, -1); - real b = dsp.buffer.read(n, -0); - - real mu = fraction; - - channel[n] = mu < 0.5 ? a : b; - } - - dsp.write(channel); - fraction += step; - } - - dsp.buffer.rdoffset++; - fraction -= 1.0; -} - -#endif diff --git a/higan/phoenix/nall/dsp/resample/sinc.hpp b/higan/phoenix/nall/dsp/resample/sinc.hpp deleted file mode 100644 index 64e247eb..00000000 --- a/higan/phoenix/nall/dsp/resample/sinc.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -#include "lib/sinc.hpp" - -struct ResampleSinc : Resampler { - inline void setFrequency(); - inline void clear(); - inline void sample(); - inline ResampleSinc(DSP &dsp); - -private: - inline void remakeSinc(); - SincResample *sinc_resampler[8]; -}; - -void ResampleSinc::setFrequency() { - remakeSinc(); -} - -void ResampleSinc::clear() { - remakeSinc(); -} - -void ResampleSinc::sample() { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - sinc_resampler[c]->write(dsp.buffer.read(c)); - } - - if(sinc_resampler[0]->output_avail()) { - do { - for(unsigned c = 0; c < dsp.settings.channels; c++) { - dsp.output.write(c) = sinc_resampler[c]->read(); - } - dsp.output.wroffset++; - } while(sinc_resampler[0]->output_avail()); - } - - dsp.buffer.rdoffset++; -} - -ResampleSinc::ResampleSinc(DSP &dsp) : Resampler(dsp) { - for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = nullptr; -} - -void ResampleSinc::remakeSinc() { - assert(dsp.settings.channels < 8); - - for(unsigned c = 0; c < dsp.settings.channels; c++) { - if(sinc_resampler[c]) delete sinc_resampler[c]; - sinc_resampler[c] = new SincResample(dsp.settings.frequency, frequency, 0.85, SincResample::QUALITY_HIGH); - } -} - -#endif diff --git a/higan/phoenix/nall/dsp/settings.hpp b/higan/phoenix/nall/dsp/settings.hpp deleted file mode 100644 index 3a8f24c6..00000000 --- a/higan/phoenix/nall/dsp/settings.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifdef NALL_DSP_INTERNAL_HPP - -void DSP::setChannels(unsigned channels) { - assert(channels > 0); - buffer.setChannels(channels); - output.setChannels(channels); - settings.channels = channels; -} - -void DSP::setPrecision(unsigned precision) { - settings.precision = precision; - settings.intensity = 1 << (settings.precision - 1); - settings.intensityInverse = 1.0 / settings.intensity; -} - -void DSP::setFrequency(real frequency) { - settings.frequency = frequency; - resampler->setFrequency(); -} - -void DSP::setVolume(real volume) { - settings.volume = volume; -} - -void DSP::setBalance(real balance) { - settings.balance = balance; -} - -void DSP::setResampler(ResampleEngine engine) { - if(resampler) delete resampler; - - switch(engine) { - case ResampleEngine::Nearest: resampler = new ResampleNearest(*this); return; - case ResampleEngine::Linear: resampler = new ResampleLinear (*this); return; - case ResampleEngine::Cosine: resampler = new ResampleCosine (*this); return; - case ResampleEngine::Cubic: resampler = new ResampleCubic (*this); return; - case ResampleEngine::Hermite: resampler = new ResampleHermite(*this); return; - case ResampleEngine::Average: resampler = new ResampleAverage(*this); return; - case ResampleEngine::Sinc: resampler = new ResampleSinc (*this); return; - } - - throw; -} - -void DSP::setResamplerFrequency(real frequency) { - resampler->frequency = frequency; - resampler->setFrequency(); -} - -#endif diff --git a/higan/phoenix/nall/emulation/super-famicom-usart.hpp b/higan/phoenix/nall/emulation/super-famicom-usart.hpp deleted file mode 100644 index 68dea605..00000000 --- a/higan/phoenix/nall/emulation/super-famicom-usart.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_EMULATION_SUPER_FAMICOM_USART_HPP -#define NALL_EMULATION_SUPER_FAMICOM_USART_HPP - -#include -#include -#include -#include - -#include -#include -#include - -#define usartproc dllexport - -static nall::function usart_quit; -static nall::function usart_usleep; -static nall::function usart_readable; -static nall::function usart_read; -static nall::function usart_writable; -static nall::function usart_write; - -extern "C" usartproc void usart_init( - nall::function quit, - nall::function usleep, - nall::function readable, - nall::function read, - nall::function writable, - nall::function write -) { - usart_quit = quit; - usart_usleep = usleep; - usart_readable = readable; - usart_read = read; - usart_writable = writable; - usart_write = write; -} - -extern "C" usartproc void usart_main(int, char**); - -// - -static nall::serial usart; -static bool usart_is_virtual = true; -static bool usart_sigint = false; - -static bool usart_virtual() { - return usart_is_virtual; -} - -// - -static bool usarthw_quit() { - return usart_sigint; -} - -static void usarthw_usleep(unsigned milliseconds) { - usleep(milliseconds); -} - -static bool usarthw_readable() { - return usart.readable(); -} - -static uint8_t usarthw_read() { - while(true) { - uint8_t buffer[1]; - signed length = usart.read((uint8_t*)&buffer, 1); - if(length > 0) return buffer[0]; - } -} - -static bool usarthw_writable() { - return usart.writable(); -} - -static void usarthw_write(uint8_t data) { - uint8_t buffer[1] = { data }; - usart.write((uint8_t*)&buffer, 1); -} - -static void sigint(int) { - signal(SIGINT, SIG_DFL); - usart_sigint = true; -} - -int main(int argc, char **argv) { - setpriority(PRIO_PROCESS, 0, -20); //requires superuser privileges; otherwise priority = +0 - signal(SIGINT, sigint); - - if(usart.open("/dev/ttyACM0", 57600, true) == false) { - printf("error: unable to open USART hardware device\n"); - return 0; - } - - usart_is_virtual = false; - usart_init(usarthw_quit, usarthw_usleep, usarthw_readable, usarthw_read, usarthw_writable, usarthw_write); - usart_main(argc, argv); - usart.close(); - - return 0; -} - -#endif diff --git a/higan/phoenix/nall/endian.hpp b/higan/phoenix/nall/endian.hpp deleted file mode 100644 index 1f834b5b..00000000 --- a/higan/phoenix/nall/endian.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#include - -#if defined(ENDIAN_LSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#elif defined(ENDIAN_MSB) - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#else - #error "Unknown endian. Please specify in nall/intrinsics.hpp" -#endif - -#endif diff --git a/higan/phoenix/nall/file.hpp b/higan/phoenix/nall/file.hpp deleted file mode 100644 index e51be466..00000000 --- a/higan/phoenix/nall/file.hpp +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include -#include -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - struct file { - enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append }; - enum class index : unsigned { absolute, relative }; - enum class time : unsigned { create, modify, access }; - - static bool copy(const string &sourcename, const string &targetname) { - file rd, wr; - if(rd.open(sourcename, mode::read) == false) return false; - if(wr.open(targetname, mode::write) == false) return false; - for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read()); - return true; - } - - static bool move(const string &sourcename, const string &targetname) { - #if !defined(_WIN32) - return rename(sourcename, targetname) == 0; - #else - return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0; - #endif - } - - static bool remove(const string &filename) { - return unlink(filename) == 0; - } - - static bool truncate(const string &filename, unsigned size) { - #if !defined(_WIN32) - return truncate(filename, size) == 0; - #else - bool result = false; - FILE *fp = fopen(filename, "rb+"); - if(fp) { - result = _chsize(fileno(fp), size) == 0; - fclose(fp); - } - return result; - #endif - } - - static vector read(const string &filename) { - vector memory; - file fp; - if(fp.open(filename, mode::read)) { - memory.resize(fp.size()); - fp.read(memory.data(), memory.size()); - } - return memory; - } - - static bool read(const string &filename, uint8_t *data, unsigned size) { - file fp; - if(fp.open(filename, mode::read) == false) return false; - fp.read(data, size); - fp.close(); - return true; - } - - static bool write(const string &filename, const string &text) { - file fp; - if(fp.open(filename, mode::write) == false) return false; - fp.print(text); - fp.close(); - return true; - } - - static bool write(const string &filename, const vector &buffer) { - file fp; - if(fp.open(filename, mode::write) == false) return false; - fp.write(buffer.data(), buffer.size()); - fp.close(); - return true; - } - - static bool write(const string &filename, const uint8_t *data, unsigned size) { - file fp; - if(fp.open(filename, mode::write) == false) return false; - fp.write(data, size); - fp.close(); - return true; - } - - static bool create(const string &filename) { - //create an empty file (will replace existing files) - file fp; - if(fp.open(filename, mode::write) == false) return false; - fp.close(); - return true; - } - - static string sha256(const string &filename) { - auto buffer = read(filename); - return nall::sha256(buffer.data(), buffer.size()); - } - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode::write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - template void print(Args... args) { - string data(args...); - const char *p = data; - while(*p) write(*p++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, index index_ = index::absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(index_) { - case index::absolute: req_offset = offset; break; - case index::relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode::read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - unsigned offset() const { - if(!fp) return 0; //file not open - return file_offset; - } - - unsigned size() const { - if(!fp) return 0; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const string &filename) { - #if !defined(_WIN32) - struct stat64 data; - return stat64(filename, &data) == 0; - #else - struct __stat64 data; - return _wstat64(utf16_t(filename), &data) == 0; - #endif - } - - static uintmax_t size(const string &filename) { - #if !defined(_WIN32) - struct stat64 data; - stat64(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - return S_ISREG(data.st_mode) ? data.st_size : 0u; - } - - static time_t timestamp(const string &filename, file::time mode = file::time::create) { - #if !defined(_WIN32) - struct stat64 data; - stat64(filename, &data); - #else - struct __stat64 data; - _wstat64(utf16_t(filename), &data); - #endif - switch(mode) { default: - case file::time::create: return data.st_ctime; - case file::time::modify: return data.st_mtime; - case file::time::access: return data.st_atime; - } - } - - bool open() const { - return fp; - } - - explicit operator bool() const { - return open(); - } - - bool open(const string &filename, mode mode_) { - if(fp) return false; - - switch(file_mode = mode_) { - #if !defined(_WIN32) - case mode::read: fp = fopen(filename, "rb" ); break; - case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering - case mode::readwrite: fp = fopen(filename, "rb+"); break; - case mode::writeread: fp = fopen(filename, "wb+"); break; - #else - case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break; - case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break; - case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break; - case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = nullptr; - } - - file() { - } - - file(const string &filename, mode mode_) { - open(filename, mode_); - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size] = {0}; - int buffer_offset = -1; //invalidate buffer - bool buffer_dirty = false; - FILE *fp = nullptr; - unsigned file_offset = 0; - unsigned file_size = 0; - mode file_mode = mode::read; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode::read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/higan/phoenix/nall/filemap.hpp b/higan/phoenix/nall/filemap.hpp deleted file mode 100644 index f4875f24..00000000 --- a/higan/phoenix/nall/filemap.hpp +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum class mode : unsigned { read, write, readwrite, writeread }; - - explicit operator bool() const { return open(); } - bool open() const { return p_open(); } - bool open(const char *filename, mode mode_) { return p_open(filename, mode_); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* data() { return p_handle; } - const uint8_t* data() const { return p_handle; } - filemap() : p_size(0), p_handle(nullptr) { p_ctor(); } - filemap(const char *filename, mode mode_) : p_size(0), p_handle(nullptr) { p_ctor(); p_open(filename, mode_); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_open() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - if(file::exists(filename) && file::size(filename) == 0) { - p_handle = nullptr; - p_size = 0; - return true; - } - - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode_) { - default: return false; - case mode::read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode::write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode::writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, nullptr, - creation_disposition, FILE_ATTRIBUTE_NORMAL, nullptr); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, nullptr); - - p_maphandle = CreateFileMapping(p_filehandle, nullptr, flprotect, 0, p_size, nullptr); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = nullptr; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_open() const { - return p_handle; - } - - bool p_open(const char *filename, mode mode_) { - if(file::exists(filename) && file::size(filename) == 0) { - p_handle = nullptr; - p_size = 0; - return true; - } - - int open_flags, mmap_flags; - - switch(mode_) { - default: return false; - case mode::read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode::write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode::readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode::writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(nullptr, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = nullptr; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = nullptr; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/higan/phoenix/nall/function.hpp b/higan/phoenix/nall/function.hpp deleted file mode 100644 index 3fbb337a..00000000 --- a/higan/phoenix/nall/function.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -namespace nall { - template class function; - - template class function { - struct container { - virtual R operator()(P... p) const = 0; - virtual container* copy() const = 0; - virtual ~container() {} - } *callback; - - struct global : container { - R (*function)(P...); - R operator()(P... p) const { return function(std::forward

(p)...); } - container* copy() const { return new global(function); } - global(R (*function)(P...)) : function(function) {} - }; - - template struct member : container { - R (C::*function)(P...); - C *object; - R operator()(P... p) const { return (object->*function)(std::forward

(p)...); } - container* copy() const { return new member(function, object); } - member(R (C::*function)(P...), C *object) : function(function), object(object) {} - }; - - template struct lambda : container { - mutable L object; - R operator()(P... p) const { return object(std::forward

(p)...); } - container* copy() const { return new lambda(object); } - lambda(const L& object) : object(object) {} - }; - - public: - explicit operator bool() const { return callback; } - R operator()(P... p) const { return (*callback)(std::forward

(p)...); } - void reset() { if(callback) { delete callback; callback = nullptr; } } - - function& operator=(const function &source) { - if(this != &source) { - if(callback) { delete callback; callback = nullptr; } - if(source.callback) callback = source.callback->copy(); - } - return *this; - } - - function(const function &source) : callback(nullptr) { operator=(source); } - function() : callback(nullptr) {} - function(void *function) : callback(nullptr) { if(function) callback = new global((R (*)(P...))function); } - function(R (*function)(P...)) { callback = new global(function); } - template function(R (C::*function)(P...), C *object) { callback = new member(function, object); } - template function(R (C::*function)(P...) const, C *object) { callback = new member((R (C::*)(P...))function, object); } - template function(const L& object) { callback = new lambda(object); } - ~function() { if(callback) delete callback; } - }; -} - -#endif diff --git a/higan/phoenix/nall/gzip.hpp b/higan/phoenix/nall/gzip.hpp deleted file mode 100644 index a72a3faf..00000000 --- a/higan/phoenix/nall/gzip.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef NALL_GZIP_HPP -#define NALL_GZIP_HPP - -#include -#include - -namespace nall { - -struct gzip { - string filename; - uint8_t *data; - unsigned size; - - inline bool decompress(const string &filename); - inline bool decompress(const uint8_t *data, unsigned size); - - inline gzip(); - inline ~gzip(); -}; - -bool gzip::decompress(const string &filename) { - if(auto memory = file::read(filename)) { - return decompress(memory.data(), memory.size()); - } - return false; -} - -bool gzip::decompress(const uint8_t *data, unsigned size) { - if(size < 18) return false; - if(data[0] != 0x1f) return false; - if(data[1] != 0x8b) return false; - unsigned cm = data[2]; - unsigned flg = data[3]; - unsigned mtime = data[4]; - mtime |= data[5] << 8; - mtime |= data[6] << 16; - mtime |= data[7] << 24; - unsigned xfl = data[8]; - unsigned os = data[9]; - unsigned p = 10; - unsigned isize = data[size - 4]; - isize |= data[size - 3] << 8; - isize |= data[size - 2] << 16; - isize |= data[size - 1] << 24; - filename = ""; - - if(flg & 0x04) { //FEXTRA - unsigned xlen = data[p + 0]; - xlen |= data[p + 1] << 8; - p += 2 + xlen; - } - - if(flg & 0x08) { //FNAME - char buffer[PATH_MAX]; - for(unsigned n = 0; n < PATH_MAX; n++, p++) { - buffer[n] = data[p]; - if(data[p] == 0) break; - } - if(data[p++]) return false; - filename = buffer; - } - - if(flg & 0x10) { //FCOMMENT - while(data[p++]); - } - - if(flg & 0x02) { //FHCRC - p += 2; - } - - this->size = isize; - this->data = new uint8_t[this->size]; - return inflate(this->data, this->size, data + p, size - p - 8); -} - -gzip::gzip() : data(nullptr) { -} - -gzip::~gzip() { - if(data) delete[] data; -} - -} - -#endif diff --git a/higan/phoenix/nall/http.hpp b/higan/phoenix/nall/http.hpp deleted file mode 100644 index f7700cea..00000000 --- a/higan/phoenix/nall/http.hpp +++ /dev/null @@ -1,176 +0,0 @@ -#ifndef NALL_HTTP_HPP -#define NALL_HTTP_HPP - -#if !defined(_WIN32) - #include - #include - #include - #include -#else - #include - #include - #include -#endif - -#include -#include - -namespace nall { - -struct http { - string hostname; - addrinfo *serverinfo; - int serversocket; - string header; - - inline void download(const string &path, uint8_t *&data, unsigned &size) { - data = nullptr; - size = 0; - - send({ - "GET ", path, " HTTP/1.1\r\n" - "Host: ", hostname, "\r\n" - "Connection: close\r\n" - "\r\n" - }); - - header = downloadHeader(); - downloadContent(data, size); - } - - inline bool connect(string host, unsigned port) { - hostname = host; - - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_PASSIVE; - - int status = getaddrinfo(hostname, string(port), &hints, &serverinfo); - if(status != 0) return false; - - serversocket = socket(serverinfo->ai_family, serverinfo->ai_socktype, serverinfo->ai_protocol); - if(serversocket == -1) return false; - - int result = ::connect(serversocket, serverinfo->ai_addr, serverinfo->ai_addrlen); - if(result == -1) return false; - - return true; - } - - inline bool send(const string &data) { - return send((const uint8_t*)(const char*)data, data.length()); - } - - inline bool send(const uint8_t *data, unsigned size) { - while(size) { - int length = ::send(serversocket, (const char*)data, size, 0); - if(length == -1) return false; - data += length; - size -= length; - } - return true; - } - - inline string downloadHeader() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endswith("\r\n\r\n") == false); - return output; - } - - inline string downloadChunkLength() { - string output; - do { - char buffer[2]; - int length = recv(serversocket, buffer, 1, 0); - if(length <= 0) return output; - buffer[1] = 0; - output.append(buffer); - } while(output.endswith("\r\n") == false); - return output; - } - - inline void downloadContent(uint8_t *&data, unsigned &size) { - unsigned capacity = 0; - - if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) { - while(true) { - unsigned length = hex(downloadChunkLength()); - if(length == 0) break; - capacity += length; - data = (uint8_t*)realloc(data, capacity); - - char buffer[length]; - while(length) { - int packetlength = recv(serversocket, buffer, length, 0); - if(packetlength <= 0) break; - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } - } else if(auto position = header.iposition("\r\nContent-Length: ")) { - unsigned length = decimal((const char*)header + position() + 18); - while(length) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, min(256, length), 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - length -= packetlength; - } - } else { - while(true) { - char buffer[256]; - int packetlength = recv(serversocket, buffer, 256, 0); - if(packetlength <= 0) break; - capacity += packetlength; - data = (uint8_t*)realloc(data, capacity); - memcpy(data + size, buffer, packetlength); - size += packetlength; - } - } - - data = (uint8_t*)realloc(data, capacity + 1); - data[capacity] = 0; - } - - inline void disconnect() { - close(serversocket); - freeaddrinfo(serverinfo); - serverinfo = nullptr; - serversocket = -1; - } - - #ifdef _WIN32 - inline int close(int sock) { - return closesocket(sock); - } - - inline http() { - int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sock == INVALID_SOCKET && WSAGetLastError() == WSANOTINITIALISED) { - WSADATA wsaData; - if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - WSACleanup(); - return; - } - } else { - close(sock); - } - } - #endif -}; - -} - -#endif diff --git a/higan/phoenix/nall/image.hpp b/higan/phoenix/nall/image.hpp deleted file mode 100644 index e334b6e0..00000000 --- a/higan/phoenix/nall/image.hpp +++ /dev/null @@ -1,539 +0,0 @@ -#ifndef NALL_IMAGE_HPP -#define NALL_IMAGE_HPP - -#include -#include -#include -#include -#include -#include - -namespace nall { - -struct image { - uint8_t *data; - unsigned width; - unsigned height; - unsigned pitch; - - bool endian; //0 = little, 1 = big - unsigned depth; - unsigned stride; - - struct Channel { - uint64_t mask; - unsigned depth; - unsigned shift; - - inline bool operator==(const Channel &source) { - return mask == source.mask && depth == source.depth && shift == source.shift; - } - - inline bool operator!=(const Channel &source) { - return !operator==(source); - } - } alpha, red, green, blue; - - typedef double (*interpolation)(double, double, double, double, double); - static inline unsigned bitDepth(uint64_t color); - static inline unsigned bitShift(uint64_t color); - static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth); - - inline bool operator==(const image &source); - inline bool operator!=(const image &source); - - inline image& operator=(const image &source); - inline image& operator=(image &&source); - inline image(const image &source); - inline image(image &&source); - inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); - inline image(const string &filename); - inline image(const uint8_t *data, unsigned size); - inline image(); - inline ~image(); - - inline uint64_t read(const uint8_t *data) const; - inline void write(uint8_t *data, uint64_t value) const; - - inline void free(); - inline bool empty() const; - inline void allocate(unsigned width, unsigned height); - inline void clear(uint64_t color); - inline bool load(const string &filename); -//inline bool loadBMP(const uint8_t *data, unsigned size); - inline bool loadPNG(const uint8_t *data, unsigned size); - inline void scale(unsigned width, unsigned height, interpolation op); - inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask); - inline void alphaBlend(uint64_t alphaColor); - -protected: - inline uint64_t interpolate(double mu, const uint64_t *s, interpolation op); - inline void scaleX(unsigned width, interpolation op); - inline void scaleY(unsigned height, interpolation op); - inline bool loadBMP(const string &filename); - inline bool loadPNG(const string &filename); -}; - -//static - -unsigned image::bitDepth(uint64_t color) { - unsigned depth = 0; - if(color) while((color & 1) == 0) color >>= 1; - while((color & 1) == 1) { color >>= 1; depth++; } - return depth; -} - -unsigned image::bitShift(uint64_t color) { - unsigned shift = 0; - if(color) while((color & 1) == 0) { color >>= 1; shift++; } - return shift; -} - -uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) { - while(sourceDepth < targetDepth) { - color = (color << sourceDepth) | color; - sourceDepth += sourceDepth; - } - if(targetDepth < sourceDepth) color >>= (sourceDepth - targetDepth); - return color; -} - -//public - -bool image::operator==(const image &source) { - if(width != source.width) return false; - if(height != source.height) return false; - if(pitch != source.pitch) return false; - - if(endian != source.endian) return false; - if(stride != source.stride) return false; - - if(alpha != source.alpha) return false; - if(red != source.red) return false; - if(green != source.green) return false; - if(blue != source.blue) return false; - - return memcmp(data, source.data, width * height * stride) == 0; -} - -bool image::operator!=(const image &source) { - return !operator==(source); -} - -image& image::operator=(const image &source) { - free(); - - width = source.width; - height = source.height; - pitch = source.pitch; - - endian = source.endian; - stride = source.stride; - - alpha = source.alpha; - red = source.red; - green = source.green; - blue = source.blue; - - data = new uint8_t[width * height * stride]; - memcpy(data, source.data, width * height * stride); - return *this; -} - -image& image::operator=(image &&source) { - free(); - - width = source.width; - height = source.height; - pitch = source.pitch; - - endian = source.endian; - stride = source.stride; - - alpha = source.alpha; - red = source.red; - green = source.green; - blue = source.blue; - - data = source.data; - source.data = nullptr; - return *this; -} - -image::image(const image &source) : data(nullptr) { - operator=(source); -} - -image::image(image &&source) : data(nullptr) { - operator=(std::forward(source)); -} - -image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = endian; - this->depth = depth; - this->stride = (depth / 8) + ((depth & 7) > 0); - - alpha.mask = alphaMask, red.mask = redMask, green.mask = greenMask, blue.mask = blueMask; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); -} - -image::image(const string &filename) : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = 0; - this->depth = 32; - this->stride = 4; - - alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); - - load(filename); -} - -image::image(const uint8_t *data, unsigned size) : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = 0; - this->depth = 32; - this->stride = 4; - - alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); - - loadPNG(data, size); -} - -image::image() : data(nullptr) { - width = 0, height = 0, pitch = 0; - - this->endian = 0; - this->depth = 32; - this->stride = 4; - - alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0; - alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask); - red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask); - green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask); - blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask); -} - -image::~image() { - free(); -} - -uint64_t image::read(const uint8_t *data) const { - uint64_t result = 0; - if(endian == 0) { - for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n]; - } else { - for(signed n = 0; n < stride; n++) result = (result << 8) | data[n]; - } - return result; -} - -void image::write(uint8_t *data, uint64_t value) const { - if(endian == 0) { - for(signed n = 0; n < stride; n++) { data[n] = value; value >>= 8; } - } else { - for(signed n = stride - 1; n >= 0; n--) { data[n] = value; value >>= 8; } - } -} - -void image::free() { - if(data) delete[] data; - data = nullptr; -} - -bool image::empty() const { - if(data == nullptr) return true; - if(width == 0 || height == 0) return true; - return false; -} - -void image::allocate(unsigned width, unsigned height) { - if(data != nullptr && this->width == width && this->height == height) return; - free(); - data = new uint8_t[width * height * stride](); - pitch = width * stride; - this->width = width; - this->height = height; -} - -void image::clear(uint64_t color) { - uint8_t *dp = data; - for(unsigned n = 0; n < width * height; n++) { - write(dp, color); - dp += stride; - } -} - -bool image::load(const string &filename) { - if(loadBMP(filename) == true) return true; - if(loadPNG(filename) == true) return true; - return false; -} - -void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) { - if(width != outputWidth) scaleX(outputWidth, op); - if(height != outputHeight) scaleY(outputHeight, op); -} - -void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) { - image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask); - output.allocate(width, height); - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = output.data + output.pitch * y; - uint8_t *sp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { - uint64_t color = read(sp); - sp += stride; - - uint64_t a = (color & alpha.mask) >> alpha.shift; - uint64_t r = (color & red.mask) >> red.shift; - uint64_t g = (color & green.mask) >> green.shift; - uint64_t b = (color & blue.mask) >> blue.shift; - - a = normalize(a, alpha.depth, output.alpha.depth); - r = normalize(r, red.depth, output.red.depth); - g = normalize(g, green.depth, output.green.depth); - b = normalize(b, blue.depth, output.blue.depth); - - output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift)); - dp += output.stride; - } - } - - operator=(std::move(output)); -} - -void image::alphaBlend(uint64_t alphaColor) { - uint64_t alphaR = (alphaColor & red.mask) >> red.shift; - uint64_t alphaG = (alphaColor & green.mask) >> green.shift; - uint64_t alphaB = (alphaColor & blue.mask) >> blue.shift; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = data + pitch * y; - for(unsigned x = 0; x < width; x++) { - uint64_t color = read(dp); - - uint64_t colorA = (color & alpha.mask) >> alpha.shift; - uint64_t colorR = (color & red.mask) >> red.shift; - uint64_t colorG = (color & green.mask) >> green.shift; - uint64_t colorB = (color & blue.mask) >> blue.shift; - double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1); - - colorA = (1 << alpha.depth) - 1; - colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale)); - colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale)); - colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale)); - - write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift)); - dp += stride; - } - } -} - -//protected - -uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, double, double, double, double)) { - uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift, - ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift; - uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift, - bg = (s[1] & green.mask) >> green.shift, bb = (s[1] & blue.mask) >> blue.shift; - uint64_t ca = (s[2] & alpha.mask) >> alpha.shift, cr = (s[2] & red.mask) >> red.shift, - cg = (s[2] & green.mask) >> green.shift, cb = (s[2] & blue.mask) >> blue.shift; - uint64_t da = (s[3] & alpha.mask) >> alpha.shift, dr = (s[3] & red.mask) >> red.shift, - dg = (s[3] & green.mask) >> green.shift, db = (s[3] & blue.mask) >> blue.shift; - - int64_t A = op(mu, aa, ba, ca, da); - int64_t R = op(mu, ar, br, cr, dr); - int64_t G = op(mu, ag, bg, cg, dg); - int64_t B = op(mu, ab, bb, cb, db); - - A = max(0, min(A, (1 << alpha.depth) - 1)); - R = max(0, min(R, (1 << red.depth) - 1)); - G = max(0, min(G, (1 << green.depth) - 1)); - B = max(0, min(B, (1 << blue.depth) - 1)); - - return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift); -} - -void image::scaleX(unsigned outputWidth, interpolation op) { - uint8_t *outputData = new uint8_t[outputWidth * height * stride]; - unsigned outputPitch = outputWidth * stride; - double step = (double)width / (double)outputWidth; - const uint8_t *terminal = data + pitch * height; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - uint8_t *dp = outputData + outputPitch * y; - uint8_t *sp = data + pitch * y; - - double fraction = 0.0; - uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; //B,C (0,1) = center of kernel { 0, 0, 1, 2 } - s[1] = s[0]; - s[2] = sp + stride < terminal ? read(sp += stride) : s[1]; - s[3] = sp + stride < terminal ? read(sp += stride) : s[2]; - - for(unsigned x = 0; x < width; x++) { - while(fraction <= 1.0) { - if(dp >= outputData + outputPitch * height) break; - write(dp, interpolate(fraction, (const uint64_t*)&s, op)); - dp += stride; - fraction += step; - } - - s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; - if(sp + stride < terminal) s[3] = read(sp += stride); - fraction -= 1.0; - } - } - - free(); - data = outputData; - width = outputWidth; - pitch = width * stride; -} - -void image::scaleY(unsigned outputHeight, interpolation op) { - uint8_t *outputData = new uint8_t[width * outputHeight * stride]; - double step = (double)height / (double)outputHeight; - const uint8_t *terminal = data + pitch * height; - - #pragma omp parallel for - for(unsigned x = 0; x < width; x++) { - uint8_t *dp = outputData + stride * x; - uint8_t *sp = data + stride * x; - - double fraction = 0.0; - uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; - s[1] = s[0]; - s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1]; - s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2]; - - for(unsigned y = 0; y < height; y++) { - while(fraction <= 1.0) { - if(dp >= outputData + pitch * outputHeight) break; - write(dp, interpolate(fraction, (const uint64_t*)&s, op)); - dp += pitch; - fraction += step; - } - - s[0] = s[1]; s[1] = s[2]; s[2] = s[3]; - if(sp + pitch < terminal) s[3] = read(sp += pitch); - fraction -= 1.0; - } - } - - free(); - data = outputData; - height = outputHeight; -} - -bool image::loadBMP(const string &filename) { - uint32_t *outputData; - unsigned outputWidth, outputHeight; - if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false; - - allocate(outputWidth, outputHeight); - const uint32_t *sp = outputData; - uint8_t *dp = data; - - for(unsigned y = 0; y < outputHeight; y++) { - for(unsigned x = 0; x < outputWidth; x++) { - uint32_t color = *sp++; - uint64_t a = normalize((uint8_t)(color >> 24), 8, alpha.depth); - uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth); - uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth); - uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth); - write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift)); - dp += stride; - } - } - - delete[] outputData; - return true; -} - -bool image::loadPNG(const uint8_t *pngData, unsigned pngSize) { - png source; - if(source.decode(pngData, pngSize) == false) return false; - - allocate(source.info.width, source.info.height); - const uint8_t *sp = source.data; - uint8_t *dp = data; - - auto decode = [&]() -> uint64_t { - uint64_t p, r, g, b, a; - - switch(source.info.colorType) { - case 0: //L - r = g = b = source.readbits(sp); - a = (1 << source.info.bitDepth) - 1; - break; - case 2: //R,G,B - r = source.readbits(sp); - g = source.readbits(sp); - b = source.readbits(sp); - a = (1 << source.info.bitDepth) - 1; - break; - case 3: //P - p = source.readbits(sp); - r = source.info.palette[p][0]; - g = source.info.palette[p][1]; - b = source.info.palette[p][2]; - a = (1 << source.info.bitDepth) - 1; - break; - case 4: //L,A - r = g = b = source.readbits(sp); - a = source.readbits(sp); - break; - case 6: //R,G,B,A - r = source.readbits(sp); - g = source.readbits(sp); - b = source.readbits(sp); - a = source.readbits(sp); - break; - } - - a = normalize(a, source.info.bitDepth, alpha.depth); - r = normalize(r, source.info.bitDepth, red.depth); - g = normalize(g, source.info.bitDepth, green.depth); - b = normalize(b, source.info.bitDepth, blue.depth); - - return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift); - }; - - for(unsigned y = 0; y < height; y++) { - for(unsigned x = 0; x < width; x++) { - write(dp, decode()); - dp += stride; - } - } - - return true; -} - -bool image::loadPNG(const string &filename) { - filemap map; - if(map.open(filename, filemap::mode::read) == false) return false; - return loadPNG(map.data(), map.size()); -} - -} - -#endif diff --git a/higan/phoenix/nall/inflate.hpp b/higan/phoenix/nall/inflate.hpp deleted file mode 100644 index 8e75ce76..00000000 --- a/higan/phoenix/nall/inflate.hpp +++ /dev/null @@ -1,358 +0,0 @@ -#ifndef NALL_INFLATE_HPP -#define NALL_INFLATE_HPP - -#include - -namespace nall { - -namespace puff { - inline int puff( - unsigned char *dest, unsigned long *destlen, - unsigned char *source, unsigned long *sourcelen - ); -} - -inline bool inflate( - uint8_t *target, unsigned targetLength, - const uint8_t *source, unsigned sourceLength -) { - unsigned long tl = targetLength, sl = sourceLength; - int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl); - return result == 0; -} - -namespace puff { - -//zlib/contrib/puff.c -//version 2.1* -//author: Mark Adler -//license: zlib -//ported by: byuu - -//* I have corrected a bug in fixed(), where it was accessing uninitialized -// memory: calling construct() with lencode prior to initializing lencode.count - -enum { - MAXBITS = 15, - MAXLCODES = 286, - MAXDCODES = 30, - FIXLCODES = 288, - MAXCODES = MAXLCODES + MAXDCODES, -}; - -struct state { - unsigned char *out; - unsigned long outlen; - unsigned long outcnt; - - unsigned char *in; - unsigned long inlen; - unsigned long incnt; - int bitbuf; - int bitcnt; - - jmp_buf env; -}; - -struct huffman { - short *count; - short *symbol; -}; - -inline int bits(state *s, int need) { - long val; - - val = s->bitbuf; - while(s->bitcnt < need) { - if(s->incnt == s->inlen) longjmp(s->env, 1); - val |= (long)(s->in[s->incnt++]) << s->bitcnt; - s->bitcnt += 8; - } - - s->bitbuf = (int)(val >> need); - s->bitcnt -= need; - - return (int)(val & ((1L << need) - 1)); -} - -inline int stored(state *s) { - unsigned len; - - s->bitbuf = 0; - s->bitcnt = 0; - - if(s->incnt + 4 > s->inlen) return 2; - len = s->in[s->incnt++]; - len |= s->in[s->incnt++] << 8; - if(s->in[s->incnt++] != (~len & 0xff) || - s->in[s->incnt++] != ((~len >> 8) & 0xff) - ) return 2; - - if(s->incnt + len > s->inlen) return 2; - if(s->out != nullptr) { - if(s->outcnt + len > s->outlen) return 1; - while(len--) s->out[s->outcnt++] = s->in[s->incnt++]; - } else { - s->outcnt += len; - s->incnt += len; - } - - return 0; -} - -inline int decode(state *s, huffman *h) { - int len, code, first, count, index, bitbuf, left; - short *next; - - bitbuf = s->bitbuf; - left = s->bitcnt; - code = first = index = 0; - len = 1; - next = h->count + 1; - while(true) { - while(left--) { - code |= bitbuf & 1; - bitbuf >>= 1; - count = *next++; - if(code - count < first) { - s->bitbuf = bitbuf; - s->bitcnt = (s->bitcnt - len) & 7; - return h->symbol[index + (code - first)]; - } - index += count; - first += count; - first <<= 1; - code <<= 1; - len++; - } - left = (MAXBITS + 1) - len; - if(left == 0) break; - if(s->incnt == s->inlen) longjmp(s->env, 1); - bitbuf = s->in[s->incnt++]; - if(left > 8) left = 8; - } - - return -10; -} - -inline int construct(huffman *h, short *length, int n) { - int symbol, len, left; - short offs[MAXBITS + 1]; - - for(len = 0; len <= MAXBITS; len++) h->count[len] = 0; - for(symbol = 0; symbol < n; symbol++) h->count[length[symbol]]++; - if(h->count[0] == n) return 0; - - left = 1; - for(len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= h->count[len]; - if(left < 0) return left; - } - - offs[1] = 0; - for(len = 1; len < MAXBITS; len++) offs[len + 1] = offs[len] + h->count[len]; - - for(symbol = 0; symbol < n; symbol++) { - if(length[symbol] != 0) h->symbol[offs[length[symbol]]++] = symbol; - } - - return left; -} - -inline int codes(state *s, huffman *lencode, huffman *distcode) { - int symbol, len; - unsigned dist; - static const short lens[29] = { - 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, - 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258 - }; - static const short lext[29] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 - }; - static const short dists[30] = { - 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, - 8193, 12289, 16385, 24577 - }; - static const short dext[30] = { - 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, - 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, - 12, 12, 13, 13 - }; - - do { - symbol = decode(s, lencode); - if(symbol < 0) return symbol; - if(symbol < 256) { - if(s->out != nullptr) { - if(s->outcnt == s->outlen) return 1; - s->out[s->outcnt] = symbol; - } - s->outcnt++; - } else if(symbol > 256) { - symbol -= 257; - if(symbol >= 29) return -10; - len = lens[symbol] + bits(s, lext[symbol]); - - symbol = decode(s, distcode); - if(symbol < 0) return symbol; - dist = dists[symbol] + bits(s, dext[symbol]); - #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR - if(dist > s->outcnt) return -11; - #endif - - if(s->out != nullptr) { - if(s->outcnt + len > s->outlen) return 1; - while(len--) { - s->out[s->outcnt] = - #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOO_FAR - dist > s->outcnt ? 0 : - #endif - s->out[s->outcnt - dist]; - s->outcnt++; - } - } else { - s->outcnt += len; - } - } - } while(symbol != 256); - - return 0; -} - -inline int fixed(state *s) { - static int virgin = 1; - static short lencnt[MAXBITS + 1], lensym[FIXLCODES]; - static short distcnt[MAXBITS + 1], distsym[MAXDCODES]; - static huffman lencode, distcode; - - if(virgin) { - int symbol = 0; - short lengths[FIXLCODES]; - - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - for(; symbol < 144; symbol++) lengths[symbol] = 8; - for(; symbol < 256; symbol++) lengths[symbol] = 9; - for(; symbol < 280; symbol++) lengths[symbol] = 7; - for(; symbol < FIXLCODES; symbol++) lengths[symbol] = 8; - construct(&lencode, lengths, FIXLCODES); - - for(symbol = 0; symbol < MAXDCODES; symbol++) lengths[symbol] = 5; - construct(&distcode, lengths, MAXDCODES); - - virgin = 0; - } - - return codes(s, &lencode, &distcode); -} - -inline int dynamic(state *s) { - int nlen, ndist, ncode, index, err; - short lengths[MAXCODES]; - short lencnt[MAXBITS + 1], lensym[MAXLCODES]; - short distcnt[MAXBITS + 1], distsym[MAXDCODES]; - huffman lencode, distcode; - static const short order[19] = { - 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 - }; - - lencode.count = lencnt; - lencode.symbol = lensym; - distcode.count = distcnt; - distcode.symbol = distsym; - - nlen = bits(s, 5) + 257; - ndist = bits(s, 5) + 1; - ncode = bits(s, 4) + 4; - if(nlen > MAXLCODES || ndist > MAXDCODES) return -3; - - for(index = 0; index < ncode; index++) lengths[order[index]] = bits(s, 3); - for(; index < 19; index++) lengths[order[index]] = 0; - - err = construct(&lencode, lengths, 19); - if(err != 0) return -4; - - index = 0; - while(index < nlen + ndist) { - int symbol, len; - - symbol = decode(s, &lencode); - if(symbol < 16) { - lengths[index++] = symbol; - } else { - len = 0; - if(symbol == 16) { - if(index == 0) return -5; - len = lengths[index - 1]; - symbol = 3 + bits(s, 2); - } else if(symbol == 17) { - symbol = 3 + bits(s, 3); - } else { - symbol = 11 + bits(s, 7); - } - if(index + symbol > nlen + ndist) return -6; - while(symbol--) lengths[index++] = len; - } - } - - if(lengths[256] == 0) return -9; - - err = construct(&lencode, lengths, nlen); - if(err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) return -7; - - err = construct(&distcode, lengths + nlen, ndist); - if(err < 0 || (err > 0 && ndist - distcode.count[0] != 1)) return -8; - - return codes(s, &lencode, &distcode); -} - -inline int puff( - unsigned char *dest, unsigned long *destlen, - unsigned char *source, unsigned long *sourcelen -) { - state s; - int last, type, err; - - s.out = dest; - s.outlen = *destlen; - s.outcnt = 0; - - s.in = source; - s.inlen = *sourcelen; - s.incnt = 0; - s.bitbuf = 0; - s.bitcnt = 0; - - if(setjmp(s.env) != 0) { - err = 2; - } else { - do { - last = bits(&s, 1); - type = bits(&s, 2); - err = type == 0 ? stored(&s) - : type == 1 ? fixed(&s) - : type == 2 ? dynamic(&s) - : -1; - if(err != 0) break; - } while(!last); - } - - if(err <= 0) { - *destlen = s.outcnt; - *sourcelen = s.incnt; - } - - return err; -} - -} - -} - -#endif diff --git a/higan/phoenix/nall/input.hpp b/higan/phoenix/nall/input.hpp deleted file mode 100644 index cd765393..00000000 --- a/higan/phoenix/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "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", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - 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, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - s.ltrim("KB"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return { "KB", ID, "::", KeyboardScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - s.ltrim("MS"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return { "MS", ID, "::", MouseScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - s.ltrim("JP"); - unsigned id = decimal(s); - auto pos = strpos(s, "::"); - if(!pos) return 0; - s = substr(s, pos() + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return { "JP", ID, "::", JoypadScancodeName[index] }; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/interpolation.hpp b/higan/phoenix/nall/interpolation.hpp deleted file mode 100644 index afc7108b..00000000 --- a/higan/phoenix/nall/interpolation.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef NALL_INTERPOLATION_HPP -#define NALL_INTERPOLATION_HPP - -namespace nall { - -struct Interpolation { - static inline double Nearest(double mu, double a, double b, double c, double d) { - return (mu <= 0.5 ? b : c); - } - - static inline double Sublinear(double mu, double a, double b, double c, double d) { - mu = ((mu - 0.5) * 2.0) + 0.5; - if(mu < 0) mu = 0; - if(mu > 1) mu = 1; - return b * (1.0 - mu) + c * mu; - } - - static inline double Linear(double mu, double a, double b, double c, double d) { - return b * (1.0 - mu) + c * mu; - } - - static inline double Cosine(double mu, double a, double b, double c, double d) { - mu = (1.0 - cos(mu * 3.14159265)) / 2.0; - return b * (1.0 - mu) + c * mu; - } - - static inline double Cubic(double mu, double a, double b, double c, double d) { - double A = d - c - a + b; - double B = a - b - A; - double C = c - a; - double D = b; - return A * (mu * mu * mu) + B * (mu * mu) + C * mu + D; - } - - static inline double Hermite(double mu1, double a, double b, double c, double d) { - const double tension = 0.0; //-1 = low, 0 = normal, +1 = high - const double bias = 0.0; //-1 = left, 0 = even, +1 = right - double mu2, mu3, m0, m1, a0, a1, a2, a3; - - mu2 = mu1 * mu1; - mu3 = mu2 * mu1; - - m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0; - m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0; - m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0; - m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0; - - a0 = +2 * mu3 - 3 * mu2 + 1; - a1 = mu3 - 2 * mu2 + mu1; - a2 = mu3 - mu2; - a3 = -2 * mu3 + 3 * mu2; - - return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c); - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/intrinsics.hpp b/higan/phoenix/nall/intrinsics.hpp deleted file mode 100644 index 920548f7..00000000 --- a/higan/phoenix/nall/intrinsics.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_INTRINSICS_HPP -#define NALL_INTRINSICS_HPP - -struct Intrinsics { - enum class Compiler : unsigned { Clang, GCC, VisualC, Unknown }; - enum class Platform : unsigned { X, OSX, Windows, Unknown }; - enum class Endian : unsigned { LSB, MSB, Unknown }; - - static inline Compiler compiler(); - static inline Platform platform(); - static inline Endian endian(); -}; - -/* Compiler detection */ - -#if defined(__clang__) - #define COMPILER_CLANG - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Clang; } -#elif defined(__GNUC__) - #define COMPILER_GCC - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::GCC; } -#elif defined(_MSC_VER) - #define COMPILER_VISUALC - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::VisualC; } -#else - #warning "unable to detect compiler" - #define COMPILER_UNKNOWN - Intrinsics::Compiler Intrinsics::compiler() { return Intrinsics::Compiler::Unknown; } -#endif - -/* Platform detection */ - -#if defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::X; } -#elif defined(__APPLE__) - #define PLATFORM_OSX - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::OSX; } -#elif defined(_WIN32) - #define PLATFORM_WINDOWS - #define PLATFORM_WIN - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Windows; } -#else - #warning "unable to detect platform" - #define PLATFORM_UNKNOWN - Intrinsics::Platform Intrinsics::platform() { return Intrinsics::Platform::Unknown; } -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ENDIAN_LSB - #define ARCH_LSB - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::LSB; } -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ENDIAN_MSB - #define ARCH_MSB - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::MSB; } -#else - #warning "unable to detect endian" - #define ENDIAN_UNKNOWN - #define ARCH_UNKNOWN - Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; } -#endif - -#endif diff --git a/higan/phoenix/nall/invoke.hpp b/higan/phoenix/nall/invoke.hpp deleted file mode 100644 index 9486e00b..00000000 --- a/higan/phoenix/nall/invoke.hpp +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef NALL_INVOKE_HPP -#define NALL_INVOKE_HPP - -//void invoke(const string &name, const string& args...); -//if a program is specified, it is executed with the arguments provided -//if a file is specified, the file is opened using the program associated with said file type -//if a folder is specified, the folder is opened using the associated file explorer -//if a URL is specified, the default web browser is opened and pointed at the URL requested -//path environment variable is always consulted -//execution is asynchronous (non-blocking); use system() for synchronous execution - -#include -#include - -#if defined(PLATFORM_WINDOWS) - #include -#endif - -namespace nall { - -#if defined(PLATFORM_WINDOWS) - -template -inline void invoke(const string &name, Args&&... args) { - lstring argl(std::forward(args)...); - for(auto &arg : argl) if(arg.position(" ")) arg = {"\"", arg, "\""}; - string arguments = argl.concatenate(" "); - ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL); -} - -#elif defined(PLATFORM_X) - -template -inline void invoke(const string &name, Args&&... args) { - pid_t pid = fork(); - if(pid == 0) { - const char *argv[1 + sizeof...(args) + 1], **argp = argv; - lstring argl(std::forward(args)...); - *argp++ = (const char*)name; - for(auto &arg : argl) *argp++ = (const char*)arg; - *argp++ = nullptr; - - if(execvp(name, (char* const*)argv) < 0) { - execlp("xdg-open", "xdg-open", (const char*)name, nullptr); - } - exit(0); - } -} - -#else - -template -inline void invoke(const string &name, Args&&... args) { -} - -#endif - -} - -#endif diff --git a/higan/phoenix/nall/ips.hpp b/higan/phoenix/nall/ips.hpp deleted file mode 100644 index 473d74c5..00000000 --- a/higan/phoenix/nall/ips.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef NALL_IPS_HPP -#define NALL_IPS_HPP - -#include -#include -#include - -namespace nall { - -struct ips { - inline bool apply(); - inline void source(const uint8_t *data, unsigned size); - inline void modify(const uint8_t *data, unsigned size); - inline ips(); - inline ~ips(); - - uint8_t *data; - unsigned size; - const uint8_t *sourceData; - unsigned sourceSize; - const uint8_t *modifyData; - unsigned modifySize; -}; - -bool ips::apply() { - if(modifySize < 8) return false; - if(modifyData[0] != 'P') return false; - if(modifyData[1] != 'A') return false; - if(modifyData[2] != 'T') return false; - if(modifyData[3] != 'C') return false; - if(modifyData[4] != 'H') return false; - - if(data) delete[] data; - data = new uint8_t[16 * 1024 * 1024 + 65536](); //maximum size of IPS patch + single-tag padding - size = sourceSize; - memcpy(data, sourceData, sourceSize); - unsigned offset = 5; - - while(true) { - unsigned address, length; - - if(offset > modifySize - 3) break; - address = modifyData[offset++] << 16; - address |= modifyData[offset++] << 8; - address |= modifyData[offset++] << 0; - - if(address == 0x454f46) { //EOF - if(offset == modifySize) return true; - if(offset == modifySize - 3) { - size = modifyData[offset++] << 16; - size |= modifyData[offset++] << 8; - size |= modifyData[offset++] << 0; - return true; - } - } - - if(offset > modifySize - 2) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - - if(length) { //Copy - if(offset > modifySize - length) break; - while(length--) data[address++] = modifyData[offset++]; - } else { //RLE - if(offset > modifySize - 3) break; - length = modifyData[offset++] << 8; - length |= modifyData[offset++] << 0; - if(length == 0) break; //illegal - while(length--) data[address++] = modifyData[offset]; - offset++; - } - - size = max(size, address); - } - - delete[] data; - data = nullptr; - return false; -} - -void ips::source(const uint8_t *data, unsigned size) { - sourceData = data, sourceSize = size; -} - -void ips::modify(const uint8_t *data, unsigned size) { - modifyData = data, modifySize = size; -} - -ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) { -} - -ips::~ips() { - if(data) delete[] data; - if(sourceData) delete[] sourceData; - if(modifyData) delete[] modifyData; -} - -} - -#endif diff --git a/higan/phoenix/nall/lzss.hpp b/higan/phoenix/nall/lzss.hpp deleted file mode 100644 index d595f911..00000000 --- a/higan/phoenix/nall/lzss.hpp +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include -#include - -namespace nall { - -//19:5 pulldown -//8:1 marker: d7-d0 -//length: { 4 - 35 }, offset: { 1 - 0x80000 } -//4-byte file size header -//little-endian encoding -struct lzss { - inline void source(const uint8_t *data, unsigned size); - inline bool source(const string &filename); - inline unsigned size() const; - inline bool compress(const string &filename); - inline bool decompress(uint8_t *targetData, unsigned targetSize); - inline bool decompress(const string &filename); - -protected: - struct Node { - unsigned offset; - Node *next; - inline Node() : offset(0), next(nullptr) {} - inline ~Node() { if(next) delete next; } - } *tree[65536]; - - filemap sourceFile; - const uint8_t *sourceData; - unsigned sourceSize; - -public: - inline lzss() : sourceData(nullptr), sourceSize(0) {} -}; - -void lzss::source(const uint8_t *data, unsigned size) { - sourceData = data; - sourceSize = size; -} - -bool lzss::source(const string &filename) { - if(sourceFile.open(filename, filemap::mode::read) == false) return false; - sourceData = sourceFile.data(); - sourceSize = sourceFile.size(); - return true; -} - -unsigned lzss::size() const { - unsigned size = 0; - if(sourceSize < 4) return size; - for(unsigned n = 0; n < 32; n += 8) size |= sourceData[n >> 3] << n; - return size; -} - -bool lzss::compress(const string &filename) { - file targetFile; - if(targetFile.open(filename, file::mode::write) == false) return false; - - for(unsigned n = 0; n < 32; n += 8) targetFile.write(sourceSize >> n); - for(unsigned n = 0; n < 65536; n++) tree[n] = nullptr; - - uint8_t buffer[25]; - unsigned sourceOffset = 0; - - while(sourceOffset < sourceSize) { - uint8_t mask = 0x00; - unsigned bufferOffset = 1; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - uint16_t symbol = sourceData[sourceOffset + 0]; - if(sourceOffset < sourceSize - 1) symbol |= sourceData[sourceOffset + 1] << 8; - Node *node = tree[symbol]; - unsigned maxLength = 0, maxOffset = 0; - - while(node) { - if(node->offset < sourceOffset - 0x80000) { - //out-of-range: all subsequent nodes will also be, so free up their memory - if(node->next) { delete node->next; node->next = nullptr; } - break; - } - - unsigned length = 0, x = sourceOffset, y = node->offset; - while(length < 35 && x < sourceSize && sourceData[x++] == sourceData[y++]) length++; - if(length > maxLength) maxLength = length, maxOffset = node->offset; - if(length == 35) break; - - node = node->next; - } - - //attach current symbol to top of tree for subsequent searches - node = new Node; - node->offset = sourceOffset; - node->next = tree[symbol]; - tree[symbol] = node; - - if(maxLength < 4) { - buffer[bufferOffset++] = sourceData[sourceOffset++]; - } else { - unsigned output = ((maxLength - 4) << 19) | (sourceOffset - 1 - maxOffset); - for(unsigned n = 0; n < 24; n += 8) buffer[bufferOffset++] = output >> n; - mask |= 0x80 >> iteration; - sourceOffset += maxLength; - } - } - - buffer[0] = mask; - targetFile.write(buffer, bufferOffset); - } - - sourceFile.close(); - targetFile.close(); - return true; -} - -bool lzss::decompress(uint8_t *targetData, unsigned targetSize) { - if(targetSize < size()) return false; - - unsigned sourceOffset = 4, targetOffset = 0; - while(sourceOffset < sourceSize) { - uint8_t mask = sourceData[sourceOffset++]; - - for(unsigned iteration = 0; iteration < 8; iteration++) { - if(sourceOffset >= sourceSize) break; - - if((mask & (0x80 >> iteration)) == 0) { - targetData[targetOffset++] = sourceData[sourceOffset++]; - } else { - unsigned code = 0; - for(unsigned n = 0; n < 24; n += 8) code |= sourceData[sourceOffset++] << n; - unsigned length = (code >> 19) + 4; - unsigned offset = targetOffset - 1 - (code & 0x7ffff); - while(length--) targetData[targetOffset++] = targetData[offset++]; - } - } - } -} - -bool lzss::decompress(const string &filename) { - if(sourceSize < 4) return false; - unsigned targetSize = size(); - - file fp; - if(fp.open(filename, file::mode::write) == false) return false; - fp.truncate(targetSize); - fp.close(); - - filemap targetFile; - if(targetFile.open(filename, filemap::mode::readwrite) == false) return false; - uint8_t *targetData = targetFile.data(); - - bool result = decompress(targetData, targetSize); - sourceFile.close(); - targetFile.close(); - return result; -} - -} - -#endif diff --git a/higan/phoenix/nall/map.hpp b/higan/phoenix/nall/map.hpp deleted file mode 100644 index 938f0c2d..00000000 --- a/higan/phoenix/nall/map.hpp +++ /dev/null @@ -1,117 +0,0 @@ -#ifndef NALL_MAP_HPP -#define NALL_MAP_HPP - -#include - -namespace nall { - -template -struct map { - struct pair { - LHS name; - RHS data; - }; - - inline void reset() { - list.reset(); - } - - inline unsigned size() const { - return list.size(); - } - - //O(log n) find - inline optional find(const LHS &name) const { - signed first = 0, last = size() - 1; - while(first <= last) { - signed middle = (first + last) / 2; - if(name < list[middle].name) last = middle - 1; //search lower half - else if(list[middle].name < name) first = middle + 1; //search upper half - else return { true, (unsigned)middle }; //match found - } - return { false, 0u }; - } - - //O(n) insert + O(log n) find - inline RHS& insert(const LHS &name, const RHS &data) { - if(auto position = find(name)) { - list[position()].data = data; - return list[position()].data; - } - signed offset = size(); - for(unsigned n = 0; n < size(); n++) { - if(name < list[n].name) { offset = n; break; } - } - list.insert(offset, { name, data }); - return list[offset].data; - } - - //O(log n) find - inline void modify(const LHS &name, const RHS &data) { - if(auto position = find(name)) list[position()].data = data; - } - - //O(n) remove + O(log n) find - inline void remove(const LHS &name) { - if(auto position = find(name)) list.remove(position()); - } - - //O(log n) find - inline RHS& operator[](const LHS &name) { - if(auto position = find(name)) return list[position()].data; - throw; - } - - inline const RHS& operator[](const LHS &name) const { - if(auto position = find(name)) return list[position()].data; - throw; - } - - inline RHS& operator()(const LHS &name) { - if(auto position = find(name)) return list[position()].data; - return insert(name, RHS()); - } - - inline const RHS& operator()(const LHS &name, const RHS &data) const { - if(auto position = find(name)) return list[position()].data; - return data; - } - - inline pair* begin() { return list.begin(); } - inline pair* end() { return list.end(); } - inline const pair* begin() const { return list.begin(); } - inline const pair* end() const { return list.end(); } - -protected: - vector list; -}; - -template -struct bidirectional_map { - const map &lhs; - const map &rhs; - - inline void reset() { - llist.reset(); - rlist.reset(); - } - - inline unsigned size() const { - return llist.size(); - } - - inline void insert(const LHS &ldata, const RHS &rdata) { - llist.insert(ldata, rdata); - rlist.insert(rdata, ldata); - } - - inline bidirectional_map() : lhs(llist), rhs(rlist) {} - -protected: - map llist; - map rlist; -}; - -} - -#endif diff --git a/higan/phoenix/nall/mosaic.hpp b/higan/phoenix/nall/mosaic.hpp deleted file mode 100644 index 16fd0bfd..00000000 --- a/higan/phoenix/nall/mosaic.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NALL_MOSAIC_HPP -#define NALL_MOSAIC_HPP - -#define NALL_MOSAIC_INTERNAL_HPP -#include -#include -#include -#undef NALL_MOSAIC_INTERNAL_HPP - -#endif diff --git a/higan/phoenix/nall/mosaic/bitstream.hpp b/higan/phoenix/nall/mosaic/bitstream.hpp deleted file mode 100644 index e2cb3bc5..00000000 --- a/higan/phoenix/nall/mosaic/bitstream.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct bitstream { - filemap fp; - uint8_t *data; - unsigned size; - bool readonly; - bool endian; - - inline bool read(uint64_t addr) const { - if(data == nullptr || (addr >> 3) >= size) return 0; - unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7)); - return data[addr >> 3] & mask; - } - - inline void write(uint64_t addr, bool value) { - if(data == nullptr || readonly == true || (addr >> 3) >= size) return; - unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7)); - if(value == 0) data[addr >> 3] &= ~mask; - if(value == 1) data[addr >> 3] |= mask; - } - - inline bool open(const string &filename) { - readonly = false; - if(fp.open(filename, filemap::mode::readwrite) == false) { - readonly = true; - if(fp.open(filename, filemap::mode::read) == false) { - return false; - } - } - data = fp.data(); - size = fp.size(); - return true; - } - - inline void close() { - fp.close(); - data = nullptr; - } - - inline bitstream() : data(nullptr), endian(1) { - } - - inline ~bitstream() { - close(); - } -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/mosaic/context.hpp b/higan/phoenix/nall/mosaic/context.hpp deleted file mode 100644 index bc7a518a..00000000 --- a/higan/phoenix/nall/mosaic/context.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct context { - unsigned offset; - unsigned width; - unsigned height; - unsigned count; - - bool endian; //0 = lsb, 1 = msb - bool order; //0 = linear, 1 = planar - unsigned depth; //1 - 24bpp - - unsigned blockWidth; - unsigned blockHeight; - unsigned blockStride; - unsigned blockOffset; - vector block; - - unsigned tileWidth; - unsigned tileHeight; - unsigned tileStride; - unsigned tileOffset; - vector tile; - - unsigned mosaicWidth; - unsigned mosaicHeight; - unsigned mosaicStride; - unsigned mosaicOffset; - vector mosaic; - - unsigned paddingWidth; - unsigned paddingHeight; - unsigned paddingColor; - vector palette; - - inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; } - inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; } - inline unsigned objectSize() const { - unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight - + blockOffset * tileHeight * mosaicWidth * mosaicHeight - + tileStride * mosaicWidth * mosaicHeight - + tileOffset * mosaicHeight; - return max(1u, size); - } - - inline unsigned eval(const string &expression) { - intmax_t result; - if(fixedpoint::eval(expression, result) == false) return 0u; - return result; - } - - inline void eval(vector &buffer, const string &expression_) { - string expression = expression_; - bool function = false; - for(auto &c : expression) { - if(c == '(') function = true; - if(c == ')') function = false; - if(c == ',' && function == true) c = ';'; - } - - lstring list = expression.split(","); - for(auto &item : list) { - item.trim(); - if(item.wildcard("f(?*) ?*")) { - item.ltrim<1>("f("); - lstring part = item.split<1>(") "); - lstring args = part[0].split<3>(";"); - for(auto &item : args) item.trim(); - - unsigned length = eval(args(0, "0")); - unsigned offset = eval(args(1, "0")); - unsigned stride = eval(args(2, "0")); - if(args.size() < 2) offset = buffer.size(); - if(args.size() < 3) stride = 1; - - for(unsigned n = 0; n < length; n++) { - string fn = part[1]; - fn.replace("n", decimal(n)); - fn.replace("o", decimal(offset)); - fn.replace("p", decimal(buffer.size())); - buffer.resize(offset + 1); - buffer[offset] = eval(fn); - offset += stride; - } - } else if(item.wildcard("base64*")) { - unsigned offset = 0; - item.ltrim<1>("base64"); - if(item.wildcard("(?*) *")) { - item.ltrim<1>("("); - lstring part = item.split<1>(") "); - offset = eval(part[0]); - item = part(1, ""); - } - item.trim(); - for(auto &c : item) { - if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0); - if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26); - if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52); - if(c == '-') buffer.append(offset + 62); - if(c == '_') buffer.append(offset + 63); - } - } else if(item.wildcard("file *")) { - item.ltrim<1>("file "); - item.trim(); - //... - } else if(item.empty() == false) { - buffer.append(eval(item)); - } - } - } - - inline void parse(const string &data) { - reset(); - - lstring lines = data.split("\n"); - for(auto &line : lines) { - lstring part = line.split<1>(":"); - if(part.size() != 2) continue; - part[0].trim(); - part[1].trim(); - - if(part[0] == "offset") offset = eval(part[1]); - if(part[0] == "width") width = eval(part[1]); - if(part[0] == "height") height = eval(part[1]); - if(part[0] == "count") count = eval(part[1]); - - if(part[0] == "endian") endian = eval(part[1]); - if(part[0] == "order") order = eval(part[1]); - if(part[0] == "depth") depth = eval(part[1]); - - if(part[0] == "blockWidth") blockWidth = eval(part[1]); - if(part[0] == "blockHeight") blockHeight = eval(part[1]); - if(part[0] == "blockStride") blockStride = eval(part[1]); - if(part[0] == "blockOffset") blockOffset = eval(part[1]); - if(part[0] == "block") eval(block, part[1]); - - if(part[0] == "tileWidth") tileWidth = eval(part[1]); - if(part[0] == "tileHeight") tileHeight = eval(part[1]); - if(part[0] == "tileStride") tileStride = eval(part[1]); - if(part[0] == "tileOffset") tileOffset = eval(part[1]); - if(part[0] == "tile") eval(tile, part[1]); - - if(part[0] == "mosaicWidth") mosaicWidth = eval(part[1]); - if(part[0] == "mosaicHeight") mosaicHeight = eval(part[1]); - if(part[0] == "mosaicStride") mosaicStride = eval(part[1]); - if(part[0] == "mosaicOffset") mosaicOffset = eval(part[1]); - if(part[0] == "mosaic") eval(mosaic, part[1]); - - if(part[0] == "paddingWidth") paddingWidth = eval(part[1]); - if(part[0] == "paddingHeight") paddingHeight = eval(part[1]); - if(part[0] == "paddingColor") paddingColor = eval(part[1]); - if(part[0] == "palette") eval(palette, part[1]); - } - - sanitize(); - } - - inline bool load(const string &filename) { - string filedata; - if(filedata.readfile(filename) == false) return false; - parse(filedata); - return true; - } - - inline void sanitize() { - if(depth < 1) depth = 1; - if(depth > 24) depth = 24; - - if(blockWidth < 1) blockWidth = 1; - if(blockHeight < 1) blockHeight = 1; - - if(tileWidth < 1) tileWidth = 1; - if(tileHeight < 1) tileHeight = 1; - - if(mosaicWidth < 1) mosaicWidth = 1; - if(mosaicHeight < 1) mosaicHeight = 1; - } - - inline void reset() { - offset = 0; - width = 0; - height = 0; - count = 0; - - endian = 1; - order = 0; - depth = 1; - - blockWidth = 1; - blockHeight = 1; - blockStride = 0; - blockOffset = 0; - block.reset(); - - tileWidth = 1; - tileHeight = 1; - tileStride = 0; - tileOffset = 0; - tile.reset(); - - mosaicWidth = 1; - mosaicHeight = 1; - mosaicStride = 0; - mosaicOffset = 0; - mosaic.reset(); - - paddingWidth = 0; - paddingHeight = 0; - paddingColor = 0x000000; - palette.reset(); - } - - inline context() { - reset(); - } -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/mosaic/parser.hpp b/higan/phoenix/nall/mosaic/parser.hpp deleted file mode 100644 index b2c0b8ef..00000000 --- a/higan/phoenix/nall/mosaic/parser.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifdef NALL_MOSAIC_INTERNAL_HPP - -namespace nall { -namespace mosaic { - -struct parser { - image canvas; - - //export from bitstream to canvas - inline void load(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) { - canvas.allocate(width, height); - canvas.clear(ctx.paddingColor); - parse(1, stream, offset, ctx, width, height); - } - - //import from canvas to bitstream - inline bool save(bitstream &stream, uint64_t offset, context &ctx) { - if(stream.readonly) return false; - parse(0, stream, offset, ctx, canvas.width, canvas.height); - return true; - } - - inline parser() : canvas(0, 32, 0u, 255u << 16, 255u << 8, 255u << 0) { - } - -private: - inline uint32_t read(unsigned x, unsigned y) const { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return 0u; - uint32_t *buffer = (uint32_t*)canvas.data; - return buffer[addr]; - } - - inline void write(unsigned x, unsigned y, uint32_t data) { - unsigned addr = y * canvas.width + x; - if(addr >= canvas.width * canvas.height) return; - uint32_t *buffer = (uint32_t*)canvas.data; - buffer[addr] = data; - } - - inline void parse(bool load, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) { - stream.endian = ctx.endian; - unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth); - unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight); - unsigned bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight; - - unsigned objectOffset = 0; - for(unsigned objectY = 0; objectY < canvasHeight; objectY++) { - for(unsigned objectX = 0; objectX < canvasWidth; objectX++) { - if(objectOffset >= ctx.count && ctx.count > 0) break; - unsigned objectIX = objectX * ctx.objectWidth(); - unsigned objectIY = objectY * ctx.objectHeight(); - objectOffset++; - - unsigned mosaicOffset = 0; - for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) { - for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) { - unsigned mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset); - unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth); - unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight); - mosaicOffset++; - - unsigned tileOffset = 0; - for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) { - for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) { - unsigned tileData = ctx.tile(tileOffset, tileOffset); - unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth; - unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight; - tileOffset++; - - unsigned blockOffset = 0; - for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) { - for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) { - if(load) { - unsigned palette = 0; - for(unsigned n = 0; n < ctx.depth; n++) { - unsigned index = blockOffset++; - if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth); - palette |= stream.read(offset + ctx.block(index, index)) << n; - } - - write( - objectIX + mosaicIX + tileIX + blockX, - objectIY + mosaicIY + tileIY + blockY, - ctx.palette(palette, palette) - ); - } else /* save */ { - uint32_t palette = read( - objectIX + mosaicIX + tileIX + blockX, - objectIY + mosaicIY + tileIY + blockY - ); - - for(unsigned n = 0; n < ctx.depth; n++) { - unsigned index = blockOffset++; - if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth); - stream.write(offset + ctx.block(index, index), palette & 1); - palette >>= 1; - } - } - } //blockX - } //blockY - - offset += ctx.blockStride; - } //tileX - - offset += ctx.blockOffset; - } //tileY - - offset += ctx.tileStride; - } //mosaicX - - offset += ctx.tileOffset; - } //mosaicY - - offset += ctx.mosaicStride; - } //objectX - - offset += ctx.mosaicOffset; - } //objectY - } -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/nall.hpp b/higan/phoenix/nall/nall.hpp deleted file mode 100644 index a7887695..00000000 --- a/higan/phoenix/nall/nall.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef NALL_HPP -#define NALL_HPP - -//include the most common nall headers with one statement -//does not include the most obscure components with high cost and low usage - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(PLATFORM_WINDOWS) - #include - #include -#endif - -#if defined(PLATFORM_X) - #include -#endif - -#endif diff --git a/higan/phoenix/nall/platform.hpp b/higan/phoenix/nall/platform.hpp deleted file mode 100644 index 3326f4c4..00000000 --- a/higan/phoenix/nall/platform.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#if defined(_WIN32) - //minimum version needed for _wstat64, etc - #undef __MSVCRT_VERSION__ - #define __MSVCRT_VERSION__ 0x0601 - #include -#endif - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#if defined(_WIN32) - #include - #include - #include - #include - #undef interface - #define dllexport __declspec(dllexport) -#else - #include - #include - #define dllexport -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define putenv _putenv - #define vsnprintf _vsnprintf - inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); } -#endif - -//================ -//inline expansion -//================ - -#if defined(__clang__) || defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -//=========== -//unreachable -//=========== - -#if defined(__clang__) || defined(__GNUC__) - #define unreachable __builtin_unreachable() -#else - #define unreachable throw -#endif - -#endif diff --git a/higan/phoenix/nall/png.hpp b/higan/phoenix/nall/png.hpp deleted file mode 100644 index ef864228..00000000 --- a/higan/phoenix/nall/png.hpp +++ /dev/null @@ -1,337 +0,0 @@ -#ifndef NALL_PNG_HPP -#define NALL_PNG_HPP - -//PNG image decoder -//author: byuu - -#include -#include - -namespace nall { - -struct png { - //colorType: - //0 = L - //2 = R,G,B - //3 = P - //4 = L,A - //6 = R,G,B,A - struct Info { - unsigned width; - unsigned height; - unsigned bitDepth; - unsigned colorType; - unsigned compressionMethod; - unsigned filterType; - unsigned interlaceMethod; - - unsigned bytesPerPixel; - unsigned pitch; - - uint8_t palette[256][3]; - } info; - - uint8_t *data; - unsigned size; - - inline bool decode(const string &filename); - inline bool decode(const uint8_t *sourceData, unsigned sourceSize); - inline unsigned readbits(const uint8_t *&data); - unsigned bitpos; - - inline png(); - inline ~png(); - -protected: - enum class FourCC : unsigned { - IHDR = 0x49484452, - PLTE = 0x504c5445, - IDAT = 0x49444154, - IEND = 0x49454e44, - }; - - inline unsigned interlace(unsigned pass, unsigned index); - inline unsigned inflateSize(); - inline bool deinterlace(const uint8_t *&inputData, unsigned pass); - inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height); - inline unsigned read(const uint8_t *data, unsigned length); -}; - -bool png::decode(const string &filename) { - if(auto memory = file::read(filename)) { - return decode(memory.data(), memory.size()); - } - return false; -} - -bool png::decode(const uint8_t *sourceData, unsigned sourceSize) { - if(sourceSize < 8) return false; - if(read(sourceData + 0, 4) != 0x89504e47) return false; - if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false; - - uint8_t *compressedData = nullptr; - unsigned compressedSize = 0; - - unsigned offset = 8; - while(offset < sourceSize) { - unsigned length = read(sourceData + offset + 0, 4); - unsigned fourCC = read(sourceData + offset + 4, 4); - unsigned checksum = read(sourceData + offset + 8 + length, 4); - - if(fourCC == (unsigned)FourCC::IHDR) { - info.width = read(sourceData + offset + 8, 4); - info.height = read(sourceData + offset + 12, 4); - info.bitDepth = read(sourceData + offset + 16, 1); - info.colorType = read(sourceData + offset + 17, 1); - info.compressionMethod = read(sourceData + offset + 18, 1); - info.filterType = read(sourceData + offset + 19, 1); - info.interlaceMethod = read(sourceData + offset + 20, 1); - - if(info.bitDepth == 0 || info.bitDepth > 16) return false; - if(info.bitDepth & (info.bitDepth - 1)) return false; //not a power of two - if(info.compressionMethod != 0) return false; - if(info.filterType != 0) return false; - if(info.interlaceMethod != 0 && info.interlaceMethod != 1) return false; - - switch(info.colorType) { - case 0: info.bytesPerPixel = info.bitDepth * 1; break; //L - case 2: info.bytesPerPixel = info.bitDepth * 3; break; //R,G,B - case 3: info.bytesPerPixel = info.bitDepth * 1; break; //P - case 4: info.bytesPerPixel = info.bitDepth * 2; break; //L,A - case 6: info.bytesPerPixel = info.bitDepth * 4; break; //R,G,B,A - default: return false; - } - - if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6) - if(info.bitDepth != 8 && info.bitDepth != 16) return false; - if(info.colorType == 3 && info.bitDepth == 16) return false; - - info.bytesPerPixel = (info.bytesPerPixel + 7) / 8; - info.pitch = (int)info.width * info.bytesPerPixel; - } - - if(fourCC == (unsigned)FourCC::PLTE) { - if(length % 3) return false; - for(unsigned n = 0, p = offset + 8; n < length / 3; n++) { - info.palette[n][0] = sourceData[p++]; - info.palette[n][1] = sourceData[p++]; - info.palette[n][2] = sourceData[p++]; - } - } - - if(fourCC == (unsigned)FourCC::IDAT) { - compressedData = (uint8_t*)realloc(compressedData, compressedSize + length); - memcpy(compressedData + compressedSize, sourceData + offset + 8, length); - compressedSize += length; - } - - if(fourCC == (unsigned)FourCC::IEND) { - break; - } - - offset += 4 + 4 + length + 4; - } - - unsigned interlacedSize = inflateSize(); - uint8_t *interlacedData = new uint8_t[interlacedSize]; - - bool result = inflate(interlacedData, interlacedSize, compressedData + 2, compressedSize - 6); - delete[] compressedData; - - if(result == false) { - delete[] interlacedData; - return false; - } - - size = info.width * info.height * info.bytesPerPixel; - data = new uint8_t[size]; - - if(info.interlaceMethod == 0) { - if(filter(data, interlacedData, info.width, info.height) == false) { - delete[] interlacedData; - delete[] data; - data = nullptr; - return false; - } - } else { - const uint8_t *passData = interlacedData; - for(unsigned pass = 0; pass < 7; pass++) { - if(deinterlace(passData, pass) == false) { - delete[] interlacedData; - delete[] data; - data = nullptr; - return false; - } - } - } - - delete[] interlacedData; - return true; -} - -unsigned png::interlace(unsigned pass, unsigned index) { - static const unsigned data[7][4] = { - //x-distance, y-distance, x-origin, y-origin - {8, 8, 0, 0}, - {8, 8, 4, 0}, - {4, 8, 0, 4}, - {4, 4, 2, 0}, - {2, 4, 0, 2}, - {2, 2, 1, 0}, - {1, 2, 0, 1}, - }; - return data[pass][index]; -} - -unsigned png::inflateSize() { - if(info.interlaceMethod == 0) { - return info.width * info.height * info.bytesPerPixel + info.height; - } - - unsigned size = 0; - for(unsigned pass = 0; pass < 7; pass++) { - unsigned xd = interlace(pass, 0), yd = interlace(pass, 1); - unsigned xo = interlace(pass, 2), yo = interlace(pass, 3); - unsigned width = (info.width + (xd - xo - 1)) / xd; - unsigned height = (info.height + (yd - yo - 1)) / yd; - if(width == 0 || height == 0) continue; - size += width * height * info.bytesPerPixel + height; - } - return size; -} - -bool png::deinterlace(const uint8_t *&inputData, unsigned pass) { - unsigned xd = interlace(pass, 0), yd = interlace(pass, 1); - unsigned xo = interlace(pass, 2), yo = interlace(pass, 3); - unsigned width = (info.width + (xd - xo - 1)) / xd; - unsigned height = (info.height + (yd - yo - 1)) / yd; - if(width == 0 || height == 0) return true; - - unsigned outputSize = width * height * info.bytesPerPixel; - uint8_t *outputData = new uint8_t[outputSize]; - bool result = filter(outputData, inputData, width, height); - - const uint8_t *rd = outputData; - for(unsigned y = yo; y < info.height; y += yd) { - uint8_t *wr = data + y * info.pitch; - for(unsigned x = xo; x < info.width; x += xd) { - for(unsigned b = 0; b < info.bytesPerPixel; b++) { - wr[x * info.bytesPerPixel + b] = *rd++; - } - } - } - - inputData += outputSize + height; - delete[] outputData; - return result; -} - -bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height) { - uint8_t *wr = outputData; - const uint8_t *rd = inputData; - int bpp = info.bytesPerPixel, pitch = width * bpp; - for(int y = 0; y < height; y++) { - uint8_t filter = *rd++; - - switch(filter) { - case 0x00: //None - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x]; - } - break; - - case 0x01: //Subtract - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x] + (x - bpp < 0 ? 0 : wr[x - bpp]); - } - break; - - case 0x02: //Above - for(int x = 0; x < pitch; x++) { - wr[x] = rd[x] + (y - 1 < 0 ? 0 : wr[x - pitch]); - } - break; - - case 0x03: //Average - for(int x = 0; x < pitch; x++) { - short a = x - bpp < 0 ? 0 : wr[x - bpp]; - short b = y - 1 < 0 ? 0 : wr[x - pitch]; - - wr[x] = rd[x] + (uint8_t)((a + b) / 2); - } - break; - - case 0x04: //Paeth - for(int x = 0; x < pitch; x++) { - short a = x - bpp < 0 ? 0 : wr[x - bpp]; - short b = y - 1 < 0 ? 0 : wr[x - pitch]; - short c = x - bpp < 0 || y - 1 < 0 ? 0 : wr[x - pitch - bpp]; - - short p = a + b - c; - short pa = p > a ? p - a : a - p; - short pb = p > b ? p - b : b - p; - short pc = p > c ? p - c : c - p; - - uint8_t paeth = (uint8_t)((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c); - - wr[x] = rd[x] + paeth; - } - break; - - default: //Invalid - return false; - } - - rd += pitch; - wr += pitch; - } - - return true; -} - -unsigned png::read(const uint8_t *data, unsigned length) { - unsigned result = 0; - while(length--) result = (result << 8) | (*data++); - return result; -} - -unsigned png::readbits(const uint8_t *&data) { - unsigned result = 0; - switch(info.bitDepth) { - case 1: - result = (*data >> bitpos) & 1; - bitpos++; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 2: - result = (*data >> bitpos) & 3; - bitpos += 2; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 4: - result = (*data >> bitpos) & 15; - bitpos += 4; - if(bitpos == 8) { data++; bitpos = 0; } - break; - case 8: - result = *data++; - break; - case 16: - result = (data[0] << 8) | (data[1] << 0); - data += 2; - break; - } - return result; -} - -png::png() : data(nullptr) { - bitpos = 0; -} - -png::~png() { - if(data) delete[] data; -} - -} - -#endif diff --git a/higan/phoenix/nall/priority-queue.hpp b/higan/phoenix/nall/priority-queue.hpp deleted file mode 100644 index 1aedc6f1..00000000 --- a/higan/phoenix/nall/priority-queue.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NALL_PRIORITY_QUEUE_HPP -#define NALL_PRIORITY_QUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) append (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - void serialize(serializer &s) { - s.integer(basecounter); - s.integer(heapsize); - for(unsigned n = 0; n < heapcapacity; n++) { - s.integer(heap[n].counter); - s.integer(heap[n].event); - } - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/higan/phoenix/nall/property.hpp b/higan/phoenix/nall/property.hpp deleted file mode 100644 index 1ddb5c9b..00000000 --- a/higan/phoenix/nall/property.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead of T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -namespace nall { - template struct property { - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - private: - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - friend C; - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - private: - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - friend C; - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/higan/phoenix/nall/public-cast.hpp b/higan/phoenix/nall/public-cast.hpp deleted file mode 100644 index 331800e1..00000000 --- a/higan/phoenix/nall/public-cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_PUBLIC_CAST_HPP -#define NALL_PUBLIC_CAST_HPP - -//this is a proof-of-concept-*only* C++ access-privilege elevation exploit. -//this code is 100% legal C++, per C++98 section 14.7.2 paragraph 8: -//"access checking rules do not apply to names in explicit instantiations." -//usage example: - -//struct N { typedef void (Class::*)(); }; -//template class public_cast; -//(class.*public_cast::value); - -//Class::Reference may be public, protected or private -//Class::Reference may be a function, object or variable - -namespace nall { - template struct public_cast; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value; - - template struct public_cast { - static typename T::type value; - }; - - template typename T::type public_cast::value = public_cast::value = P; -} - -#endif diff --git a/higan/phoenix/nall/random.hpp b/higan/phoenix/nall/random.hpp deleted file mode 100644 index 409c4561..00000000 --- a/higan/phoenix/nall/random.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NALL_RANDOM_HPP -#define NALL_RANDOM_HPP - -namespace nall { - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } - - struct random_lfsr { - inline void seed(unsigned seed__) { - seed_ = seed__; - } - - inline unsigned operator()() { - return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320); - } - - random_lfsr() : seed_(0) { - } - - private: - unsigned seed_; - }; -} - -#endif diff --git a/higan/phoenix/nall/serial.hpp b/higan/phoenix/nall/serial.hpp deleted file mode 100644 index da87ae50..00000000 --- a/higan/phoenix/nall/serial.hpp +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - struct serial { - bool readable() { - if(port_open == false) return false; - fd_set fdset; - FD_ZERO(&fdset); - FD_SET(port, &fdset); - timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - int result = select(FD_SETSIZE, &fdset, nullptr, nullptr, &timeout); - if(result < 1) return false; - return FD_ISSET(port, &fdset); - } - - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - bool writable() { - if(port_open == false) return false; - fd_set fdset; - FD_ZERO(&fdset); - FD_SET(port, &fdset); - timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 0; - int result = select(FD_SETSIZE, nullptr, &fdset, nullptr, &timeout); - if(result < 1) return false; - return FD_ISSET(port, &fdset); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate, bool flowcontrol) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL); - attr.c_cflag |= (CS8 | CREAD); - if(flowcontrol == false) { - attr.c_cflag &= ~CRTSCTS; - } else { - attr.c_cflag |= CRTSCTS; - } - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/higan/phoenix/nall/serializer.hpp b/higan/phoenix/nall/serializer.hpp deleted file mode 100644 index a616cbdf..00000000 --- a/higan/phoenix/nall/serializer.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(nullptr) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = nullptr; - return *this; - } - - serializer(serializer &&s) { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = nullptr; - isize = 0; - icapacity = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/higan/phoenix/nall/set.hpp b/higan/phoenix/nall/set.hpp deleted file mode 100644 index c6d3d06e..00000000 --- a/higan/phoenix/nall/set.hpp +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef NALL_SET_HPP -#define NALL_SET_HPP - -//set -//* unordered -//* intended for unique items -//* dynamic growth -//* reference-based variant - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - -template struct set; - -template struct set::value>::type> { - struct exception_out_of_bounds{}; - -protected: - T *pool; - unsigned poolsize, objectsize; - -public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } -}; - -//reference set -template struct set::value>::type> { - struct exception_out_of_bounds{}; - -protected: - typedef typename std::remove_reference::type T; - T **pool; - unsigned poolsize, objectsize; - -public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned size) { - if(size == poolsize) return; - pool = (T**)realloc(pool, sizeof(T*) * size); - poolsize = size; - objectsize = min(objectsize, size); - } - - void resize(unsigned size) { - if(size > poolsize) reserve(bit::round(size)); //amortize growth - objectsize = size; - } - - bool append(T& data) { - if(find(data)) return false; - unsigned offset = objectsize++; - if(offset >= poolsize) resize(offset + 1); - pool[offset] = &data; - return true; - } - - template - bool append(T& data, Args&&... args) { - bool result = append(data); - append(std::forward(args)...); - return result; - } - - bool remove(T& data) { - if(auto position = find(data)) { - for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1]; - resize(objectsize - 1); - return true; - } - return false; - } - - optional find(const T& data) { - for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return {true, n}; - return {false, 0u}; - } - - template set(Args&&... args) : pool(nullptr), poolsize(0), objectsize(0) { - construct(std::forward(args)...); - } - - ~set() { - reset(); - } - - set& operator=(const set &source) { - if(&source == this) return *this; - if(pool) free(pool); - objectsize = source.objectsize; - poolsize = source.poolsize; - pool = (T**)malloc(sizeof(T*) * poolsize); - memcpy(pool, source.pool, sizeof(T*) * objectsize); - return *this; - } - - set& operator=(const set &&source) { - if(&source == this) return *this; - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = nullptr; - source.reset(); - return *this; - } - - T& operator[](unsigned position) const { - if(position >= objectsize) throw exception_out_of_bounds(); - return *pool[position]; - } - - struct iterator { - bool operator!=(const iterator &source) const { return position != source.position; } - T& operator*() { return source.operator[](position); } - iterator& operator++() { position++; return *this; } - iterator(const set &source, unsigned position) : source(source), position(position) {} - private: - const set &source; - unsigned position; - }; - - iterator begin() { return iterator(*this, 0); } - iterator end() { return iterator(*this, objectsize); } - const iterator begin() const { return iterator(*this, 0); } - const iterator end() const { return iterator(*this, objectsize); } - -private: - void construct() {} - void construct(const set &source) { operator=(source); } - void construct(const set &&source) { operator=(std::move(source)); } - template void construct(T& data, Args&&... args) { - append(data); - construct(std::forward(args)...); - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/sha256.hpp b/higan/phoenix/nall/sha256.hpp deleted file mode 100644 index c63367a7..00000000 --- a/higan/phoenix/nall/sha256.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -#include - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - inline void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - inline void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - inline void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - inline void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/higan/phoenix/nall/sort.hpp b/higan/phoenix/nall/sort.hpp deleted file mode 100644 index 8326ab1d..00000000 --- a/higan/phoenix/nall/sort.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//note: merge sort was chosen over quick sort, because: -//* it is a stable sort -//* it lacks O(n^2) worst-case overhead - -#define NALL_SORT_INSERTION -//#define NALL_SORT_SELECTION - -namespace nall { - template - void sort(T list[], unsigned size, const Comparator &lessthan) { - if(size <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(size < 64) { - #if defined(NALL_SORT_INSERTION) - for(signed i = 1, j; i < size; i++) { - T copy = std::move(list[i]); - for(j = i - 1; j >= 0; j--) { - if(!lessthan(copy, list[j])) break; - list[j + 1] = std::move(list[j]); - } - list[j + 1] = std::move(copy); - } - #elif defined(NALL_SORT_SELECTION) - for(unsigned i = 0; i < size; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < size; j++) { - if(lessthan(list[j], list[min])) min = j; - } - if(min != i) std::swap(list[i], list[min]); - } - #endif - return; - } - - //split list in half and recursively sort both - unsigned middle = size / 2; - sort(list, middle, lessthan); - sort(list + middle, size - middle, lessthan); - - //left and right are sorted here; perform merge sort - T *buffer = new T[size]; - unsigned offset = 0, left = 0, right = middle; - while(left < middle && right < size) { - if(!lessthan(list[right], list[left])) { - buffer[offset++] = std::move(list[left++]); - } else { - buffer[offset++] = std::move(list[right++]); - } - } - while(left < middle) buffer[offset++] = std::move(list[left++]); - while(right < size) buffer[offset++] = std::move(list[right++]); - - for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]); - delete[] buffer; - } - - template - void sort(T list[], unsigned size) { - return sort(list, size, [](const T &l, const T &r) { return l < r; }); - } -} - -#endif diff --git a/higan/phoenix/nall/stdint.hpp b/higan/phoenix/nall/stdint.hpp deleted file mode 100644 index c63f5912..00000000 --- a/higan/phoenix/nall/stdint.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/higan/phoenix/nall/stream.hpp b/higan/phoenix/nall/stream.hpp deleted file mode 100644 index 586ccda7..00000000 --- a/higan/phoenix/nall/stream.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STREAM_HPP -#define NALL_STREAM_HPP - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define NALL_STREAM_INTERNAL_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#undef NALL_STREAM_INTERNAL_HPP - -#endif diff --git a/higan/phoenix/nall/stream/auto.hpp b/higan/phoenix/nall/stream/auto.hpp deleted file mode 100644 index d1b6e2ba..00000000 --- a/higan/phoenix/nall/stream/auto.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef NALL_STREAM_AUTO_HPP -#define NALL_STREAM_AUTO_HPP - -namespace nall { - -#define autostream(...) (*makestream(__VA_ARGS__)) - -inline std::unique_ptr makestream(const string &path) { - if(path.ibeginswith("http://")) return std::unique_ptr(new httpstream(path, 80)); - if(path.iendswith(".gz")) return std::unique_ptr(new gzipstream(filestream{path})); - if(path.iendswith(".zip")) return std::unique_ptr(new zipstream(filestream{path})); - return std::unique_ptr(new mmapstream(path)); -} - -inline std::unique_ptr makestream(uint8_t *data, unsigned size) { - return std::unique_ptr(new memorystream(data, size)); -} - -inline std::unique_ptr makestream(const uint8_t *data, unsigned size) { - return std::unique_ptr(new memorystream(data, size)); -} - -} - -#endif diff --git a/higan/phoenix/nall/stream/file.hpp b/higan/phoenix/nall/stream/file.hpp deleted file mode 100644 index 878418cf..00000000 --- a/higan/phoenix/nall/stream/file.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_STREAM_FILE_HPP -#define NALL_STREAM_FILE_HPP - -#include - -namespace nall { - -struct filestream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return pwritable; } - bool randomaccess() const { return false; } - - unsigned size() const { return pfile.size(); } - unsigned offset() const { return pfile.offset(); } - void seek(unsigned offset) const { pfile.seek(offset); } - - uint8_t read() const { return pfile.read(); } - void write(uint8_t data) const { pfile.write(data); } - - filestream(const string &filename) { - pfile.open(filename, file::mode::readwrite); - pwritable = pfile.open(); - if(!pwritable) pfile.open(filename, file::mode::read); - } - - filestream(const string &filename, file::mode mode) { - pfile.open(filename, mode); - pwritable = mode == file::mode::write || mode == file::mode::readwrite; - } - -private: - mutable file pfile; - bool pwritable; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/gzip.hpp b/higan/phoenix/nall/stream/gzip.hpp deleted file mode 100644 index 0c270a72..00000000 --- a/higan/phoenix/nall/stream/gzip.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef NALL_STREAM_GZIP_HPP -#define NALL_STREAM_GZIP_HPP - -#include - -namespace nall { - -struct gzipstream : memorystream { - using stream::read; - using stream::write; - - gzipstream(const stream &stream) { - unsigned size = stream.size(); - uint8_t *data = new uint8_t[size]; - stream.read(data, size); - - gzip archive; - bool result = archive.decompress(data, size); - delete[] data; - if(result == false) return; - - psize = archive.size; - pdata = new uint8_t[psize]; - memcpy(pdata, archive.data, psize); - } - - ~gzipstream() { - if(pdata) delete[] pdata; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/http.hpp b/higan/phoenix/nall/stream/http.hpp deleted file mode 100644 index 2f9e45dd..00000000 --- a/higan/phoenix/nall/stream/http.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef NALL_STREAM_HTTP_HPP -#define NALL_STREAM_HTTP_HPP - -#include - -namespace nall { - -struct httpstream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return true; } - bool randomaccess() const { return true; } - - unsigned size() const { return psize; } - unsigned offset() const { return poffset; } - void seek(unsigned offset) const { poffset = offset; } - - uint8_t read() const { return pdata[poffset++]; } - void write(uint8_t data) const { pdata[poffset++] = data; } - - uint8_t read(unsigned offset) const { return pdata[offset]; } - void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) { - string uri = url; - uri.ltrim<1>("http://"); - lstring part = uri.split<1>("/"); - part[1] = { "/", part[1] }; - - http connection; - if(connection.connect(part[0], port) == false) return; - connection.download(part[1], pdata, psize); - } - - ~httpstream() { - if(pdata) delete[] pdata; - } - -private: - mutable uint8_t *pdata; - mutable unsigned psize, poffset; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/memory.hpp b/higan/phoenix/nall/stream/memory.hpp deleted file mode 100644 index cf49b3b2..00000000 --- a/higan/phoenix/nall/stream/memory.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef NALL_STREAM_MEMORY_HPP -#define NALL_STREAM_MEMORY_HPP - -#include - -namespace nall { - -struct memorystream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return pwritable; } - bool randomaccess() const { return true; } - - uint8_t *data() const { return pdata; } - unsigned size() const { return psize; } - unsigned offset() const { return poffset; } - void seek(unsigned offset) const { poffset = offset; } - - uint8_t read() const { return pdata[poffset++]; } - void write(uint8_t data) const { pdata[poffset++] = data; } - - uint8_t read(unsigned offset) const { return pdata[offset]; } - void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {} - - memorystream(uint8_t *data, unsigned size) { - pdata = data, psize = size, poffset = 0; - pwritable = true; - } - - memorystream(const uint8_t *data, unsigned size) { - pdata = (uint8_t*)data, psize = size, poffset = 0; - pwritable = false; - } - -protected: - mutable uint8_t *pdata; - mutable unsigned psize, poffset, pwritable; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/mmap.hpp b/higan/phoenix/nall/stream/mmap.hpp deleted file mode 100644 index ce30f810..00000000 --- a/higan/phoenix/nall/stream/mmap.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef NALL_STREAM_MMAP_HPP -#define NALL_STREAM_MMAP_HPP - -#include - -namespace nall { - -struct mmapstream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return pwritable; } - bool randomaccess() const { return true; } - - unsigned size() const { return pmmap.size(); } - unsigned offset() const { return poffset; } - void seek(unsigned offset) const { poffset = offset; } - - uint8_t read() const { return pdata[poffset++]; } - void write(uint8_t data) const { pdata[poffset++] = data; } - - uint8_t read(unsigned offset) const { return pdata[offset]; } - void write(unsigned offset, uint8_t data) const { pdata[offset] = data; } - - mmapstream(const string &filename) { - pmmap.open(filename, filemap::mode::readwrite); - pwritable = pmmap.open(); - if(!pwritable) pmmap.open(filename, filemap::mode::read); - pdata = pmmap.data(), poffset = 0; - } - -private: - mutable filemap pmmap; - mutable uint8_t *pdata; - mutable unsigned pwritable, poffset; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/stream.hpp b/higan/phoenix/nall/stream/stream.hpp deleted file mode 100644 index 043eecba..00000000 --- a/higan/phoenix/nall/stream/stream.hpp +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef NALL_STREAM_STREAM_HPP -#define NALL_STREAM_STREAM_HPP - -namespace nall { - -struct stream { - virtual bool seekable() const = 0; - virtual bool readable() const = 0; - virtual bool writable() const = 0; - virtual bool randomaccess() const = 0; - - virtual uint8_t* data() const { return nullptr; } - virtual unsigned size() const = 0; - virtual unsigned offset() const = 0; - virtual void seek(unsigned offset) const = 0; - - virtual uint8_t read() const = 0; - virtual void write(uint8_t data) const = 0; - - virtual uint8_t read(unsigned) const { return 0; } - virtual void write(unsigned, uint8_t) const {} - - operator bool() const { - return size(); - } - - bool empty() const { - return size() == 0; - } - - bool end() const { - return offset() >= size(); - } - - uintmax_t readl(unsigned length = 1) const { - uintmax_t data = 0, shift = 0; - while(length--) { data |= read() << shift; shift += 8; } - return data; - } - - uintmax_t readm(unsigned length = 1) const { - uintmax_t data = 0; - while(length--) data = (data << 8) | read(); - return data; - } - - void read(uint8_t *data, unsigned length) const { - while(length--) *data++ = read(); - } - - string text() const { - string buffer; - buffer.resize(size() + 1); - buffer[size()] = 0; - seek(0); - read((uint8_t*)buffer(), size()); - return buffer; - } - - void writel(uintmax_t data, unsigned length = 1) const { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) const { - uintmax_t shift = 8 * length; - while(length--) { - shift -= 8; - write(data >> shift); - } - } - - void write(const uint8_t *data, unsigned length) const { - while(length--) write(*data++); - } - - struct byte { - operator uint8_t() const { return s.read(offset); } - byte& operator=(uint8_t data) { s.write(offset, data); return *this; } - byte(const stream &s, unsigned offset) : s(s), offset(offset) {} - - private: - const stream &s; - const unsigned offset; - }; - - byte operator[](unsigned offset) const { - return byte(*this, offset); - } - - stream() {} - virtual ~stream() {} - stream(const stream&) = delete; - stream& operator=(const stream&) = delete; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/vector.hpp b/higan/phoenix/nall/stream/vector.hpp deleted file mode 100644 index 59f36c02..00000000 --- a/higan/phoenix/nall/stream/vector.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef NALL_STREAM_VECTOR_HPP -#define NALL_STREAM_VECTOR_HPP - -#include -#include - -namespace nall { - -struct vectorstream : stream { - using stream::read; - using stream::write; - - bool seekable() const { return true; } - bool readable() const { return true; } - bool writable() const { return pwritable; } - bool randomaccess() const { return true; } - - uint8_t* data() const { return memory.data(); } - unsigned size() const { return memory.size(); } - unsigned offset() const { return poffset; } - void seek(unsigned offset) const { poffset = offset; } - - uint8_t read() const { return memory[poffset++]; } - void write(uint8_t data) const { memory[poffset++] = data; } - - uint8_t read(unsigned offset) const { return memory[offset]; } - void write(unsigned offset, uint8_t data) const { memory[offset] = data; } - - vectorstream(vector &memory) : memory(memory), poffset(0), pwritable(true) {} - vectorstream(const vector &memory) : memory((vector&)memory), poffset(0), pwritable(false) {} - -protected: - vector &memory; - mutable unsigned poffset, pwritable; -}; - -} - -#endif diff --git a/higan/phoenix/nall/stream/zip.hpp b/higan/phoenix/nall/stream/zip.hpp deleted file mode 100644 index 94aa3992..00000000 --- a/higan/phoenix/nall/stream/zip.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_STREAM_ZIP_HPP -#define NALL_STREAM_ZIP_HPP - -#include - -namespace nall { - -struct zipstream : memorystream { - using stream::read; - using stream::write; - - zipstream(const stream &stream, const string &filter = "*") { - unsigned size = stream.size(); - uint8_t *data = new uint8_t[size]; - stream.read(data, size); - - unzip archive; - if(archive.open(data, size) == false) return; - delete[] data; - - for(auto &file : archive.file) { - if(file.name.wildcard(filter)) { - auto buffer = archive.extract(file); - psize = buffer.size(); - pdata = buffer.move(); - return; - } - } - } - - ~zipstream() { - if(pdata) delete[] pdata; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/string.hpp b/higan/phoenix/nall/string.hpp deleted file mode 100644 index 82b7cde4..00000000 --- a/higan/phoenix/nall/string.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NALL_STRING_INTERNAL_HPP -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#undef NALL_STRING_INTERNAL_HPP - -#endif diff --git a/higan/phoenix/nall/string/base.hpp b/higan/phoenix/nall/string/base.hpp deleted file mode 100644 index 7a1e55fb..00000000 --- a/higan/phoenix/nall/string/base.hpp +++ /dev/null @@ -1,231 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - struct cstring; - struct string; - struct lstring; - template inline const char* to_string(T); - - struct cstring { - inline operator const char*() const; - inline unsigned length() const; - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline optional position(const char *key) const; - inline optional iposition(const char *key) const; - inline cstring& operator=(const char *data); - inline cstring(const char *data); - inline cstring(); - - protected: - const char *data; - }; - - struct string { - //deprecated: use string text = file::read(filename); - inline static string read(const string &filename); - - inline static string date(); - inline static string time(); - inline static string datetime(); - - inline void reserve(unsigned); - inline void resize(unsigned); - inline void clear(char); - inline bool empty() const; - - template inline string& assign(Args&&... args); - template inline string& append(Args&&... args); - - inline bool readfile(const string&); - - template inline string& replace(const char*, const char*); - template inline string& ireplace(const char*, const char*); - template inline string& qreplace(const char*, const char*); - template inline string& iqreplace(const char*, const char*); - - inline unsigned length() const; - inline unsigned capacity() const; - - template inline lstring split(const char*) const; - template inline lstring isplit(const char*) const; - template inline lstring qsplit(const char*) const; - template inline lstring iqsplit(const char*) const; - - inline bool equals(const char*) const; - inline bool iequals(const char*) const; - - inline bool wildcard(const char*) const; - inline bool iwildcard(const char*) const; - - inline bool beginswith(const char*) const; - inline bool ibeginswith(const char*) const; - inline bool endswith(const char*) const; - inline bool iendswith(const char*) const; - - inline string& lower(); - inline string& upper(); - inline string& qlower(); - inline string& qupper(); - inline string& transform(const char *before, const char *after); - inline string& reverse(); - - template inline string& ltrim(const char *key = " "); - template inline string& rtrim(const char *key = " "); - template inline string& trim(const char *key = " ", const char *rkey = nullptr); - inline string& strip(); - - inline optional position(const char *key) const; - inline optional iposition(const char *key) const; - inline optional qposition(const char *key) const; - inline optional iqposition(const char *key) const; - - inline explicit operator bool() const; - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string& operator=(const string&); - inline string& operator=(string&&); - - template inline string(Args&&... args); - inline string(const string&); - inline string(string&&); - inline ~string(); - - inline char* begin() { return &data[0]; } - inline char* end() { return &data[length()]; } - inline const char* begin() const { return &data[0]; } - inline const char* end() const { return &data[length()]; } - - //internal functions - inline string& assign_(const char*); - inline string& append_(const char*); - - protected: - char *data; - unsigned size; - - template inline string& ureplace(const char*, const char*); - - #if defined(QSTRING_H) - public: - inline operator QString() const; - #endif - }; - - struct lstring : vector { - inline optional find(const char*) const; - inline string concatenate(const char*) const; - inline void append() {} - inline void isort(); - template inline void append(const string&, Args&&...); - - template inline lstring& split(const char*, const char*); - template inline lstring& isplit(const char*, const char*); - template inline lstring& qsplit(const char*, const char*); - template inline lstring& iqsplit(const char*, const char*); - - inline bool operator==(const lstring&) const; - inline bool operator!=(const lstring&) const; - - inline lstring& operator=(const lstring&); - inline lstring& operator=(lstring&); - inline lstring& operator=(lstring&&); - - template inline lstring(Args&&... args); - inline lstring(const lstring&); - inline lstring(lstring&); - inline lstring(lstring&&); - - protected: - template inline lstring& usplit(const char*, const char*); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int istrcmp(const char *str1, const char *str2); - inline bool strbegin(const char *str, const char *key); - inline bool istrbegin(const char *str, const char *key); - inline bool strend(const char *str, const char *key); - inline bool istrend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* qstrlower(char *str); - inline char* qstrupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - - //format.hpp - template inline string format(const string &value); - template inline string hex(uintmax_t value); - template inline string octal(uintmax_t value); - template inline string binary(uintmax_t value); - - //math.hpp - inline bool strint(const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //platform.hpp - inline string activepath(); - inline string realpath(const string &name); - inline string userpath(); - inline string configpath(); - inline string temppath(); - - //strm.hpp - inline unsigned strmcpy(char *target, const char *source, unsigned length); - inline unsigned strmcat(char *target, const char *source, unsigned length); - inline bool strccpy(char *target, const char *source, unsigned length); - inline bool strccat(char *target, const char *source, unsigned length); - inline void strpcpy(char *&target, const char *source, unsigned &length); - - //strpos.hpp - inline optional strpos(const char *str, const char *key); - inline optional istrpos(const char *str, const char *key); - inline optional qstrpos(const char *str, const char *key); - inline optional iqstrpos(const char *str, const char *key); - template inline optional ustrpos(const char *str, const char *key); - - //trim.hpp - template inline char* ltrim(char *str, const char *key = " "); - template inline char* rtrim(char *str, const char *key = " "); - template inline char* trim(char *str, const char *key = " ", const char *rkey = nullptr); - inline char* strip(char *s); - - //utility.hpp - template alwaysinline bool chrequal(char x, char y); - template alwaysinline bool quoteskip(T *&p); - template alwaysinline bool quotecopy(char *&t, T *&p); - inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u); - inline string sha256(const uint8_t *data, unsigned size); - - inline char* integer(char *result, intmax_t value); - inline char* decimal(char *result, uintmax_t value); - - //these functions are deprecated, use format() instead: - template inline string integer(intmax_t value); - template inline string linteger(intmax_t value); - template inline string decimal(uintmax_t value); - template inline string ldecimal(uintmax_t value); - inline unsigned fp(char *str, long double value); - inline string fp(long double value); - - //variadic.hpp - template inline void print(Args&&... args); - - //wildcard.hpp - inline bool wildcard(const char *str, const char *pattern); - inline bool iwildcard(const char *str, const char *pattern); -}; - -#endif diff --git a/higan/phoenix/nall/string/bsv.hpp b/higan/phoenix/nall/string/bsv.hpp deleted file mode 100644 index d9415d53..00000000 --- a/higan/phoenix/nall/string/bsv.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//BSV v1.0 parser -//revision 0.02 - -namespace nall { - -struct BSV { - static inline string decode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '}' ) return ""; - if(*input == '\r') return ""; - if(*input == '\n') return ""; - - //normal characters - if(*input != '{') { output[offset++] = *input++; continue; } - - //entities - if(strbegin(input, "{lf}")) { output[offset++] = '\n'; input += 4; continue; } - if(strbegin(input, "{lb}")) { output[offset++] = '{'; input += 4; continue; } - if(strbegin(input, "{rb}")) { output[offset++] = '}'; input += 4; continue; } - - //illegal entities - return ""; - } - output[offset] = 0; - return output; - } - - static inline string encode(const char *input) { - string output; - unsigned offset = 0; - while(*input) { - //illegal characters - if(*input == '\r') return ""; - - if(*input == '\n') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'f'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '{') { - output[offset++] = '{'; - output[offset++] = 'l'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - if(*input == '}') { - output[offset++] = '{'; - output[offset++] = 'r'; - output[offset++] = 'b'; - output[offset++] = '}'; - input++; - continue; - } - - output[offset++] = *input++; - } - output[offset] = 0; - return output; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/string/cast.hpp b/higan/phoenix/nall/string/cast.hpp deleted file mode 100644 index eee42177..00000000 --- a/higan/phoenix/nall/string/cast.hpp +++ /dev/null @@ -1,211 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//convert any (supported) type to a const char* without constructing a new nall::string -//this is used inside istring(...) to build nall::string values -template struct stringify; - -// base types - -template<> struct stringify { - bool value; - operator const char*() const { return value ? "true" : "false"; } - stringify(bool value) : value(value) {} -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(char value) { integer(data, value); } -}; - -// signed integers - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed char value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed short value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed int value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed long value) { integer(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(signed long long value) { integer(data, value); } -}; - -template struct stringify> { - char data[256]; - operator const char*() const { return data; } - stringify(int_t value) { integer(data, value); } -}; - -// unsigned integers - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned char value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned short value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned int value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long value) { decimal(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(unsigned long long value) { decimal(data, value); } -}; - -template struct stringify> { - char data[256]; - operator const char*() const { return data; } - stringify(uint_t value) { decimal(data, value); } -}; - -// floating-point - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(float value) { fp(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(double value) { fp(data, value); } -}; - -template<> struct stringify { - char data[256]; - operator const char*() const { return data; } - stringify(long double value) { fp(data, value); } -}; - -// arrays - -template<> struct stringify> { - char *text; - operator const char*() const { return text; } - stringify(vector value) { - text = new char[value.size() + 1](); - memcpy(text, value.data(), value.size()); - } - ~stringify() { - delete[] text; - } -}; - -template<> struct stringify&> { - char *text; - operator const char*() const { return text; } - stringify(const vector &value) { - text = new char[value.size() + 1](); - memcpy(text, value.data(), value.size()); - } - ~stringify() { - delete[] text; - } -}; - -// strings - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(char *value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const char *value) : value(value) {} -}; - -template<> struct stringify { - const string &value; - operator const char*() const { return value; } - stringify(const string &value) : value(value) {} -}; - -template<> struct stringify { - const string &value; - operator const char*() const { return value; } - stringify(const string &value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const cstring &value) : value(value) {} -}; - -template<> struct stringify { - const char *value; - operator const char*() const { return value; } - stringify(const cstring &value) : value(value) {} -}; - -#if defined(QSTRING_H) - -template<> struct stringify { - const QString &value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString &value) : value(value) {} -}; - -template<> struct stringify { - const QString &value; - operator const char*() const { return value.toUtf8().constData(); } - stringify(const QString &value) : value(value) {} -}; - -string::operator QString() const { - return QString::fromUtf8(*this); -} - -#endif - -// - -template stringify make_string(T value) { - return stringify(std::forward(value)); -} - -} - -#endif diff --git a/higan/phoenix/nall/string/compare.hpp b/higan/phoenix/nall/string/compare.hpp deleted file mode 100644 index 941c8e67..00000000 --- a/higan/phoenix/nall/string/compare.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int istrcmp(const char *str1, const char *str2) { - while(*str1) { - if(chrlower(*str1) != chrlower(*str2)) break; - str1++, str2++; - } - return (int)chrlower(*str1) - (int)chrlower(*str2); -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool istrbegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool istrend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/convert.hpp b/higan/phoenix/nall/string/convert.hpp deleted file mode 100644 index 27448770..00000000 --- a/higan/phoenix/nall/string/convert.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return nullptr; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return nullptr; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* qstrlower(char *s) { - if(!s) return nullptr; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'A' && *s <= 'Z') *s += 0x20; - s++; - } -} - -char* qstrupper(char *s) { - if(!s) return nullptr; - bool quoted = false; - while(*s) { - if(*s == '\"' || *s == '\'') quoted ^= 1; - if(quoted == false && *s >= 'a' && *s <= 'z') *s -= 0x20; - s++; - } -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/core.hpp b/higan/phoenix/nall/string/core.hpp deleted file mode 100644 index 043c575b..00000000 --- a/higan/phoenix/nall/string/core.hpp +++ /dev/null @@ -1,217 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -static void istring(string &output) { -} - -template -static void istring(string &output, const T &value, Args&&... args) { - output.append_(make_string(value)); - istring(output, std::forward(args)...); -} - -void string::reserve(unsigned size_) { - if(size_ > size) resize(size_); -} - -void string::resize(unsigned size_) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; -} - -void string::clear(char c) { - for(unsigned n = 0; n < size; n++) data[n] = c; - data[size] = 0; -} - -bool string::empty() const { - return !*data; -} - -template string& string::assign(Args&&... args) { - *data = 0; - istring(*this, std::forward(args)...); - return *this; -} - -template string& string::append(Args&&... args) { - istring(*this, std::forward(args)...); - return *this; -} - -string& string::assign_(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append_(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator bool() const { - return !empty(); -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string& string::operator=(const string &value) { - if(&value == this) return *this; - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(&source == this) return *this; - if(data) free(data); - size = source.size; - data = source.data; - source.data = nullptr; - source.size = 0; - return *this; -} - -template string::string(Args&&... args) { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; - istring(*this, std::forward(args)...); -} - -string::string(const string &value) { - if(&value == this) return; - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - if(&source == this) return; - size = source.size; - data = source.data; - source.data = nullptr; -} - -string::~string() { - if(data) free(data); -} - -bool string::readfile(const string &filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -optional lstring::find(const char *key) const { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return { true, i }; - } - return { false, 0 }; -} - -string lstring::concatenate(const char *separator) const { - string output; - for(unsigned i = 0; i < size(); i++) { - output.append(operator[](i), i < size() - 1 ? separator : ""); - } - return output; -} - -template void lstring::append(const string &data, Args&&... args) { - vector::append(data); - append(std::forward(args)...); -} - -void lstring::isort() { - nall::sort(pool, objectsize, [](const string &x, const string &y) { - return istrcmp(x, y) < 0; - }); -} - -bool lstring::operator==(const lstring &source) const { - if(this == &source) return true; - if(size() != source.size()) return false; - for(unsigned n = 0; n < size(); n++) { - if(operator[](n) != source[n]) return false; - } - return true; -} - -bool lstring::operator!=(const lstring &source) const { - return !operator==(source); -} - -lstring& lstring::operator=(const lstring &source) { - vector::operator=(source); - return *this; -} - -lstring& lstring::operator=(lstring &source) { - vector::operator=(source); - return *this; -} - -lstring& lstring::operator=(lstring &&source) { - vector::operator=(std::move(source)); - return *this; -} - -template lstring::lstring(Args&&... args) { - append(std::forward(args)...); -} - -lstring::lstring(const lstring &source) { - vector::operator=(source); -} - -lstring::lstring(lstring &source) { - vector::operator=(source); -} - -lstring::lstring(lstring &&source) { - vector::operator=(std::move(source)); -} - -} - -#endif diff --git a/higan/phoenix/nall/string/cstring.hpp b/higan/phoenix/nall/string/cstring.hpp deleted file mode 100644 index 13b508ff..00000000 --- a/higan/phoenix/nall/string/cstring.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//const string: -//bind a const char* pointer to an object that has various testing functionality; -//yet lacks the memory allocation and modification functionality of the string class - -namespace nall { - -cstring::operator const char*() const { return data; } -unsigned cstring::length() const { return strlen(data); } -bool cstring::operator==(const char *s) const { return !strcmp(data, s); } -bool cstring::operator!=(const char *s) const { return strcmp(data, s); } -optional cstring::position (const char *key) const { return strpos(data, key); } -optional cstring::iposition(const char *key) const { return istrpos(data, key); } -cstring& cstring::operator=(const char *data) { this->data = data; return *this; } -cstring::cstring(const char *data) : data(data) {} -cstring::cstring() : data("") {} - -} - -#endif diff --git a/higan/phoenix/nall/string/datetime.hpp b/higan/phoenix/nall/string/datetime.hpp deleted file mode 100644 index 438631bf..00000000 --- a/higan/phoenix/nall/string/datetime.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -string string::date() { - time_t timestamp = ::time(nullptr); - tm *info = localtime(×tamp); - return { - decimal<4, '0'>(1900 + info->tm_year), "-", - decimal<2, '0'>(1 + info->tm_mon), "-", - decimal<2, '0'>(info->tm_mday) - }; -} - -string string::time() { - time_t timestamp = ::time(nullptr); - tm *info = localtime(×tamp); - return { - decimal<2, '0'>(info->tm_hour), ":", - decimal<2, '0'>(info->tm_min), ":", - decimal<2, '0'>(info->tm_sec) - }; -} - -string string::datetime() { - return {string::date(), " ", string::time()}; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/filename.hpp b/higan/phoenix/nall/string/filename.hpp deleted file mode 100644 index 19b5f117..00000000 --- a/higan/phoenix/nall/string/filename.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -// "/foo/bar.c" -> "/foo/" -// "/foo/" -> "/foo/" -// "bar.c" -> "./" -inline string dir(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name[i + 1] = 0; - break; - } - if(i == 0) name = "./"; - } - return name; -} - -// "/foo/bar.c" -> "bar.c" -// "/foo/" -> "" -// "bar.c" -> "bar.c" -inline string notdir(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - return (const char*)name + i + 1; - } - } - return name; -} - -// "/foo/bar/baz" -> "/foo/bar/" -// "/foo/bar/" -> "/foo/" -// "/foo/bar" -> "/foo/" -inline string parentdir(string name) { - unsigned length = name.length(), paths = 0, prev, last; - for(unsigned i = 0; i < length; i++) { - if(name[i] == '/' || name[i] == '\\') { - paths++; - prev = last; - last = i; - } - } - if(last + 1 == length) last = prev; //if name ends in slash; use previous slash - if(paths > 1) name[last + 1] = 0; - return name; -} - -// "/foo/bar.c" -> "/foo/bar" -inline string basename(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') break; //file has no extension - if(name[i] == '.') { - name[i] = 0; - break; - } - } - return name; -} - -// "/foo/bar.c" -> "c" -// "/foo/bar" -> "" -inline string extension(string name) { - for(signed i = name.length(); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') return ""; //file has no extension - if(name[i] == '.') { - return (const char*)name + i + 1; - } - } - return name; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/format.hpp b/higan/phoenix/nall/string/format.hpp deleted file mode 100644 index 599021d1..00000000 --- a/higan/phoenix/nall/string/format.hpp +++ /dev/null @@ -1,73 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template string format(const string &value) { - if(precision == 0) return value; - - bool padright = precision >= 0; - unsigned padding = abs(precision); - - unsigned length = value.length(); - if(padding <= length) { - if(padright) return substr(value, length - padding); - else return substr(value, 0, padding); - } - - string buffer; - buffer.resize(padding); - buffer.clear(padchar); - - memcpy(buffer() + (padright ? padding - length : 0), value, length); - return buffer; -} - -template string hex(uintmax_t value) { - string buffer; - buffer.resize(sizeof(uintmax_t) * 2); - - unsigned size = 0; - do { - unsigned n = value & 15; - buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - buffer[size] = 0; - buffer.reverse(); - - return format(buffer); -} - -template string octal(uintmax_t value) { - string buffer; - buffer.resize(sizeof(uintmax_t) * 3); - - unsigned size = 0; - do { - buffer[size++] = '0' + (value & 7); - value >>= 3; - } while(value); - buffer[size] = 0; - buffer.reverse(); - - return format(buffer); -} - -template string binary(uintmax_t value) { - string buffer; - buffer.resize(sizeof(uintmax_t) * 8); - - unsigned size = 0; - do { - buffer[size++] = '0' + (value & 1); - value >>= 1; - } while(value); - buffer[size] = 0; - buffer.reverse(); - - return format(buffer); -} - -} - -#endif diff --git a/higan/phoenix/nall/string/markup/bml.hpp b/higan/phoenix/nall/string/markup/bml.hpp deleted file mode 100644 index 26bf6685..00000000 --- a/higan/phoenix/nall/string/markup/bml.hpp +++ /dev/null @@ -1,147 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//BML v1.0 parser -//revision 0.02 - -namespace nall { -namespace BML { - -struct Node : Markup::Node { -protected: - //test to verify if a valid character for a node name - bool valid(char p) const { //A-Z, a-z, 0-9, -./ - return p - 'A' < 26u || p - 'a' < 26u || p - '0' < 10u || p - '-' < 3u; - } - - //determine indentation level, without incrementing pointer - unsigned readDepth(const char *p) { - unsigned depth = 0; - while(p[depth] == '\t' || p[depth] == ' ') depth++; - return depth; - } - - //determine indentation level - unsigned parseDepth(const char *&p) { - unsigned depth = readDepth(p); - p += depth; - return depth; - } - - //read name - void parseName(const char *&p) { - unsigned length = 0; - while(valid(p[length])) length++; - if(length == 0) throw "Invalid node name"; - name = substr(p, 0, length); - p += length; - } - - void parseData(const char *&p) { - if(*p == '=' && *(p + 1) == '\"') { - unsigned length = 2; - while(p[length] && p[length] != '\n' && p[length] != '\"') length++; - if(p[length] != '\"') throw "Unescaped value"; - data = substr(p, 2, length - 2); - p += length + 1; - } else if(*p == '=') { - unsigned length = 1; - while(p[length] && p[length] != '\n' && p[length] != '\"' && p[length] != ' ') length++; - if(p[length] == '\"') throw "Illegal character in value"; - data = substr(p, 1, length - 1); - p += length; - } else if(*p == ':') { - unsigned length = 1; - while(p[length] && p[length] != '\n') length++; - data = {substr(p, 1, length - 1), "\n"}; - p += length; - } - } - - //read all attributes for a node - void parseAttributes(const char *&p) { - while(*p && *p != '\n') { - if(*p != ' ') throw "Invalid node name"; - while(*p == ' ') p++; //skip excess spaces - - Node node; - node.attribute = true; - unsigned length = 0; - while(valid(p[length])) length++; - if(length == 0) throw "Invalid attribute name"; - node.name = substr(p, 0, length); - node.parseData(p += length); - children.append(node); - } - } - - //read a node and all of its children nodes - void parseNode(const char *&p) { - level = parseDepth(p); - parseName(p); - parseData(p); - parseAttributes(p); - if(*p && *p++ != '\n') throw "Missing line feed"; - - while(*p) { - if(*p == '\n') { p++; continue; } - - unsigned depth = readDepth(p); - if(depth <= level) break; - - if(p[depth] == ':') { - p += depth; - unsigned length = 0; - while(p[length] && p[length] != '\n') length++; - data.append(substr(p, 1, length - 1), "\n"); - p += length; - continue; - } - - Node node; - node.parseNode(p); - children.append(node); - } - - data.rtrim<1>("\n"); - } - - //read top-level nodes - void parse(const char *p) { - while(*p) { - Node node; - node.parseNode(p); - if(node.level > 0) throw "Root nodes cannot be indented"; - children.append(node); - } - } - - friend class Document; -}; - -struct Document : Node { - string error; - - bool load(string document) { - name = "{root}", data = ""; - - try { - document.replace("\r", ""); - while(document.position("\n\n")) document.replace("\n\n", "\n"); - parse(document); - } catch(const char *perror) { - error = perror; - children.reset(); - return false; - } - return true; - } - - Document(const string &document = "") { - load(document); - } -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/string/markup/document.hpp b/higan/phoenix/nall/string/markup/document.hpp deleted file mode 100644 index 34465a4f..00000000 --- a/higan/phoenix/nall/string/markup/document.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { -namespace Markup { - -inline Node Document(const string &markup) { - if(markup.beginswith("<")) return XML::Document(markup); - return BML::Document(markup); -} - -} -} - -#endif diff --git a/higan/phoenix/nall/string/markup/node.hpp b/higan/phoenix/nall/string/markup/node.hpp deleted file mode 100644 index 77822373..00000000 --- a/higan/phoenix/nall/string/markup/node.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//note: specific markups inherit from Markup::Node -//vector will slice any data; so derived nodes must not contain data nor virtual functions -//vector would incur a large performance penalty and greatly increased complexity - -namespace nall { -namespace Markup { - -struct Node { - string name; - string data; - bool attribute; - - bool exists() const { - return !name.empty(); - } - - string text() const { - return string{data}.strip(); - } - - intmax_t integer() const { - return numeral(text()); - } - - uintmax_t decimal() const { - return numeral(text()); - } - - void reset() { - children.reset(); - } - - bool evaluate(const string &query) const { - if(query.empty()) return true; - lstring rules = string{query}.replace(" ", "").split(","); - - for(auto &rule : rules) { - enum class Comparator : unsigned { ID, EQ, NE, LT, LE, GT, GE }; - auto comparator = Comparator::ID; - if(rule.wildcard("*!=*")) comparator = Comparator::NE; - else if(rule.wildcard("*<=*")) comparator = Comparator::LE; - else if(rule.wildcard("*>=*")) comparator = Comparator::GE; - else if(rule.wildcard ("*=*")) comparator = Comparator::EQ; - else if(rule.wildcard ("*<*")) comparator = Comparator::LT; - else if(rule.wildcard ("*>*")) comparator = Comparator::GT; - - if(comparator == Comparator::ID) { - if(find(rule).size()) continue; - return false; - } - - lstring side; - switch(comparator) { - case Comparator::EQ: side = rule.split<1> ("="); break; - case Comparator::NE: side = rule.split<1>("!="); break; - case Comparator::LT: side = rule.split<1> ("<"); break; - case Comparator::LE: side = rule.split<1>("<="); break; - case Comparator::GT: side = rule.split<1> (">"); break; - case Comparator::GE: side = rule.split<1>(">="); break; - } - - string data = text(); - if(side(0).empty() == false) { - auto result = find(side(0)); - if(result.size() == 0) return false; - data = result(0).data; - } - - switch(comparator) { - case Comparator::EQ: if(data.wildcard(side(1)) == true) continue; break; - case Comparator::NE: if(data.wildcard(side(1)) == false) continue; break; - case Comparator::LT: if(numeral(data) < numeral(side(1))) continue; break; - case Comparator::LE: if(numeral(data) <= numeral(side(1))) continue; break; - case Comparator::GT: if(numeral(data) > numeral(side(1))) continue; break; - case Comparator::GE: if(numeral(data) >= numeral(side(1))) continue; break; - } - - return false; - } - - return true; - } - - vector find(const string &query) const { - vector result; - - lstring path = query.split("/"); - string name = path.take(0), rule; - unsigned lo = 0u, hi = ~0u; - - if(name.wildcard("*[*]")) { - lstring side = name.split<1>("["); - name = side(0); - side = side(1).rtrim<1>("]").split<1>("-"); - lo = side(0).empty() ? 0u : numeral(side(0)); - hi = side(1).empty() ? ~0u : numeral(side(1)); - } - - if(name.wildcard("*(*)")) { - lstring side = name.split<1>("("); - name = side(0); - rule = side(1).rtrim<1>(")"); - } - - unsigned position = 0; - for(auto &node : children) { - if(node.name.wildcard(name) == false) continue; - if(node.evaluate(rule) == false) continue; - - bool inrange = position >= lo && position <= hi; - position++; - if(inrange == false) continue; - - if(path.size() == 0) result.append(node); - else { - auto list = node.find(path.concatenate("/")); - for(auto &item : list) result.append(item); - } - } - - return result; - } - - Node operator[](const string &query) const { - auto result = find(query); - return result(0); - } - - Node* begin() { return children.begin(); } - Node* end() { return children.end(); } - const Node* begin() const { return children.begin(); } - const Node* end() const { return children.end(); } - - Node() : attribute(false), level(0) {} - -protected: - unsigned level; - vector children; -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/string/markup/xml.hpp b/higan/phoenix/nall/string/markup/xml.hpp deleted file mode 100644 index d3a3e15a..00000000 --- a/higan/phoenix/nall/string/markup/xml.hpp +++ /dev/null @@ -1,218 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//XML v1.0 subset parser -//revision 0.03 - -namespace nall { -namespace XML { - -struct Node : Markup::Node { -protected: - inline string escape() const { - string result = data; - result.replace("&", "&"); - result.replace("<", "<"); - result.replace(">", ">"); - if(attribute == false) return result; - result.replace("\'", "'"); - result.replace("\"", """); - return result; - } - - inline bool isName(char c) const { - if(c >= 'A' && c <= 'Z') return true; - if(c >= 'a' && c <= 'z') return true; - if(c >= '0' && c <= '9') return true; - if(c == '.' || c == '_') return true; - if(c == '?') return true; - return false; - } - - inline bool isWhitespace(char c) const { - if(c == ' ' || c == '\t') return true; - if(c == '\r' || c == '\n') return true; - return false; - } - - //copy part of string from source document into target string; decode markup while copying - inline void copy(string &target, const char *source, unsigned length) { - target.reserve(length + 1); - - #if defined(NALL_XML_LITERAL) - memcpy(target(), source, length); - target[length] = 0; - return; - #endif - - char *output = target(); - while(length) { - if(*source == '&') { - if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; } - if(!memcmp(source, ">", 4)) { *output++ = '>'; source += 4; length -= 4; continue; } - if(!memcmp(source, "&", 5)) { *output++ = '&'; source += 5; length -= 5; continue; } - if(!memcmp(source, "'", 6)) { *output++ = '\''; source += 6; length -= 6; continue; } - if(!memcmp(source, """, 6)) { *output++ = '\"'; source += 6; length -= 6; continue; } - } - - if(attribute == false && source[0] == '<' && source[1] == '!') { - //comment - if(!memcmp(source, "", 3)) source++, length--; - source += 3, length -= 3; - continue; - } - - //CDATA - if(!memcmp(source, "", 3)) *output++ = *source++, length--; - source += 3, length -= 3; - continue; - } - } - - *output++ = *source++, length--; - } - *output = 0; - } - - inline bool parseExpression(const char *&p) { - if(*(p + 1) != '!') return false; - - //comment - if(!memcmp(p, "", 3)) p++; - if(!*p) throw "unclosed comment"; - p += 3; - return true; - } - - //CDATA - if(!memcmp(p, "", 3)) p++; - if(!*p) throw "unclosed CDATA"; - p += 3; - return true; - } - - //DOCTYPE - if(!memcmp(p, "') counter--; - } while(counter); - return true; - } - - return false; - } - - //returns true if tag closes itself (); false if not () - inline bool parseHead(const char *&p) { - //parse name - const char *nameStart = ++p; //skip '<' - while(isName(*p)) p++; - const char *nameEnd = p; - copy(name, nameStart, nameEnd - nameStart); - if(name.empty()) throw "missing element name"; - - //parse attributes - while(*p) { - while(isWhitespace(*p)) p++; - if(!*p) throw "unclosed attribute"; - if(*p == '?' || *p == '/' || *p == '>') break; - - //parse attribute name - Node attribute; - attribute.attribute = true; - - const char *nameStart = p; - while(isName(*p)) p++; - const char *nameEnd = p; - copy(attribute.name, nameStart, nameEnd - nameStart); - if(attribute.name.empty()) throw "missing attribute name"; - - //parse attribute data - if(*p++ != '=') throw "missing attribute value"; - char terminal = *p++; - if(terminal != '\'' && terminal != '\"') throw "attribute value not quoted"; - const char *dataStart = p; - while(*p && *p != terminal) p++; - if(!*p) throw "missing attribute data terminal"; - const char *dataEnd = p++; //skip closing terminal - - copy(attribute.data, dataStart, dataEnd - dataStart); - children.append(attribute); - } - - //parse closure - if(*p == '?' && *(p + 1) == '>') { p += 2; return true; } - if(*p == '/' && *(p + 1) == '>') { p += 2; return true; } - if(*p == '>') { p += 1; return false; } - throw "invalid element tag"; - } - - //parse element and all of its child elements - inline void parseElement(const char *&p) { - Node node; - if(node.parseHead(p) == false) node.parse(p); - children.append(node); - } - - //return true if matches this node's name - inline bool parseClosureElement(const char *&p) { - if(p[0] != '<' || p[1] != '/') return false; - p += 2; - const char *nameStart = p; - while(*p && *p != '>') p++; - if(*p != '>') throw "unclosed closure element"; - const char *nameEnd = p++; - if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch"; - return true; - } - - //parse contents of an element - inline void parse(const char *&p) { - const char *dataStart = p, *dataEnd = p; - - while(*p) { - while(*p && *p != '<') p++; - if(!*p) break; - dataEnd = p; - if(parseClosureElement(p) == true) break; - if(parseExpression(p) == true) continue; - parseElement(p); - } - - copy(data, dataStart, dataEnd - dataStart); - } -}; - -struct Document : Node { - string error; - - inline bool load(const char *document) { - if(document == nullptr) return false; - reset(); - try { - parse(document); - } catch(const char *error) { - reset(); - this->error = error; - return false; - } - return true; - } - - inline Document() {} - inline Document(const char *document) { load(document); } -}; - -} -} - -#endif diff --git a/higan/phoenix/nall/string/math-fixed-point.hpp b/higan/phoenix/nall/string/math-fixed-point.hpp deleted file mode 100644 index a61b23f3..00000000 --- a/higan/phoenix/nall/string/math-fixed-point.hpp +++ /dev/null @@ -1,166 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace fixedpoint { - -static nall::function eval_fallback; - -static intmax_t eval_integer(const char *& s) { - if(!*s) throw "unrecognized integer"; - intmax_t value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched char"; - } - } - - throw "unrecognized integer"; -} - -static intmax_t eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized token"; - intmax_t value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing - - else throw "unrecognized token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value /= result; continue; } - if(x == '%') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value %= result; continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - intmax_t lhs = eval(++s, 2); - if(*s != ':') throw "mismatched ternary"; - intmax_t rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized token"; - } - - return value; -} - -static bool eval(const char *s, intmax_t &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -static intmax_t parse(const char *s) { - try { - intmax_t result = eval(s); - return result; - } catch(const char *) { - return 0; - } -} - -} - -#endif diff --git a/higan/phoenix/nall/string/math-floating-point.hpp b/higan/phoenix/nall/string/math-floating-point.hpp deleted file mode 100644 index 43a2f0f4..00000000 --- a/higan/phoenix/nall/string/math-floating-point.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace floatingpoint { - -static nall::function eval_fallback; - -static double eval_integer(const char *&s) { - if(!*s) throw "unrecognized integer"; - intmax_t value = 0, radix = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0' && y != '.') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - if(*s == '.') { s++; break; } - return value; - } - //floating-point - while(true) { - if(*s >= '0' && *s <= '9') { radix = radix * 10 + (*s++ - '0'); continue; } - return atof(nall::string{ nall::decimal(value), ".", nall::decimal(radix) }); - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched char"; - } - } - - throw "unrecognized integer"; -} - -static double eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized token"; - double value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched group"; - } - - else if(x == '!') value = !eval(++s, 9); - else if(x == '+') value = +eval(++s, 9); - else if(x == '-') value = -eval(++s, 9); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing - - else throw "unrecognized token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 9) break; - if(x == '*') { value *= eval(++s, 9); continue; } - if(x == '/') { double result = eval(++s, 9); if(result == 0.0) throw "division by zero"; value /= result; continue; } - - if(depth >= 8) break; - if(x == '+') { value += eval(++s, 8); continue; } - if(x == '-') { value -= eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 7); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 7); continue; } - if(x == '<') { value = value < eval(++s, 7); continue; } - if(x == '>') { value = value > eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 6); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - double lhs = eval(++s, 2); - if(*s != ':') throw "mismatched ternary"; - double rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized token"; - } - - return value; -} - -static bool eval(const char *s, double &result) { - try { - result = eval(s); - return true; - } catch(const char*e) { - result = 0; - return false; - } -} - -static double parse(const char *s) { - try { - double result = eval(s); - return result; - } catch(const char *) { - return 0; - } -} - -} - -#endif diff --git a/higan/phoenix/nall/string/platform.hpp b/higan/phoenix/nall/string/platform.hpp deleted file mode 100644 index 0129f4d2..00000000 --- a/higan/phoenix/nall/string/platform.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -string activepath() { - string result; - #ifdef _WIN32 - wchar_t path[PATH_MAX] = L""; - auto unused = _wgetcwd(path, PATH_MAX); - result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #else - char path[PATH_MAX] = ""; - auto unused = getcwd(path, PATH_MAX); - result = path; - #endif - if(result.empty()) result = "."; - if(result.endswith("/") == false) result.append("/"); - return result; -} - -string realpath(const string &name) { - string result; - #ifdef _WIN32 - wchar_t path[PATH_MAX] = L""; - if(_wfullpath(path, utf16_t(name), PATH_MAX)) result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #else - char path[PATH_MAX] = ""; - if(::realpath(name, path)) result = path; - #endif - if(result.empty()) result = {activepath(), name}; - return result; -} - -// /home/username/ -// c:/users/username/ -string userpath() { - string result; - #ifdef _WIN32 - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path); - result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #else - char path[PATH_MAX] = ""; - struct passwd *userinfo = getpwuid(getuid()); - if(userinfo) strcpy(path, userinfo->pw_dir); - result = path; - #endif - if(result.empty()) result = "."; - if(result.endswith("/") == false) result.append("/"); - return result; -} - -// /home/username/.config/ -// c:/users/username/appdata/roaming/ -string configpath() { - string result; - #ifdef _WIN32 - wchar_t path[PATH_MAX] = L""; - SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path); - result = (const char*)utf8_t(path); - result.transform("\\", "/"); - #else - result = {userpath(), ".config/"}; - #endif - if(result.empty()) result = "."; - if(result.endswith("/") == false) result.append("/"); - return result; -} - -string temppath() { - #ifdef _WIN32 - wchar_t path[PATH_MAX] = L""; - GetTempPathW(PATH_MAX, path); - string result = (const char*)utf8_t(path); - result.transform("\\", "/"); - return result; - #else - return "/tmp/"; - #endif -} - -} - -#endif diff --git a/higan/phoenix/nall/string/replace.hpp b/higan/phoenix/nall/string/replace.hpp deleted file mode 100644 index 2bd1412f..00000000 --- a/higan/phoenix/nall/string/replace.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template -string& string::ureplace(const char *key, const char *token) { - if(!key || !*key) return *this; - enum : unsigned { limit = Limit ? Limit : ~0u }; - - const char *p = data; - unsigned counter = 0, keyLength = 0; - - while(*p) { - if(quoteskip(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter++; p += n; keyLength = n; break; } - if(!chrequal(key[n], p[n])) { p++; break; } - } - } - if(counter == 0) return *this; - if(Limit) counter = min(counter, Limit); - - char *t = data, *base; - unsigned tokenLength = strlen(token); - if(tokenLength > keyLength) { - t = base = strdup(data); - reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter)); - } - char *o = data; - - while(*t && counter) { - if(quotecopy(o, t)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { counter--; memcpy(o, token, tokenLength); t += keyLength; o += tokenLength; break; } - if(!chrequal(key[n], t[n])) { *o++ = *t++; break; } - } - } - do *o++ = *t; while(*t++); - if(tokenLength > keyLength) free(base); - - return *this; -} - -template string &string::replace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::ireplace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::qreplace(const char *key, const char *token) { return ureplace(key, token); } -template string &string::iqreplace(const char *key, const char *token) { return ureplace(key, token); } - -}; - -#endif diff --git a/higan/phoenix/nall/string/split.hpp b/higan/phoenix/nall/string/split.hpp deleted file mode 100644 index bb12a91b..00000000 --- a/higan/phoenix/nall/string/split.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template lstring& lstring::usplit(const char *key, const char *base) { - reset(); - if(!key || !*key) return *this; - - const char *p = base; - - while(*p) { - if(Limit) if(size() >= Limit) break; - if(quoteskip(p)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) { - append(substr(base, 0, p - base)); - p += n; - base = p; - break; - } - if(!chrequal(key[n], p[n])) { p++; break; } - } - } - - append(base); - return *this; -} - -template lstring& lstring::split(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::isplit(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::qsplit(const char *key, const char *src) { return usplit(key, src); } -template lstring& lstring::iqsplit(const char *key, const char *src) { return usplit(key, src); } - -}; - -#endif diff --git a/higan/phoenix/nall/string/static.hpp b/higan/phoenix/nall/string/static.hpp deleted file mode 100644 index ca521cb0..00000000 --- a/higan/phoenix/nall/string/static.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -string string::read(const string &filename) { - string data; - data.readfile(filename); - return data; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/strm.hpp b/higan/phoenix/nall/string/strm.hpp deleted file mode 100644 index 21d05652..00000000 --- a/higan/phoenix/nall/string/strm.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -// -//strmcpy, strmcat created by byuu -// - -//return = strlen(target) -unsigned strmcpy(char *target, const char *source, unsigned length) { - const char *origin = target; - if(length) { - while(*source && --length) *target++ = *source++; - *target = 0; - } - return target - origin; -} - -//return = strlen(target) -unsigned strmcat(char *target, const char *source, unsigned length) { - const char *origin = target; - while(*target && length) target++, length--; - return (target - origin) + strmcpy(target, source, length); -} - -//return = true when all of source was copied -bool strccpy(char *target, const char *source, unsigned length) { - return !source[strmcpy(target, source, length)]; -} - -//return = true when all of source was copied -bool strccat(char *target, const char *source, unsigned length) { - while(*target && length) target++, length--; - return !source[strmcpy(target, source, length)]; -} - -//return = reserved for future use -void strpcpy(char *&target, const char *source, unsigned &length) { - unsigned offset = strmcpy(target, source, length); - target += offset, length -= offset; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/strpos.hpp b/higan/phoenix/nall/string/strpos.hpp deleted file mode 100644 index fe563a6c..00000000 --- a/higan/phoenix/nall/string/strpos.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -//usage example: -//if(auto position = strpos(str, key)) print(position(), "\n"); -//prints position of key within str; but only if it is found - -namespace nall { - -template -optional ustrpos(const char *str, const char *key) { - const char *base = str; - - while(*str) { - if(quoteskip(str)) continue; - for(unsigned n = 0;; n++) { - if(key[n] == 0) return { true, (unsigned)(str - base) }; - if(str[n] == 0) return { false, 0 }; - if(!chrequal(str[n], key[n])) break; - } - str++; - } - - return { false, 0 }; -} - -optional strpos(const char *str, const char *key) { return ustrpos(str, key); } -optional istrpos(const char *str, const char *key) { return ustrpos(str, key); } -optional qstrpos(const char *str, const char *key) { return ustrpos(str, key); } -optional iqstrpos(const char *str, const char *key) { return ustrpos(str, key); } - -} - -#endif diff --git a/higan/phoenix/nall/string/trim.hpp b/higan/phoenix/nall/string/trim.hpp deleted file mode 100644 index 3e0c914f..00000000 --- a/higan/phoenix/nall/string/trim.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -//limit defaults to zero, which will underflow on first compare; equivalent to no limit -template char* ltrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - if(--limit == 0) break; - } - return str; -} - -template char* rtrim(char *str, const char *key) { - unsigned limit = Limit; - if(!key || !*key) return str; - while(strend(str, key)) { - str[strlen(str) - strlen(key)] = 0; - if(--limit == 0) break; - } - return str; -} - -template char* trim(char *str, const char *key, const char *rkey) { - if(rkey) return ltrim(rtrim(str, rkey), key); - return ltrim(rtrim(str, key), key); -} - -//remove whitespace characters from both left and right sides of string -char* strip(char *s) { - signed n = 0, p = 0; - while(s[n]) { - if(s[n] != ' ' && s[n] != '\t' && s[n] != '\r' && s[n] != '\n') break; - n++; - } - while(s[n]) s[p++] = s[n++]; - s[p--] = 0; - while(p >= 0) { - if(s[p] != ' ' && s[p] != '\t' && s[p] != '\r' && s[p] != '\n') break; - p--; - } - s[++p] = 0; - return s; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/utf8.hpp b/higan/phoenix/nall/string/utf8.hpp deleted file mode 100644 index 77397bf2..00000000 --- a/higan/phoenix/nall/string/utf8.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -struct UTF8 { - unsigned size; //size of encoded codepoint - uint64_t data; //encoded codepoint - unsigned codepoint; //decoded codepoint -}; - -inline UTF8 utf8_read(const char *s) { - UTF8 utf8; - - if((*s & 0xfe) == 0xfc) utf8.size = 6; - else if((*s & 0xfc) == 0xf8) utf8.size = 5; - else if((*s & 0xf8) == 0xf0) utf8.size = 4; - else if((*s & 0xf0) == 0xe0) utf8.size = 3; - else if((*s & 0xe0) == 0xc0) utf8.size = 2; - else utf8.size = 1; - - utf8.data = 0; - for(unsigned n = 0; n < utf8.size; n++) { - utf8.data = (utf8.data << 8) | (uint8_t)s[n]; - } - - static uint8_t mask[] = { 0, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01 }; - utf8.codepoint = s[0] & mask[utf8.size]; - for(unsigned n = 1; n < utf8.size; n++) { - utf8.codepoint = (utf8.codepoint << 6) | (s[n] & 0x3f); - } - - return utf8; -} - -inline void utf8_write(char *s, const UTF8 &utf8) { - for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) { - s[n] = utf8.data >> shift; - } -} - -} - -#endif diff --git a/higan/phoenix/nall/string/utility.hpp b/higan/phoenix/nall/string/utility.hpp deleted file mode 100644 index 2379e7fb..00000000 --- a/higan/phoenix/nall/string/utility.hpp +++ /dev/null @@ -1,242 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template -bool chrequal(char x, char y) { - if(Insensitive) return chrlower(x) == chrlower(y); - return x == y; -} - -template -bool quoteskip(T *&p) { - if(Quoted == false) return false; - if(*p != '\'' && *p != '\"') return false; - - while(*p == '\'' || *p == '\"') { - char x = *p++; - while(*p && *p++ != x); - } - return true; -} - -template -bool quotecopy(char *&t, T *&p) { - if(Quoted == false) return false; - if(*p != '\'' && *p != '\"') return false; - - while(*p == '\'' || *p == '\"') { - char x = *p++; - *t++ = x; - while(*p && *p != x) *t++ = *p++; - *t++ = *p++; - } - return true; -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == ~0u) { - //copy entire string - dest.reserve(strlen(src + start) + 1); - strcpy(dest(), src + start); - } else { - //copy partial string - dest.reserve(length + 1); - strmcpy(dest(), src + start, length + 1); - } - return dest; -} - -string sha256(const uint8_t *data, unsigned size) { - sha256_ctx sha; - uint8_t hash[32]; - sha256_init(&sha); - sha256_chunk(&sha, data, size); - sha256_final(&sha); - sha256_hash(&sha, hash); - string result; - for(auto &byte : hash) result.append(hex<2>(byte)); - return result; -} - -/* cast.hpp arithmetic -> string */ - -char* integer(char *result, intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - if(negative) buffer[size++] = '-'; -//buffer[size++] = negative ? '-' : '+'; - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y]; - result[size] = 0; - return result; -} - -char* decimal(char *result, uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - - for(signed x = size - 1, y = 0; x >= 0 && y < size; x--, y++) result[x] = buffer[y]; - result[size] = 0; - return result; -} - -/* general-purpose arithmetic -> string */ - -template string integer(intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - if(negative) buffer[size++] = '-'; -//buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string linteger(intmax_t value) { - bool negative = value < 0; - if(negative) value = -value; - - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - if(negative) buffer[size++] = '-'; -//buffer[size++] = negative ? '-' : '+'; - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string decimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = length - 1, y = 0; x >= 0 && y < size; x--, y++) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -template string ldecimal(uintmax_t value) { - char buffer[64]; - unsigned size = 0; - - do { - unsigned n = value % 10; - buffer[size++] = '0' + n; - value /= 10; - } while(value); - buffer[size] = 0; - - unsigned length = (length_ == 0 ? size : length_); - char result[length + 1]; - memset(result, padding, length); - result[length] = 0; - - for(signed x = 0, y = size - 1; x < length && y >= 0; x++, y--) { - result[x] = buffer[y]; - } - - return (const char*)result; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned fp(char *str, long double value) { - char buffer[256]; - #ifdef _WIN32 - //Windows C-runtime does not support long double via sprintf() - sprintf(buffer, "%f", (double)value); - #else - sprintf(buffer, "%Lf", value); - #endif - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string fp(long double value) { - string temp; - temp.reserve(fp(nullptr, value)); - fp(temp(), value); - return temp; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/variadic.hpp b/higan/phoenix/nall/string/variadic.hpp deleted file mode 100644 index c43bfe86..00000000 --- a/higan/phoenix/nall/string/variadic.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -template inline void print(Args&&... args) { - printf("%s", (const char*)string(std::forward(args)...)); -} - -} - -#endif diff --git a/higan/phoenix/nall/string/wildcard.hpp b/higan/phoenix/nall/string/wildcard.hpp deleted file mode 100644 index ea11490a..00000000 --- a/higan/phoenix/nall/string/wildcard.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -bool wildcard(const char *s, const char *p) { - const char *cp = nullptr, *mp = nullptr; - while(*s && *p != '*') { - if(*p != '?' && *s != *p) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || *p == *s) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -bool iwildcard(const char *s, const char *p) { - const char *cp = nullptr, *mp = nullptr; - while(*s && *p != '*') { - if(*p != '?' && chrlower(*s) != chrlower(*p)) return false; - p++, s++; - } - while(*s) { - if(*p == '*') { - if(!*++p) return true; - mp = p, cp = s + 1; - } else if(*p == '?' || chrlower(*p) == chrlower(*s)) { - p++, s++; - } else { - p = mp, s = cp++; - } - } - while(*p == '*') p++; - return !*p; -} - -inline bool tokenize(const char *s, const char *p) { - while(*s) { - if(*p == '*') { - while(*s) if(tokenize(s++, p + 1)) return true; - return !*++p; - } - if(*s++ != *p++) return false; - } - while(*p == '*') p++; - return !*p; -} - -inline bool tokenize(lstring &list, const char *s, const char *p) { - while(*s) { - if(*p == '*') { - const char *b = s; - while(*s) { - if(tokenize(list, s++, p + 1)) { - list.prepend(substr(b, 0, --s - b)); - return true; - } - } - list.prepend(b); - return !*++p; - } - if(*s++ != *p++) return false; - } - while(*p == '*') { list.prepend(s); p++; } - return !*p; -} - -} - -#endif diff --git a/higan/phoenix/nall/string/wrapper.hpp b/higan/phoenix/nall/string/wrapper.hpp deleted file mode 100644 index 08aa98b3..00000000 --- a/higan/phoenix/nall/string/wrapper.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#ifdef NALL_STRING_INTERNAL_HPP - -namespace nall { - -unsigned string::length() const { return strlen(data); } -unsigned string::capacity() const { return size; } - -template lstring string::split(const char *key) const { lstring result; result.split(key, data); return result; } -template lstring string::isplit(const char *key) const { lstring result; result.isplit(key, data); return result; } -template lstring string::qsplit(const char *key) const { lstring result; result.qsplit(key, data); return result; } -template lstring string::iqsplit(const char *key) const { lstring result; result.iqsplit(key, data); return result; } - -bool string::equals(const char *str) const { return !strcmp(data, str); } -bool string::iequals(const char *str) const { return !istrcmp(data, str); } - -bool string::wildcard(const char *str) const { return nall::wildcard(data, str); } -bool string::iwildcard(const char *str) const { return nall::iwildcard(data, str); } - -bool string::beginswith(const char *str) const { return strbegin(data, str); } -bool string::ibeginswith(const char *str) const { return istrbegin(data, str); } - -bool string::endswith(const char *str) const { return strend(data, str); } -bool string::iendswith(const char *str) const { return istrend(data, str); } - -string& string::lower() { nall::strlower(data); return *this; } -string& string::upper() { nall::strupper(data); return *this; } -string& string::qlower() { nall::qstrlower(data); return *this; } -string& string::qupper() { nall::qstrupper(data); return *this; } -string& string::transform(const char *before, const char *after) { nall::strtr(data, before, after); return *this; } -string& string::reverse() { - unsigned length = strlen(data), pivot = length >> 1; - for(signed x = 0, y = length - 1; x < pivot && y >= 0; x++, y--) std::swap(data[x], data[y]); - return *this; -} - -template string& string::ltrim(const char *key) { nall::ltrim(data, key); return *this; } -template string& string::rtrim(const char *key) { nall::rtrim(data, key); return *this; } -template string& string::trim(const char *key, const char *rkey) { nall::trim (data, key, rkey); return *this; } -string& string::strip() { nall::strip(data); return *this; } - -optional string::position(const char *key) const { return strpos(data, key); } -optional string::iposition(const char *key) const { return istrpos(data, key); } -optional string::qposition(const char *key) const { return qstrpos(data, key); } -optional string::iqposition(const char *key) const { return iqstrpos(data, key); } - -} - -#endif diff --git a/higan/phoenix/nall/thread.hpp b/higan/phoenix/nall/thread.hpp deleted file mode 100644 index 2ac730a0..00000000 --- a/higan/phoenix/nall/thread.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef NALL_THREAD_HPP -#define NALL_THREAD_HPP - -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include - -namespace nall { - void* thread_entry_point(void*); - - struct thread { - thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { - initialize(); - pthread_create(&pthread, nullptr, thread_entry_point, (void*)this); - } - - ~thread() { - join(); - } - - bool active() const { - return completed == false; - } - - void join() { - if(dead) return; - dead = true; - pthread_join(pthread, nullptr); - } - - static bool primary() { - initialize(); - return pthread_equal(primaryThread(), pthread_self()); - } - - private: - pthread_t pthread; - function entryPoint; - volatile bool completed, dead; - friend void* thread_entry_point(void*); - - static void initialize() { - static bool initialized = false; - if(initialized) return; - initialized = true; - primaryThread() = pthread_self(); - } - - static pthread_t& primaryThread() { - static pthread_t thread; - return thread; - } - }; - - void* thread_entry_point(void *parameter) { - thread *context = (thread*)parameter; - context->entryPoint(); - context->completed = true; - pthread_exit(nullptr); - } -} -#elif defined(PLATFORM_WIN) -namespace nall { - inline DWORD WINAPI thread_entry_point(LPVOID); - - struct thread { - thread(function entryPoint) : entryPoint(entryPoint), completed(false), dead(false) { - initialize(); - hthread = CreateThread(nullptr, 0, thread_entry_point, (void*)this, 0, nullptr); - } - - ~thread() { - join(); - } - - bool active() const { - return completed == false; - } - - void join() { - if(dead) return; - dead = true; - WaitForSingleObject(hthread, INFINITE); - CloseHandle(hthread); - } - - static bool primary() { - initialize(); - return primaryThread() == GetCurrentThreadId(); - } - - private: - HANDLE hthread; - function entryPoint; - volatile bool completed, dead; - friend DWORD WINAPI thread_entry_point(LPVOID); - - static void initialize() { - static bool initialized = false; - if(initialized) return; - initialized = true; - primaryThread() = GetCurrentThreadId(); - } - - static DWORD& primaryThread() { - static DWORD thread; - return thread; - } - }; - - inline DWORD WINAPI thread_entry_point(LPVOID parameter) { - thread *context = (thread*)parameter; - context->entryPoint(); - context->completed = true; - return 0; - } -} -#endif - -#endif diff --git a/higan/phoenix/nall/traits.hpp b/higan/phoenix/nall/traits.hpp deleted file mode 100644 index 6a140c2b..00000000 --- a/higan/phoenix/nall/traits.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef NALL_TRAITS_HPP -#define NALL_TRAITS_HPP - -#include - -namespace nall { - -template class has_default_constructor { - template class receive_size{}; - template static signed sfinae(receive_size*); - template static char sfinae(...); - -public: - enum : bool { value = sizeof(sfinae(0)) == sizeof(signed) }; -}; - -template struct enable_if { typedef T type; }; -template struct enable_if {}; - -template struct type_if { typedef T type; }; -template struct type_if { typedef F type; }; - -template struct static_and { enum { value = false }; }; -template<> struct static_and { enum { value = true }; }; - -template struct static_or { enum { value = false }; }; -template<> struct static_or { enum { value = true }; }; -template<> struct static_or { enum { value = true }; }; -template<> struct static_or { enum { value = true }; }; - -} - -#endif diff --git a/higan/phoenix/nall/udl.hpp b/higan/phoenix/nall/udl.hpp deleted file mode 100644 index 30ceefb3..00000000 --- a/higan/phoenix/nall/udl.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NALL_UDL_HPP -#define NALL_UDL_HPP - -//user-defined literals - -#include -#include - -namespace nall { - constexpr inline uintmax_t operator"" _b(const char *n) { return binary(n); } - - //convert to bytes - constexpr inline uintmax_t operator"" _kb(unsigned long long n) { return 1024 * n; } - constexpr inline uintmax_t operator"" _mb(unsigned long long n) { return 1024 * 1024 * n; } - constexpr inline uintmax_t operator"" _gb(unsigned long long n) { return 1024 * 1024 * 1024 * n; } - - //convert to bits - constexpr inline uintmax_t operator"" _kbit(unsigned long long n) { return 1024 * n / 8; } - constexpr inline uintmax_t operator"" _mbit(unsigned long long n) { return 1024 * 1024 * n / 8; } - constexpr inline uintmax_t operator"" _gbit(unsigned long long n) { return 1024 * 1024 * 1024 * n / 8; } - - //convert to hz - constexpr inline uintmax_t operator"" _khz(long double n) { return n * 1000; } - constexpr inline uintmax_t operator"" _mhz(long double n) { return n * 1000000; } - constexpr inline uintmax_t operator"" _ghz(long double n) { return n * 1000000000; } -} - -#endif diff --git a/higan/phoenix/nall/unzip.hpp b/higan/phoenix/nall/unzip.hpp deleted file mode 100644 index 5a7935f6..00000000 --- a/higan/phoenix/nall/unzip.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef NALL_UNZIP_HPP -#define NALL_UNZIP_HPP - -#include -#include -#include -#include - -namespace nall { - -struct unzip { - struct File { - string name; - const uint8_t *data; - unsigned size; - unsigned csize; - unsigned cmode; //0 = uncompressed, 8 = deflate - unsigned crc32; - }; - - inline bool open(const string &filename) { - close(); - if(fm.open(filename, filemap::mode::read) == false) return false; - if(open(fm.data(), fm.size()) == false) { - fm.close(); - return false; - } - return true; - } - - inline bool open(const uint8_t *data, unsigned size) { - if(size < 22) return false; - - filedata = data; - filesize = size; - - file.reset(); - - const uint8_t *footer = data + size - 22; - while(true) { - if(footer <= data + 22) return false; - if(read(footer, 4) == 0x06054b50) { - unsigned commentlength = read(footer + 20, 2); - if(footer + 22 + commentlength == data + size) break; - } - footer--; - } - const uint8_t *directory = data + read(footer + 16, 4); - - while(true) { - unsigned signature = read(directory + 0, 4); - if(signature != 0x02014b50) break; - - File file; - file.cmode = read(directory + 10, 2); - file.crc32 = read(directory + 16, 4); - file.csize = read(directory + 20, 4); - file.size = read(directory + 24, 4); - - unsigned namelength = read(directory + 28, 2); - unsigned extralength = read(directory + 30, 2); - unsigned commentlength = read(directory + 32, 2); - - char *filename = new char[namelength + 1]; - memcpy(filename, directory + 46, namelength); - filename[namelength] = 0; - file.name = filename; - delete[] filename; - - unsigned offset = read(directory + 42, 4); - unsigned offsetNL = read(data + offset + 26, 2); - unsigned offsetEL = read(data + offset + 28, 2); - file.data = data + offset + 30 + offsetNL + offsetEL; - - directory += 46 + namelength + extralength + commentlength; - - this->file.append(file); - } - - return true; - } - - inline vector extract(File &file) { - vector buffer; - - if(file.cmode == 0) { - buffer.resize(file.size); - memcpy(buffer.data(), file.data, file.size); - } - - if(file.cmode == 8) { - buffer.resize(file.size); - if(inflate(buffer.data(), buffer.size(), file.data, file.csize) == false) { - buffer.reset(); - } - } - - return buffer; - } - - inline void close() { - if(fm.open()) fm.close(); - } - - ~unzip() { - close(); - } - -protected: - filemap fm; - const uint8_t *filedata; - unsigned filesize; - - unsigned read(const uint8_t *data, unsigned size) { - unsigned result = 0, shift = 0; - while(size--) { result |= *data++ << shift; shift += 8; } - return result; - } - -public: - vector file; -}; - -} - -#endif diff --git a/higan/phoenix/nall/ups.hpp b/higan/phoenix/nall/ups.hpp deleted file mode 100644 index ffcdb2d7..00000000 --- a/higan/phoenix/nall/ups.hpp +++ /dev/null @@ -1,223 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include -#include -#include -#include - -namespace nall { - -struct ups { - enum class result : unsigned { - unknown, - success, - patch_unwritable, - patch_invalid, - source_invalid, - target_invalid, - target_too_small, - patch_checksum_invalid, - source_checksum_invalid, - target_checksum_invalid, - }; - - function progress; - - result create( - const uint8_t *sourcedata, unsigned sourcelength, - const uint8_t *targetdata, unsigned targetlength, - const char *patchfilename - ) { - source_data = (uint8_t*)sourcedata, target_data = (uint8_t*)targetdata; - source_length = sourcelength, target_length = targetlength; - source_offset = target_offset = 0; - source_checksum = target_checksum = patch_checksum = ~0; - - if(patch_file.open(patchfilename, file::mode::write) == false) return result::patch_unwritable; - - patch_write('U'); - patch_write('P'); - patch_write('S'); - patch_write('1'); - encode(source_length); - encode(target_length); - - unsigned output_length = source_length > target_length ? source_length : target_length; - unsigned relative = 0; - for(unsigned offset = 0; offset < output_length;) { - uint8_t x = source_read(); - uint8_t y = target_read(); - - if(x == y) { - offset++; - continue; - } - - encode(offset++ - relative); - patch_write(x ^ y); - - while(true) { - if(offset >= output_length) { - patch_write(0x00); - break; - } - - x = source_read(); - y = target_read(); - offset++; - patch_write(x ^ y); - if(x == y) break; - } - - relative = offset; - } - - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(source_checksum >> (i * 8)); - for(unsigned i = 0; i < 4; i++) patch_write(target_checksum >> (i * 8)); - uint32_t patch_result_checksum = ~patch_checksum; - for(unsigned i = 0; i < 4; i++) patch_write(patch_result_checksum >> (i * 8)); - - patch_file.close(); - return result::success; - } - - result apply( - const uint8_t *patchdata, unsigned patchlength, - const uint8_t *sourcedata, unsigned sourcelength, - uint8_t *targetdata, unsigned &targetlength - ) { - patch_data = (uint8_t*)patchdata, source_data = (uint8_t*)sourcedata, target_data = targetdata; - patch_length = patchlength, source_length = sourcelength, target_length = targetlength; - patch_offset = source_offset = target_offset = 0; - patch_checksum = source_checksum = target_checksum = ~0; - - if(patch_length < 18) return result::patch_invalid; - if(patch_read() != 'U') return result::patch_invalid; - if(patch_read() != 'P') return result::patch_invalid; - if(patch_read() != 'S') return result::patch_invalid; - if(patch_read() != '1') return result::patch_invalid; - - unsigned source_read_length = decode(); - unsigned target_read_length = decode(); - - if(source_length != source_read_length && source_length != target_read_length) return result::source_invalid; - targetlength = (source_length == source_read_length ? target_read_length : source_read_length); - if(target_length < targetlength) return result::target_too_small; - target_length = targetlength; - - while(patch_offset < patch_length - 12) { - unsigned length = decode(); - while(length--) target_write(source_read()); - while(true) { - uint8_t patch_xor = patch_read(); - target_write(patch_xor ^ source_read()); - if(patch_xor == 0) break; - } - } - while(source_offset < source_length) target_write(source_read()); - while(target_offset < target_length) target_write(source_read()); - - uint32_t patch_read_checksum = 0, source_read_checksum = 0, target_read_checksum = 0; - for(unsigned i = 0; i < 4; i++) source_read_checksum |= patch_read() << (i * 8); - for(unsigned i = 0; i < 4; i++) target_read_checksum |= patch_read() << (i * 8); - uint32_t patch_result_checksum = ~patch_checksum; - source_checksum = ~source_checksum; - target_checksum = ~target_checksum; - for(unsigned i = 0; i < 4; i++) patch_read_checksum |= patch_read() << (i * 8); - - if(patch_result_checksum != patch_read_checksum) return result::patch_invalid; - if(source_checksum == source_read_checksum && source_length == source_read_length) { - if(target_checksum == target_read_checksum && target_length == target_read_length) return result::success; - return result::target_invalid; - } else if(source_checksum == target_read_checksum && source_length == target_read_length) { - if(target_checksum == source_read_checksum && target_length == source_read_length) return result::success; - return result::target_invalid; - } else { - return result::source_invalid; - } - } - -private: - uint8_t *patch_data, *source_data, *target_data; - unsigned patch_length, source_length, target_length; - unsigned patch_offset, source_offset, target_offset; - unsigned patch_checksum, source_checksum, target_checksum; - file patch_file; - - uint8_t patch_read() { - if(patch_offset < patch_length) { - uint8_t n = patch_data[patch_offset++]; - patch_checksum = crc32_adjust(patch_checksum, n); - return n; - } - return 0x00; - } - - uint8_t source_read() { - if(source_offset < source_length) { - uint8_t n = source_data[source_offset++]; - source_checksum = crc32_adjust(source_checksum, n); - return n; - } - return 0x00; - } - - uint8_t target_read() { - uint8_t result = 0x00; - if(target_offset < target_length) { - result = target_data[target_offset]; - target_checksum = crc32_adjust(target_checksum, result); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - return result; - } - - void patch_write(uint8_t n) { - patch_file.write(n); - patch_checksum = crc32_adjust(patch_checksum, n); - } - - void target_write(uint8_t n) { - if(target_offset < target_length) { - target_data[target_offset] = n; - target_checksum = crc32_adjust(target_checksum, n); - } - if(((target_offset++ & 255) == 0) && progress) { - progress(target_offset, source_length > target_length ? source_length : target_length); - } - } - - void encode(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - patch_write(0x80 | x); - break; - } - patch_write(x); - offset--; - } - } - - uint64_t decode() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = patch_read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/utility.hpp b/higan/phoenix/nall/utility.hpp deleted file mode 100644 index b3c1e5aa..00000000 --- a/higan/phoenix/nall/utility.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template class optional { - public: - bool valid; - T value; - public: - inline operator bool() const { return valid; } - inline const T& operator()() const { if(!valid) throw; return value; } - inline optional& operator=(const optional &source) { valid = source.valid; value = source.value; return *this; } - inline optional() : valid(false) {} - inline optional(bool valid, const T &value) : valid(valid), value(value) {} - }; - - template inline T* allocate(unsigned size, const T &value) { - T *array = new T[size]; - for(unsigned i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/higan/phoenix/nall/varint.hpp b/higan/phoenix/nall/varint.hpp deleted file mode 100644 index 98e189db..00000000 --- a/higan/phoenix/nall/varint.hpp +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include - -namespace nall { - template struct uint_t { - private: - typedef typename type_if::type type_t; - type_t data; - - public: - inline operator type_t() const { return data; } - inline type_t operator ++(int) { type_t r = data; data = uclip(data + 1); return r; } - inline type_t operator --(int) { type_t r = data; data = uclip(data - 1); return r; } - inline type_t operator ++() { return data = uclip(data + 1); } - inline type_t operator --() { return data = uclip(data - 1); } - inline type_t operator =(const type_t i) { return data = uclip(i); } - inline type_t operator |=(const type_t i) { return data = uclip(data | i); } - inline type_t operator ^=(const type_t i) { return data = uclip(data ^ i); } - inline type_t operator &=(const type_t i) { return data = uclip(data & i); } - inline type_t operator<<=(const type_t i) { return data = uclip(data << i); } - inline type_t operator>>=(const type_t i) { return data = uclip(data >> i); } - inline type_t operator +=(const type_t i) { return data = uclip(data + i); } - inline type_t operator -=(const type_t i) { return data = uclip(data - i); } - inline type_t operator *=(const type_t i) { return data = uclip(data * i); } - inline type_t operator /=(const type_t i) { return data = uclip(data / i); } - inline type_t operator %=(const type_t i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const type_t i) : data(uclip(i)) {} - - template inline type_t operator=(const uint_t &i) { return data = uclip((type_t)i); } - template inline uint_t(const uint_t &i) : data(uclip(i)) {} - }; - - template struct int_t { - private: - typedef typename type_if::type type_t; - type_t data; - - public: - inline operator type_t() const { return data; } - inline type_t operator ++(int) { type_t r = data; data = sclip(data + 1); return r; } - inline type_t operator --(int) { type_t r = data; data = sclip(data - 1); return r; } - inline type_t operator ++() { return data = sclip(data + 1); } - inline type_t operator --() { return data = sclip(data - 1); } - inline type_t operator =(const type_t i) { return data = sclip(i); } - inline type_t operator |=(const type_t i) { return data = sclip(data | i); } - inline type_t operator ^=(const type_t i) { return data = sclip(data ^ i); } - inline type_t operator &=(const type_t i) { return data = sclip(data & i); } - inline type_t operator<<=(const type_t i) { return data = sclip(data << i); } - inline type_t operator>>=(const type_t i) { return data = sclip(data >> i); } - inline type_t operator +=(const type_t i) { return data = sclip(data + i); } - inline type_t operator -=(const type_t i) { return data = sclip(data - i); } - inline type_t operator *=(const type_t i) { return data = sclip(data * i); } - inline type_t operator /=(const type_t i) { return data = sclip(data / i); } - inline type_t operator %=(const type_t i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const type_t i) : data(sclip(i)) {} - - template inline type_t operator=(const int_t &i) { return data = sclip((type_t)i); } - template inline int_t(const int_t &i) : data(sclip(i)) {} - }; - - template struct varuint_t { - private: - type_t data; - type_t mask; - - public: - inline operator type_t() const { return data; } - inline type_t operator ++(int) { type_t r = data; data = (data + 1) & mask; return r; } - inline type_t operator --(int) { type_t r = data; data = (data - 1) & mask; return r; } - inline type_t operator ++() { return data = (data + 1) & mask; } - inline type_t operator --() { return data = (data - 1) & mask; } - inline type_t operator =(const type_t i) { return data = (i) & mask; } - inline type_t operator |=(const type_t i) { return data = (data | i) & mask; } - inline type_t operator ^=(const type_t i) { return data = (data ^ i) & mask; } - inline type_t operator &=(const type_t i) { return data = (data & i) & mask; } - inline type_t operator<<=(const type_t i) { return data = (data << i) & mask; } - inline type_t operator>>=(const type_t i) { return data = (data >> i) & mask; } - inline type_t operator +=(const type_t i) { return data = (data + i) & mask; } - inline type_t operator -=(const type_t i) { return data = (data - i) & mask; } - inline type_t operator *=(const type_t i) { return data = (data * i) & mask; } - inline type_t operator /=(const type_t i) { return data = (data / i) & mask; } - inline type_t operator %=(const type_t i) { return data = (data % i) & mask; } - - inline void bits(type_t bits) { mask = (1ull << (bits - 1)) + ((1ull << (bits - 1)) - 1); data &= mask; } - inline varuint_t() : data(0ull), mask((type_t)~0ull) {} - inline varuint_t(const type_t i) : data(i), mask((type_t)~0ull) {} - }; -} - -//typedefs - typedef nall::uint_t< 1> uint1_t; - typedef nall::uint_t< 2> uint2_t; - typedef nall::uint_t< 3> uint3_t; - typedef nall::uint_t< 4> uint4_t; - typedef nall::uint_t< 5> uint5_t; - typedef nall::uint_t< 6> uint6_t; - typedef nall::uint_t< 7> uint7_t; -//typedef nall::uint_t< 8> uint8_t; - - typedef nall::uint_t< 9> uint9_t; - typedef nall::uint_t<10> uint10_t; - typedef nall::uint_t<11> uint11_t; - typedef nall::uint_t<12> uint12_t; - typedef nall::uint_t<13> uint13_t; - typedef nall::uint_t<14> uint14_t; - typedef nall::uint_t<15> uint15_t; -//typedef nall::uint_t<16> uint16_t; - - typedef nall::uint_t<17> uint17_t; - typedef nall::uint_t<18> uint18_t; - typedef nall::uint_t<19> uint19_t; - typedef nall::uint_t<20> uint20_t; - typedef nall::uint_t<21> uint21_t; - typedef nall::uint_t<22> uint22_t; - typedef nall::uint_t<23> uint23_t; - typedef nall::uint_t<24> uint24_t; - typedef nall::uint_t<25> uint25_t; - typedef nall::uint_t<26> uint26_t; - typedef nall::uint_t<27> uint27_t; - typedef nall::uint_t<28> uint28_t; - typedef nall::uint_t<29> uint29_t; - typedef nall::uint_t<30> uint30_t; - typedef nall::uint_t<31> uint31_t; -//typedef nall::uint_t<32> uint32_t; - - typedef nall::int_t< 1> int1_t; - typedef nall::int_t< 2> int2_t; - typedef nall::int_t< 3> int3_t; - typedef nall::int_t< 4> int4_t; - typedef nall::int_t< 5> int5_t; - typedef nall::int_t< 6> int6_t; - typedef nall::int_t< 7> int7_t; -//typedef nall::int_t< 8> int8_t; - - typedef nall::int_t< 9> int9_t; - typedef nall::int_t<10> int10_t; - typedef nall::int_t<11> int11_t; - typedef nall::int_t<12> int12_t; - typedef nall::int_t<13> int13_t; - typedef nall::int_t<14> int14_t; - typedef nall::int_t<15> int15_t; -//typedef nall::int_t<16> int16_t; - - typedef nall::int_t<17> int17_t; - typedef nall::int_t<18> int18_t; - typedef nall::int_t<19> int19_t; - typedef nall::int_t<20> int20_t; - typedef nall::int_t<21> int21_t; - typedef nall::int_t<22> int22_t; - typedef nall::int_t<23> int23_t; - typedef nall::int_t<24> int24_t; - typedef nall::int_t<25> int25_t; - typedef nall::int_t<26> int26_t; - typedef nall::int_t<27> int27_t; - typedef nall::int_t<28> int28_t; - typedef nall::int_t<29> int29_t; - typedef nall::int_t<30> int30_t; - typedef nall::int_t<31> int31_t; -//typedef nall::int_t<32> int32_t; - -#endif diff --git a/higan/phoenix/nall/vector.hpp b/higan/phoenix/nall/vector.hpp deleted file mode 100644 index ea714b7b..00000000 --- a/higan/phoenix/nall/vector.hpp +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template struct vector { - struct exception_out_of_bounds{}; - - protected: - T *pool; - unsigned poolsize; - unsigned objectsize; - - public: - explicit operator bool() const { return pool; } - T* data() { return pool; } - const T* data() const { return pool; } - - bool empty() const { return objectsize == 0; } - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - T* move() { - T *result = pool; - pool = nullptr; - poolsize = 0; - objectsize = 0; - return result; - } - - void reset() { - if(pool) { - for(unsigned n = 0; n < objectsize; n++) pool[n].~T(); - free(pool); - } - pool = nullptr; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned size) { - unsigned outputsize = min(size, objectsize); - size = bit::round(size); //amortize growth - T *copy = (T*)calloc(size, sizeof(T)); - for(unsigned n = 0; n < outputsize; n++) new(copy + n) T(pool[n]); - for(unsigned n = 0; n < objectsize; n++) pool[n].~T(); - free(pool); - pool = copy; - poolsize = size; - objectsize = outputsize; - } - - //requires trivial constructor - void resize(unsigned size) { - if(size == objectsize) return; - if(size < objectsize) return reserve(size); - while(size > objectsize) append(T()); - } - - template - void append(const T& data, Args&&... args) { - append(data); - append(std::forward(args)...); - } - - void append(const T& data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - bool appendonce(const T& data) { - if(find(data) == true) return false; - append(data); - return true; - } - - void insert(unsigned position, const T& data) { - append(data); - for(signed n = size() - 1; n > position; n--) pool[n] = pool[n - 1]; - pool[position] = data; - } - - void prepend(const T& data) { - insert(0, data); - } - - void remove(unsigned index = ~0u, unsigned count = 1) { - if(index == ~0) index = objectsize ? objectsize - 1 : 0; - for(unsigned n = index; count + n < objectsize; n++) pool[n] = pool[count + n]; - objectsize = (count + index >= objectsize) ? index : objectsize - count; - } - - T take(unsigned index = ~0u) { - if(index == ~0) index = objectsize ? objectsize - 1 : 0; - if(index >= objectsize) throw exception_out_of_bounds(); - T item = pool[index]; - remove(index); - return item; - } - - void reverse() { - unsigned pivot = size() / 2; - for(unsigned l = 0, r = size() - 1; l < pivot; l++, r--) { - std::swap(pool[l], pool[r]); - } - } - - void sort() { - nall::sort(pool, objectsize); - } - - template void sort(const Comparator &lessthan) { - nall::sort(pool, objectsize, lessthan); - } - - optional find(const T& data) { - for(unsigned n = 0; n < size(); n++) if(pool[n] == data) return {true, n}; - return {false, 0u}; - } - - T& first() { - if(objectsize == 0) throw exception_out_of_bounds(); - return pool[0]; - } - - T& last() { - if(objectsize == 0) throw exception_out_of_bounds(); - return pool[objectsize - 1]; - } - - //access - inline T& operator[](unsigned position) { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline const T& operator[](unsigned position) const { - if(position >= objectsize) throw exception_out_of_bounds(); - return pool[position]; - } - - inline T& operator()(unsigned position) { - if(position >= poolsize) reserve(position + 1); - while(position >= objectsize) append(T()); - return pool[position]; - } - - inline const T& operator()(unsigned position, const T& data) const { - if(position >= objectsize) return data; - return pool[position]; - } - - //iteration - T* begin() { return &pool[0]; } - T* end() { return &pool[objectsize]; } - const T* begin() const { return &pool[0]; } - const T* end() const { return &pool[objectsize]; } - - //copy - inline vector& operator=(const vector &source) { - reset(); - reserve(source.capacity()); - for(auto &data : source) append(data); - return *this; - } - - vector(const vector &source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline vector& operator=(vector &&source) { - reset(); - pool = source.pool, poolsize = source.poolsize, objectsize = source.objectsize; - source.pool = nullptr, source.poolsize = 0, source.objectsize = 0; - return *this; - } - - vector(vector &&source) : pool(nullptr), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - vector() : pool(nullptr), poolsize(0), objectsize(0) { - } - - vector(std::initializer_list list) : pool(nullptr), poolsize(0), objectsize(0) { - for(auto &data : list) append(data); - } - - ~vector() { - reset(); - } - }; -} - -#endif diff --git a/higan/phoenix/nall/windows/detour.hpp b/higan/phoenix/nall/windows/detour.hpp deleted file mode 100644 index e270f318..00000000 --- a/higan/phoenix/nall/windows/detour.hpp +++ /dev/null @@ -1,192 +0,0 @@ -#ifndef NALL_WINDOWS_DETOUR_HPP -#define NALL_WINDOWS_DETOUR_HPP - -#include -#include -#include -#include -#include - -namespace nall { - -#define Copy 0 -#define RelNear 1 - -struct detour { - static bool insert(const string &moduleName, const string &functionName, void *&source, void *target); - static bool remove(const string &moduleName, const string &functionName, void *&source); - -protected: - static unsigned length(const uint8_t *function); - static unsigned mirror(uint8_t *target, const uint8_t *source); - - struct opcode { - uint16_t prefix; - unsigned length; - unsigned mode; - uint16_t modify; - }; - static opcode opcodes[]; -}; - -//TODO: -//* fs:, gs: should force another opcode copy -//* conditional branches within +5-byte range should fail -detour::opcode detour::opcodes[] = { - { 0x50, 1 }, //push eax - { 0x51, 1 }, //push ecx - { 0x52, 1 }, //push edx - { 0x53, 1 }, //push ebx - { 0x54, 1 }, //push esp - { 0x55, 1 }, //push ebp - { 0x56, 1 }, //push esi - { 0x57, 1 }, //push edi - { 0x58, 1 }, //pop eax - { 0x59, 1 }, //pop ecx - { 0x5a, 1 }, //pop edx - { 0x5b, 1 }, //pop ebx - { 0x5c, 1 }, //pop esp - { 0x5d, 1 }, //pop ebp - { 0x5e, 1 }, //pop esi - { 0x5f, 1 }, //pop edi - { 0x64, 1 }, //fs: - { 0x65, 1 }, //gs: - { 0x68, 5 }, //push dword - { 0x6a, 2 }, //push byte - { 0x74, 2, RelNear, 0x0f84 }, //je near -> je far - { 0x75, 2, RelNear, 0x0f85 }, //jne near -> jne far - { 0x89, 2 }, //mov reg,reg - { 0x8b, 2 }, //mov reg,reg - { 0x90, 1 }, //nop - { 0xa1, 5 }, //mov eax,[dword] - { 0xeb, 2, RelNear, 0xe9 }, //jmp near -> jmp far -}; - -bool detour::insert(const string &moduleName, const string &functionName, void *&source, void *target) { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - unsigned sourceLength = detour::length(sourceData); - if(sourceLength < 5) { - //unable to clone enough bytes to insert hook - #if 1 - string output = { "detour::insert(", moduleName, "::", functionName, ") failed: " }; - for(unsigned n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " "); - output.rtrim<1>(" "); - MessageBoxA(0, output, "nall::detour", MB_OK); - #endif - return false; - } - - uint8_t *mirrorData = new uint8_t[512](); - detour::mirror(mirrorData, sourceData); - - DWORD privileges; - VirtualProtect((void*)mirrorData, 512, PAGE_EXECUTE_READWRITE, &privileges); - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - uintmax_t address = (uintmax_t)target - ((uintmax_t)sourceData + 5); - sourceData[0] = 0xe9; //jmp target - sourceData[1] = address >> 0; - sourceData[2] = address >> 8; - sourceData[3] = address >> 16; - sourceData[4] = address >> 24; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)mirrorData; - return true; -} - -bool detour::remove(const string &moduleName, const string &functionName, void *&source) { - HMODULE module = GetModuleHandleW(utf16_t(moduleName)); - if(!module) return false; - - uint8_t *sourceData = (uint8_t*)GetProcAddress(module, functionName); - if(!sourceData) return false; - - uint8_t *mirrorData = (uint8_t*)source; - if(mirrorData == sourceData) return false; //hook was never installed - - unsigned length = detour::length(256 + mirrorData); - if(length < 5) return false; - - DWORD privileges; - VirtualProtect((void*)sourceData, 256, PAGE_EXECUTE_READWRITE, &privileges); - for(unsigned n = 0; n < length; n++) sourceData[n] = mirrorData[256 + n]; - VirtualProtect((void*)sourceData, 256, privileges, &privileges); - - source = (void*)sourceData; - delete[] mirrorData; - return true; -} - -unsigned detour::length(const uint8_t *function) { - unsigned length = 0; - while(length < 5) { - detour::opcode *opcode = 0; - foreach(op, detour::opcodes) { - if(function[length] == op.prefix) { - opcode = &op; - break; - } - } - if(opcode == 0) break; - length += opcode->length; - } - return length; -} - -unsigned detour::mirror(uint8_t *target, const uint8_t *source) { - const uint8_t *entryPoint = source; - for(unsigned n = 0; n < 256; n++) target[256 + n] = source[n]; - - unsigned size = detour::length(source); - while(size) { - detour::opcode *opcode = 0; - foreach(op, detour::opcodes) { - if(*source == op.prefix) { - opcode = &op; - break; - } - } - - switch(opcode->mode) { - case Copy: - for(unsigned n = 0; n < opcode->length; n++) *target++ = *source++; - break; - case RelNear: { - source++; - uintmax_t sourceAddress = (uintmax_t)source + 1 + (int8_t)*source; - *target++ = opcode->modify; - if(opcode->modify >> 8) *target++ = opcode->modify >> 8; - uintmax_t targetAddress = (uintmax_t)target + 4; - uintmax_t address = sourceAddress - targetAddress; - *target++ = address >> 0; - *target++ = address >> 8; - *target++ = address >> 16; - *target++ = address >> 24; - source += 2; - } break; - } - - size -= opcode->length; - } - - uintmax_t address = (entryPoint + detour::length(entryPoint)) - (target + 5); - *target++ = 0xe9; //jmp entryPoint - *target++ = address >> 0; - *target++ = address >> 8; - *target++ = address >> 16; - *target++ = address >> 24; - - return source - entryPoint; -} - -#undef Implied -#undef RelNear - -} - -#endif diff --git a/higan/phoenix/nall/windows/guid.hpp b/higan/phoenix/nall/windows/guid.hpp deleted file mode 100644 index adee891d..00000000 --- a/higan/phoenix/nall/windows/guid.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_WINDOWS_GUID_HPP -#define NALL_WINDOWS_GUID_HPP - -#include -#include - -namespace nall { - -//generate unique GUID -inline string guid() { - random_lfsr lfsr; - lfsr.seed(time(nullptr)); - for(unsigned n = 0; n < 256; n++) lfsr(); - - string output; - for(unsigned n = 0; n < 4; n++) output.append(hex<2>(lfsr())); - output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); - output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); - output.append("-"); - for(unsigned n = 0; n < 2; n++) output.append(hex<2>(lfsr())); - output.append("-"); - for(unsigned n = 0; n < 6; n++) output.append(hex<2>(lfsr())); - return {"{", output, "}"}; -} - -} - -#endif diff --git a/higan/phoenix/nall/windows/launcher.hpp b/higan/phoenix/nall/windows/launcher.hpp deleted file mode 100644 index 914683ec..00000000 --- a/higan/phoenix/nall/windows/launcher.hpp +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef NALL_WINDOWS_LAUNCHER_HPP -#define NALL_WINDOWS_LAUNCHER_HPP - -namespace nall { - -//launch a new process and inject specified DLL into it - -bool launch(const char *applicationName, const char *libraryName, uint32_t entryPoint) { - //if a launcher does not send at least one message, a wait cursor will appear - PostThreadMessage(GetCurrentThreadId(), WM_USER, 0, 0); - MSG msg; - GetMessage(&msg, 0, 0, 0); - - STARTUPINFOW si; - PROCESS_INFORMATION pi; - - memset(&si, 0, sizeof(STARTUPINFOW)); - BOOL result = CreateProcessW( - utf16_t(applicationName), GetCommandLineW(), NULL, NULL, TRUE, - DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS, //do not break if application creates its own processes - NULL, NULL, &si, &pi - ); - if(result == false) return false; - - uint8_t entryData[1024], entryHook[1024] = { - 0x68, 0x00, 0x00, 0x00, 0x00, //push libraryName - 0xb8, 0x00, 0x00, 0x00, 0x00, //mov eax,LoadLibraryW - 0xff, 0xd0, //call eax - 0xcd, 0x03, //int 3 - }; - - entryHook[1] = (uint8_t)((entryPoint + 14) >> 0); - entryHook[2] = (uint8_t)((entryPoint + 14) >> 8); - entryHook[3] = (uint8_t)((entryPoint + 14) >> 16); - entryHook[4] = (uint8_t)((entryPoint + 14) >> 24); - - uint32_t pLoadLibraryW = (uint32_t)GetProcAddress(GetModuleHandleW(L"kernel32"), "LoadLibraryW"); - entryHook[6] = pLoadLibraryW >> 0; - entryHook[7] = pLoadLibraryW >> 8; - entryHook[8] = pLoadLibraryW >> 16; - entryHook[9] = pLoadLibraryW >> 24; - - utf16_t buffer = utf16_t(libraryName); - memcpy(entryHook + 14, buffer, 2 * wcslen(buffer) + 2); - - while(true) { - DEBUG_EVENT event; - WaitForDebugEvent(&event, INFINITE); - - if(event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT) break; - - if(event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT) { - if(event.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT) { - if(event.u.Exception.ExceptionRecord.ExceptionAddress == (void*)(entryPoint + 14 - 1)) { - HANDLE hProcess = OpenProcess(0, FALSE, event.dwProcessId); - HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, event.dwThreadId); - - CONTEXT context; - context.ContextFlags = CONTEXT_FULL; - GetThreadContext(hThread, &context); - - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - context.Eip = entryPoint; - SetThreadContext(hThread, &context); - - CloseHandle(hThread); - CloseHandle(hProcess); - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); - continue; - } - - if(event.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT) { - ReadProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryData, sizeof entryData, NULL); - WriteProcessMemory(pi.hProcess, (void*)entryPoint, (void*)&entryHook, sizeof entryHook, NULL); - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - continue; - } - - ContinueDebugEvent(event.dwProcessId, event.dwThreadId, DBG_CONTINUE); - } - - return true; -} - -} - -#endif diff --git a/higan/phoenix/nall/windows/registry.hpp b/higan/phoenix/nall/windows/registry.hpp deleted file mode 100644 index cb035e19..00000000 --- a/higan/phoenix/nall/windows/registry.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef NALL_WINDOWS_REGISTRY_HPP -#define NALL_WINDOWS_REGISTRY_HPP - -#include -#include - -#include -#ifndef KEY_WOW64_64KEY - #define KEY_WOW64_64KEY 0x0100 -#endif -#ifndef KEY_WOW64_32KEY - #define KEY_WOW64_32KEY 0x0200 -#endif - -#ifndef NWR_FLAGS - #define NWR_FLAGS KEY_WOW64_64KEY -#endif - -#ifndef NWR_SIZE - #define NWR_SIZE 4096 -#endif - -namespace nall { - -struct registry { - static bool exists(const string &name) { - lstring part = name.split("/"); - HKEY handle, rootKey = root(part.take(0)); - string node = part.take(); - string path = part.concatenate("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - wchar_t data[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); - RegCloseKey(handle); - if(result == ERROR_SUCCESS) return true; - } - return false; - } - - static string read(const string &name) { - lstring part = name.split("/"); - HKEY handle, rootKey = root(part.take(0)); - string node = part.take(); - string path = part.concatenate("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - wchar_t data[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - LONG result = RegQueryValueExW(handle, utf16_t(node), nullptr, nullptr, (LPBYTE)&data, (LPDWORD)&size); - RegCloseKey(handle); - if(result == ERROR_SUCCESS) return (const char*)utf8_t(data); - } - return ""; - } - - static void write(const string &name, const string &data = "") { - lstring part = name.split("/"); - HKEY handle, rootKey = root(part.take(0)); - string node = part.take(), path; - DWORD disposition; - for(unsigned n = 0; n < part.size(); n++) { - path.append(part[n]); - if(RegCreateKeyExW(rootKey, utf16_t(path), 0, nullptr, 0, NWR_FLAGS | KEY_ALL_ACCESS, nullptr, &handle, &disposition) == ERROR_SUCCESS) { - if(n == part.size() - 1) { - RegSetValueExW(handle, utf16_t(node), 0, REG_SZ, (BYTE*)(wchar_t*)utf16_t(data), (data.length() + 1) * sizeof(wchar_t)); - } - RegCloseKey(handle); - } - path.append("\\"); - } - } - - static bool remove(const string &name) { - lstring part = name.split("/"); - HKEY rootKey = root(part.take(0)); - string node = part.take(); - string path = part.concatenate("\\"); - if(node.empty()) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS; - return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS; - } - - static lstring contents(const string &name) { - lstring part = name.split("/"), result; - HKEY handle, rootKey = root(part.take(0)); - part.remove(); - string path = part.concatenate("\\"); - if(RegOpenKeyExW(rootKey, utf16_t(path), 0, NWR_FLAGS | KEY_READ, &handle) == ERROR_SUCCESS) { - DWORD folders, nodes; - RegQueryInfoKey(handle, nullptr, nullptr, nullptr, &folders, nullptr, nullptr, &nodes, nullptr, nullptr, nullptr, nullptr); - for(unsigned n = 0; n < folders; n++) { - wchar_t name[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - RegEnumKeyEx(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); - result.append({(const char*)utf8_t(name), "/"}); - } - for(unsigned n = 0; n < nodes; n++) { - wchar_t name[NWR_SIZE] = L""; - DWORD size = NWR_SIZE * sizeof(wchar_t); - RegEnumValueW(handle, n, (wchar_t*)&name, &size, nullptr, nullptr, nullptr, nullptr); - result.append((const char*)utf8_t(name)); - } - RegCloseKey(handle); - } - return result; - } - -private: - static HKEY root(const string &name) { - if(name == "HKCR") return HKEY_CLASSES_ROOT; - if(name == "HKCC") return HKEY_CURRENT_CONFIG; - if(name == "HKCU") return HKEY_CURRENT_USER; - if(name == "HKLM") return HKEY_LOCAL_MACHINE; - if(name == "HKU" ) return HKEY_USERS; - return nullptr; - } -}; - -} - -#endif diff --git a/higan/phoenix/nall/windows/utf8.hpp b/higan/phoenix/nall/windows/utf8.hpp deleted file mode 100644 index 05f89660..00000000 --- a/higan/phoenix/nall/windows/utf8.hpp +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef UNICODE -#undef _WIN32_WINNT -#undef NOMINMAX -#define UNICODE -#define _WIN32_WINNT 0x0501 -#define NOMINMAX -#include -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, nullptr, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, nullptr, 0, nullptr, nullptr); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, nullptr, nullptr); - } - - ~utf8_t() { - delete[] buffer; - } - - utf8_t(const utf8_t&) = delete; - utf8_t& operator=(const utf8_t&) = delete; - - private: - char *buffer; - }; - - inline void utf8_args(int &argc, char **&argv) { - wchar_t **wargv = CommandLineToArgvW(GetCommandLineW(), &argc); - argv = new char*[argc]; - for(unsigned i = 0; i < argc; i++) { - argv[i] = new char[_MAX_PATH]; - strcpy(argv[i], nall::utf8_t(wargv[i])); - } - } -} - -#endif //if defined(_WIN32) - -#endif diff --git a/higan/phoenix/nall/xorg/guard.hpp b/higan/phoenix/nall/xorg/guard.hpp deleted file mode 100644 index a1282683..00000000 --- a/higan/phoenix/nall/xorg/guard.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef NALL_XORG_GUARD_HPP -#define NALL_XORG_GUARD_HPP - -#define None -#undef XlibNone -#define XlibNone 0L -#define Button1 XlibButton1 -#define Button2 XlibButton2 -#define Button3 XlibButton3 -#define Button4 XlibButton4 -#define Button5 XlibButton5 -#define Display XlibDisplay -#define Screen XlibScreen -#define Window XlibWindow - -#else -#undef NALL_XORG_GUARD_HPP - -#undef None -#undef Button1 -#undef Button2 -#undef Button3 -#undef Button4 -#undef Button5 -#undef Display -#undef Screen -#undef Window - -#endif diff --git a/higan/phoenix/nall/xorg/xorg.hpp b/higan/phoenix/nall/xorg/xorg.hpp deleted file mode 100644 index bcf48b46..00000000 --- a/higan/phoenix/nall/xorg/xorg.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef NALL_XORG_XORG_HPP -#define NALL_XORG_XORG_HPP - -#include -#include -#include -#include -#include -#include -#include - -#endif diff --git a/higan/phoenix/nall/zip.hpp b/higan/phoenix/nall/zip.hpp deleted file mode 100644 index 2cc673ce..00000000 --- a/higan/phoenix/nall/zip.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef NALL_ZIP_HPP -#define NALL_ZIP_HPP - -//creates uncompressed ZIP archives - -#include -#include - -namespace nall { - -struct zip { - zip(const string &filename) { - fp.open(filename, file::mode::write); - time_t currentTime = time(nullptr); - tm *info = localtime(¤tTime); - dosTime = (info->tm_hour << 11) | (info->tm_min << 5) | (info->tm_sec >> 1); - dosDate = ((info->tm_year - 80) << 9) | ((1 + info->tm_mon) << 5) + (info->tm_mday); - } - - //append path: append("path/"); - //append file: append("path/file", data, size); - void append(string filename, const uint8_t *data = nullptr, unsigned size = 0u) { - filename.transform("\\", "/"); - uint32_t checksum = crc32_calculate(data, size); - directory.append({filename, checksum, size, fp.offset()}); - - fp.writel(0x04034b50, 4); //signature - fp.writel(0x0014, 2); //minimum version (2.0) - fp.writel(0x0000, 2); //general purpose bit flags - fp.writel(0x0000, 2); //compression method (0 = uncompressed) - fp.writel(dosTime, 2); - fp.writel(dosDate, 2); - fp.writel(checksum, 4); - fp.writel(size, 4); //compressed size - fp.writel(size, 4); //uncompressed size - fp.writel(filename.length(), 2); //file name length - fp.writel(0x0000, 2); //extra field length - fp.print(filename); //file name - - fp.write(data, size); //file data - } - - ~zip() { - //central directory - unsigned baseOffset = fp.offset(); - for(auto &entry : directory) { - fp.writel(0x02014b50, 4); //signature - fp.writel(0x0014, 2); //version made by (2.0) - fp.writel(0x0014, 2); //version needed to extract (2.0) - fp.writel(0x0000, 2); //general purpose bit flags - fp.writel(0x0000, 2); //compression method (0 = uncompressed) - fp.writel(dosTime, 2); - fp.writel(dosDate, 2); - fp.writel(entry.checksum, 4); - fp.writel(entry.size, 4); //compressed size - fp.writel(entry.size, 4); //uncompressed size - fp.writel(entry.filename.length(), 2); //file name length - fp.writel(0x0000, 2); //extra field length - fp.writel(0x0000, 2); //file comment length - fp.writel(0x0000, 2); //disk number start - fp.writel(0x0000, 2); //internal file attributes - fp.writel(0x00000000, 4); //external file attributes - fp.writel(entry.offset, 4); //relative offset of file header - fp.print(entry.filename); - } - unsigned finishOffset = fp.offset(); - - //end of central directory - fp.writel(0x06054b50, 4); //signature - fp.writel(0x0000, 2); //number of this disk - fp.writel(0x0000, 2); //disk where central directory starts - fp.writel(directory.size(), 2); //number of central directory records on this disk - fp.writel(directory.size(), 2); //total number of central directory records - fp.writel(finishOffset - baseOffset, 4); //size of central directory - fp.writel(baseOffset, 4); //offset of central directory - fp.writel(0x0000, 2); //comment length - - fp.close(); - } - -protected: - file fp; - uint16_t dosTime, dosDate; - struct entry_t { - string filename; - uint32_t checksum; - uint32_t size; - uint32_t offset; - }; - vector directory; -}; - -} - -#endif diff --git a/higan/phoenix/qt/action/radio-item.cpp b/higan/phoenix/qt/action/radio-item.cpp index 535be71e..a3bb07ac 100755 --- a/higan/phoenix/qt/action/radio-item.cpp +++ b/higan/phoenix/qt/action/radio-item.cpp @@ -14,7 +14,7 @@ void pRadioItem::setChecked() { locked = false; } -void pRadioItem::setGroup(const set &group) { +void pRadioItem::setGroup(const group &group) { } void pRadioItem::setText(const string &text) { diff --git a/higan/phoenix/qt/platform.moc b/higan/phoenix/qt/platform.moc index 5d8092ff..75906d6c 100755 --- a/higan/phoenix/qt/platform.moc +++ b/higan/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Sat Mar 16 11:52:02 2013 +** Created: Wed Apr 10 03:33:04 2013 ** by: The Qt Meta Object Compiler version 62 (Qt 4.6.3) ** ** WARNING! All changes made in this file will be lost! diff --git a/higan/phoenix/qt/platform.moc.hpp b/higan/phoenix/qt/platform.moc.hpp index 8896a492..931410a9 100755 --- a/higan/phoenix/qt/platform.moc.hpp +++ b/higan/phoenix/qt/platform.moc.hpp @@ -14,15 +14,17 @@ struct pApplication { static QApplication *qtApplication = nullptr; -struct Settings : public configuration { +struct Settings : Configuration::Document { bidirectional_map keymap; - unsigned frameGeometryX; - unsigned frameGeometryY; - unsigned frameGeometryWidth; - unsigned frameGeometryHeight; - unsigned menuGeometryHeight; - unsigned statusGeometryHeight; + struct Geometry : Configuration::Node { + unsigned frameX; + unsigned frameY; + unsigned frameWidth; + unsigned frameHeight; + unsigned menuHeight; + unsigned statusHeight; + } geometry; void load(); void save(); @@ -238,7 +240,7 @@ public: bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {} @@ -542,7 +544,7 @@ public: bool checked(); Size minimumSize(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioButton(RadioButton &radioButton) : pWidget(radioButton), radioButton(radioButton) {} diff --git a/higan/phoenix/qt/settings.cpp b/higan/phoenix/qt/settings.cpp index dcaf9faf..d11622d5 100755 --- a/higan/phoenix/qt/settings.cpp +++ b/higan/phoenix/qt/settings.cpp @@ -3,26 +3,25 @@ namespace phoenix { static Settings *settings = nullptr; void Settings::load() { - string path = { userpath(), ".config/phoenix/qt.cfg" }; - configuration::load(path); + string path = {userpath(), ".config/phoenix/qt.bml"}; + Configuration::Document::load(path); } void Settings::save() { - string path = { userpath(), ".config/" }; - mkdir(path, 0755); - path.append("phoenix/"); - mkdir(path, 0755); - path.append("qt.cfg"); - configuration::save(path); + string path = {userpath(), ".config/phoenix/"}; + directory::create(path, 0755); + path.append("qt.bml"); + Configuration::Document::save(path); } Settings::Settings() { - append(frameGeometryX = 4, "frameGeometryX"); - append(frameGeometryY = 24, "frameGeometryY"); - append(frameGeometryWidth = 8, "frameGeometryWidth"); - append(frameGeometryHeight = 28, "frameGeometryHeight"); - append(menuGeometryHeight = 20, "menuGeometryHeight"); - append(statusGeometryHeight = 20, "statusGeometryHeight"); + geometry.append(geometry.frameX = 4, "FrameX"); + geometry.append(geometry.frameY = 24, "FrameY"); + geometry.append(geometry.frameWidth = 8, "FrameWidth"); + geometry.append(geometry.frameHeight = 28, "FrameHeight"); + geometry.append(geometry.menuHeight = 20, "MenuHeight"); + geometry.append(geometry.statusHeight = 20, "StatusHeight"); + append(geometry, "Geometry"); } } diff --git a/higan/phoenix/qt/widget/radio-button.cpp b/higan/phoenix/qt/widget/radio-button.cpp index 3f8a58e2..ec919819 100644 --- a/higan/phoenix/qt/widget/radio-button.cpp +++ b/higan/phoenix/qt/widget/radio-button.cpp @@ -18,7 +18,7 @@ void pRadioButton::setChecked() { parent().locked = false; } -void pRadioButton::setGroup(const set &group) { +void pRadioButton::setGroup(const group &group) { parent().locked = true; for(auto &item : radioButton.state.group) { item.p.qtRadioButton->setChecked(item.state.checked); diff --git a/higan/phoenix/qt/window.cpp b/higan/phoenix/qt/window.cpp index cbc57cd6..205eade9 100755 --- a/higan/phoenix/qt/window.cpp +++ b/higan/phoenix/qt/window.cpp @@ -34,14 +34,14 @@ Color pWindow::backgroundColor() { } Geometry pWindow::frameMargin() { - unsigned menuHeight = window.state.menuVisible ? settings->menuGeometryHeight : 0; - unsigned statusHeight = window.state.statusVisible ? settings->statusGeometryHeight : 0; - if(window.state.fullScreen) return { 0, menuHeight, 0, menuHeight + statusHeight }; + unsigned menuHeight = window.state.menuVisible ? settings->geometry.menuHeight : 0; + unsigned statusHeight = window.state.statusVisible ? settings->geometry.statusHeight : 0; + if(window.state.fullScreen) return {0, menuHeight, 0, menuHeight + statusHeight}; return { - settings->frameGeometryX, - settings->frameGeometryY + menuHeight, - settings->frameGeometryWidth, - settings->frameGeometryHeight + menuHeight + statusHeight + settings->geometry.frameX, + settings->geometry.frameY + menuHeight, + settings->geometry.frameWidth, + settings->geometry.frameHeight + menuHeight + statusHeight }; } @@ -237,19 +237,19 @@ void pWindow::updateFrameGeometry() { QRect border = qtWindow->frameGeometry(); QRect client = qtWindow->geometry(); - settings->frameGeometryX = client.x() - border.x(); - settings->frameGeometryY = client.y() - border.y(); - settings->frameGeometryWidth = border.width() - client.width(); - settings->frameGeometryHeight = border.height() - client.height(); + settings->geometry.frameX = client.x() - border.x(); + settings->geometry.frameY = client.y() - border.y(); + settings->geometry.frameWidth = border.width() - client.width(); + settings->geometry.frameHeight = border.height() - client.height(); if(window.state.menuVisible) { pApplication::syncX(); - settings->menuGeometryHeight = qtMenu->height(); + settings->geometry.menuHeight = qtMenu->height(); } if(window.state.statusVisible) { pApplication::syncX(); - settings->statusGeometryHeight = qtStatus->height(); + settings->geometry.statusHeight = qtStatus->height(); } settings->save(); @@ -303,8 +303,8 @@ void pWindow::QtWindow::resizeEvent(QResizeEvent*) { QSize pWindow::QtWindow::sizeHint() const { unsigned width = self.window.state.geometry.width; unsigned height = self.window.state.geometry.height; - if(self.window.state.menuVisible) height += settings->menuGeometryHeight; - if(self.window.state.statusVisible) height += settings->statusGeometryHeight; + if(self.window.state.menuVisible) height += settings->geometry.menuHeight; + if(self.window.state.statusVisible) height += settings->geometry.statusHeight; return QSize(width, height); } diff --git a/higan/phoenix/reference/action/radio-item.cpp b/higan/phoenix/reference/action/radio-item.cpp index 2bc64520..05fa4b37 100755 --- a/higan/phoenix/reference/action/radio-item.cpp +++ b/higan/phoenix/reference/action/radio-item.cpp @@ -7,7 +7,7 @@ bool pRadioItem::checked() { void pRadioItem::setChecked() { } -void pRadioItem::setGroup(const set &group) { +void pRadioItem::setGroup(const group &group) { } void pRadioItem::setText(const string &text) { diff --git a/higan/phoenix/reference/action/radio-item.hpp b/higan/phoenix/reference/action/radio-item.hpp index a8e245f8..4879735e 100644 --- a/higan/phoenix/reference/action/radio-item.hpp +++ b/higan/phoenix/reference/action/radio-item.hpp @@ -5,7 +5,7 @@ struct pRadioItem : public pAction { bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {} diff --git a/higan/phoenix/reference/widget/radio-button.cpp b/higan/phoenix/reference/widget/radio-button.cpp index 6fe4d98c..40b3817e 100644 --- a/higan/phoenix/reference/widget/radio-button.cpp +++ b/higan/phoenix/reference/widget/radio-button.cpp @@ -7,7 +7,7 @@ bool pRadioButton::checked() { void pRadioButton::setChecked() { } -void pRadioButton::setGroup(const set &group) { +void pRadioButton::setGroup(const group &group) { } void pRadioButton::setText(const string &text) { diff --git a/higan/phoenix/reference/widget/radio-button.hpp b/higan/phoenix/reference/widget/radio-button.hpp index b560789c..e2d61afa 100644 --- a/higan/phoenix/reference/widget/radio-button.hpp +++ b/higan/phoenix/reference/widget/radio-button.hpp @@ -5,7 +5,7 @@ struct pRadioButton : public pWidget { bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioButton(RadioButton &radioButton) : pWidget(radioButton), radioButton(radioButton) {} diff --git a/higan/phoenix/windows/action/radio-item.cpp b/higan/phoenix/windows/action/radio-item.cpp index e43332bf..7135d0e2 100755 --- a/higan/phoenix/windows/action/radio-item.cpp +++ b/higan/phoenix/windows/action/radio-item.cpp @@ -13,7 +13,7 @@ void pRadioItem::setChecked() { } } -void pRadioItem::setGroup(const set &group) { +void pRadioItem::setGroup(const group &group) { } void pRadioItem::setText(const string &text) { diff --git a/higan/phoenix/windows/platform.hpp b/higan/phoenix/windows/platform.hpp index c755ac50..a913ccf2 100755 --- a/higan/phoenix/windows/platform.hpp +++ b/higan/phoenix/windows/platform.hpp @@ -199,7 +199,7 @@ struct pRadioItem : public pAction { bool checked(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioItem(RadioItem &radioItem) : pAction(radioItem), radioItem(radioItem) {} @@ -423,7 +423,7 @@ struct pRadioButton : public pWidget { bool checked(); Size minimumSize(); void setChecked(); - void setGroup(const set &group); + void setGroup(const group &group); void setText(const string &text); pRadioButton(RadioButton &radioButton) : pWidget(radioButton), radioButton(radioButton) {} diff --git a/higan/phoenix/windows/utility.cpp b/higan/phoenix/windows/utility.cpp index 0e7ddb62..7d4f67a2 100755 --- a/higan/phoenix/windows/utility.cpp +++ b/higan/phoenix/windows/utility.cpp @@ -30,6 +30,12 @@ static HBITMAP CreateBitmap(const image &image) { return hbitmap; } +static unsigned GetWindowZOrder(HWND hwnd) { + unsigned z = 0; + for(HWND next = hwnd; next != NULL; next = GetWindow(next, GW_HWNDPREV)) z++; + return z; +} + static Keyboard::Keycode Keysym(unsigned keysym, unsigned keyflags) { #define pressed(keysym) (GetAsyncKeyState(keysym) & 0x8000) #define enabled(keysym) (GetKeyState(keysym)) diff --git a/higan/phoenix/windows/widget/radio-button.cpp b/higan/phoenix/windows/widget/radio-button.cpp index 9ddf8d2d..ce29f3d8 100644 --- a/higan/phoenix/windows/widget/radio-button.cpp +++ b/higan/phoenix/windows/widget/radio-button.cpp @@ -15,7 +15,7 @@ void pRadioButton::setChecked() { } } -void pRadioButton::setGroup(const set &group) { +void pRadioButton::setGroup(const group &group) { } void pRadioButton::setText(const string &text) { diff --git a/higan/phoenix/windows/window.cpp b/higan/phoenix/windows/window.cpp index 515effec..8f3a1f0a 100755 --- a/higan/phoenix/windows/window.cpp +++ b/higan/phoenix/windows/window.cpp @@ -2,13 +2,40 @@ namespace phoenix { vector pWindow::modal; +//EnableWindow(hwnd, false) sends WM_KILLFOCUS; deactivating said window +//EnableWindow(hwnd, true) does not restore lost focus +//when a modal loop finishes, and the dialog is dismissed, the application loses focus entirely +//due to anti-focus-stealing code in Windows, SetForegroundWindow() cannot restore lost focus +//further, GetActiveWindow() returns nothing when all windows have lost focus +//thus, we must use a focus-stealing hack to reclaim the focus we never intended to dismiss; +//and we must replicate GetActiveWindow() by scanning the Z-order of windows for this process + void pWindow::updateModality() { + //bind thread input to process that currently has input focus + auto threadId = GetWindowThreadProcessId(GetForegroundWindow(), NULL); + AttachThreadInput(threadId, GetCurrentThreadId(), TRUE); + + pWindow *topMost = nullptr; for(auto &object : pObject::objects) { if(dynamic_cast(object) == nullptr) continue; pWindow *p = (pWindow*)object; - if(modal.size() == 0) EnableWindow(p->hwnd, true); - else EnableWindow(p->hwnd, modal.find(p)); + bool enable = modal.size() == 0 || modal.find(p); + EnableWindow(p->hwnd, enable); + if(enable && p->window.visible()) { + if(topMost == nullptr) topMost = p; + else if(GetWindowZOrder(p->hwnd) < GetWindowZOrder(topMost->hwnd)) topMost = p; + } } + + //set input focus on top-most window + if(topMost) { + SetForegroundWindow(topMost->hwnd); + SetActiveWindow(topMost->hwnd); + SetFocus(topMost->hwnd); + } + + //unbind thread input hook + AttachThreadInput(threadId, GetCurrentThreadId(), FALSE); } static const unsigned FixedStyle = WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_BORDER; diff --git a/higan/ruby/ruby_impl.cpp b/higan/ruby/implementation.cpp old mode 100755 new mode 100644 similarity index 98% rename from higan/ruby/ruby_impl.cpp rename to higan/ruby/implementation.cpp index 3cdb50f5..70fdbad0 --- a/higan/ruby/ruby_impl.cpp +++ b/higan/ruby/implementation.cpp @@ -17,9 +17,10 @@ #include #include #elif defined(PLATFORM_OSX) - #define __INTEL_COMPILER + #define decimal CocoaDecimal #include #include + #undef decimal #elif defined(PLATFORM_WINDOWS) #define _WIN32_WINNT 0x0501 #include diff --git a/higan/ruby/ruby.cpp b/higan/ruby/ruby.cpp index 63c36ded..fd3cd86e 100755 --- a/higan/ruby/ruby.cpp +++ b/higan/ruby/ruby.cpp @@ -2,7 +2,7 @@ #undef mkdir #undef usleep -#include +#include namespace ruby { @@ -18,6 +18,9 @@ const char *Video::Depth = "Depth"; const char *Video::Filter = "Filter"; const char *Video::Shader = "Shader"; +const unsigned Video::FilterNearest = 0; +const unsigned Video::FilterLinear = 1; + void VideoInterface::driver(const char *driver) { if(p) term(); diff --git a/higan/ruby/video.hpp b/higan/ruby/video.hpp index c179c236..8083c009 100755 --- a/higan/ruby/video.hpp +++ b/higan/ruby/video.hpp @@ -5,10 +5,8 @@ struct Video { static const char *Filter; static const char *Shader; - enum Filter : unsigned { - FilterPoint, - FilterLinear, - }; + static const unsigned FilterNearest; + static const unsigned FilterLinear; virtual bool cap(const nall::string& name) { return false; } virtual nall::any get(const nall::string& name) { return false; } diff --git a/higan/ruby/video/cgl.cpp b/higan/ruby/video/cgl.cpp index 9022609f..4f3850f8 100644 --- a/higan/ruby/video/cgl.cpp +++ b/higan/ruby/video/cgl.cpp @@ -54,9 +54,8 @@ public: if(view) { @autoreleasepool { [[view openGLContext] makeCurrentContext]; - init(); - OpenGL::shader(settings.shader); - if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; + int synchronize = settings.synchronize; + [[view openGLContext] setValues:&synchronize forParameter:NSOpenGLCPSwapInterval]; } } } @@ -116,28 +115,31 @@ public: @autoreleasepool { NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAccelerated, + NSOpenGLPFAAlphaSize, 8, NSOpenGLPFADoubleBuffer, - NSOpenGLPFAWindow, 0 }; auto size = [settings.handle frame].size; auto format = [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; + auto context = [[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease]; view = [[RubyVideoCGL alloc] initWith:this pixelFormat:format]; + [view setOpenGLContext:context]; [view setFrame:NSMakeRect(0, 0, size.width, size.height)]; [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; [settings.handle addSubview:view]; + [context setView:view]; [view lockFocus]; OpenGL::init(); + //print((const char*)glGetString(GL_VERSION), "\n"); - auto context = (CGLContextObj)[[view openGLContext] CGLContextObj]; int synchronize = settings.synchronize; - CGLSetParameter(context, kCGLCPSwapInterval, &synchronize); + [[view openGLContext] setValues:&synchronize forParameter:NSOpenGLCPSwapInterval]; [view unlockFocus]; } diff --git a/higan/ruby/video/direct3d.cpp b/higan/ruby/video/direct3d.cpp index a66acbad..d75e7d66 100755 --- a/higan/ruby/video/direct3d.cpp +++ b/higan/ruby/video/direct3d.cpp @@ -171,8 +171,8 @@ public: if(lost && !recover()) return; switch(settings.filter) { default: - case Video::FilterPoint: flags.filter = D3DTEXF_POINT; break; - case Video::FilterLinear: flags.filter = D3DTEXF_LINEAR; break; + case Video::FilterNearest: flags.filter = D3DTEXF_POINT; break; + case Video::FilterLinear: flags.filter = D3DTEXF_LINEAR; break; } device->SetSamplerState(0, D3DSAMP_MINFILTER, flags.filter); diff --git a/higan/ruby/video/opengl/bind.hpp b/higan/ruby/video/opengl/bind.hpp index 4fb4ccaf..e74780e0 100644 --- a/higan/ruby/video/opengl/bind.hpp +++ b/higan/ruby/video/opengl/bind.hpp @@ -12,9 +12,16 @@ PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr; PFNGLATTACHSHADERPROC glAttachShader = nullptr; PFNGLDETACHSHADERPROC glDetachShader = nullptr; PFNGLLINKPROGRAMPROC glLinkProgram = nullptr; +PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr; PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr; +PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr; +PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr; +PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr; +PFNGLGENBUFFERSPROC glGenBuffers = nullptr; +PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr; PFNGLBINDBUFFERPROC glBindBuffer = nullptr; +PFNGLBUFFERDATAPROC glBufferData = nullptr; PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation = nullptr; PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr; PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; @@ -52,9 +59,16 @@ static bool OpenGLBind() { bind(PFNGLATTACHSHADERPROC, glAttachShader); bind(PFNGLDETACHSHADERPROC, glDetachShader); bind(PFNGLLINKPROGRAMPROC, glLinkProgram); + bind(PFNGLVALIDATEPROGRAMPROC, glValidateProgram); bind(PFNGLGETPROGRAMIVPROC, glGetProgramiv); bind(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); + bind(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); + bind(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays); + bind(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); + bind(PFNGLGENBUFFERSPROC, glGenBuffers); + bind(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); bind(PFNGLBINDBUFFERPROC, glBindBuffer); + bind(PFNGLBUFFERDATAPROC, glBufferData); bind(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation); bind(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); bind(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); diff --git a/higan/ruby/video/opengl/main.hpp b/higan/ruby/video/opengl/main.hpp index d3a57cfc..45974ce5 100644 --- a/higan/ruby/video/opengl/main.hpp +++ b/higan/ruby/video/opengl/main.hpp @@ -1,20 +1,20 @@ void OpenGL::shader(const char *pathname) { for(auto &program : programs) program.release(); programs.reset(); - settings = ""; + format = GL_RGBA8; + filter = GL_LINEAR; + wrap = GL_CLAMP_TO_BORDER; absoluteWidth = 0, absoluteHeight = 0; relativeWidth = 0, relativeHeight = 0; if(pathname) { auto document = Markup::Document(file::read({pathname, "manifest.bml"})); - for(auto &node : document["settings"]) { - settings.append("#define ", node.name, " ", node.text(), "\n"); - } for(auto &node : document.find("program")) { unsigned n = programs.size(); programs(n).bind(this, node, pathname); } + bind(this, document["output"], pathname); } } @@ -66,35 +66,35 @@ void OpenGL::refresh() { glrUniform1i("phase", p.phase); glrUniform1i("sourceLength", history.size()); - glrUniform1i("textureLength", p.textures.size()); + glrUniform1i("pixmapLength", p.pixmaps.size()); glrUniform4f("targetSize", targetWidth, targetHeight, 1.0 / targetWidth, 1.0 / targetHeight); glrUniform4f("outputSize", outputWidth, outputHeight, 1.0 / outputWidth, 1.0 / outputHeight); //glrUniform4f("targetActualSize", glrSize(targetWidth), glrSize(targetHeight), 1.0 / glrSize(targetWidth), 1.0 / glrSize(targetHeight)); //glrUniform4f("outputActualSize", glrSize(outputWidth), glrSize(outputHeight), 1.0 / glrSize(outputWidth), 1.0 / glrSize(outputHeight)); unsigned aid = 0; - for(auto &texture : history) { + for(auto &pixmap : history) { glrUniform1i({"source[", aid, "]"}, aid); - glrUniform4f({"sourceSize[", aid, "]"}, texture.width, texture.height, 1.0 / texture.width, 1.0 / texture.height); - //glrUniform4f({"sourceActualSize[", aid, "]"}, glrSize(texture.width), glrSize(texture.height), 1.0 / glrSize(texture.width), 1.0 / glrSize(texture.height)); + glrUniform4f({"sourceSize[", aid, "]"}, pixmap.width, pixmap.height, 1.0 / pixmap.width, 1.0 / pixmap.height); + //glrUniform4f({"sourceActualSize[", aid, "]"}, glrSize(pixmap.width), glrSize(pixmap.height), 1.0 / glrSize(pixmap.width), 1.0 / glrSize(pixmap.height)); glActiveTexture(GL_TEXTURE0 + (aid++)); - glBindTexture(GL_TEXTURE_2D, texture.texture); - glrParameters(texture.filter, texture.wrap); + glBindTexture(GL_TEXTURE_2D, pixmap.texture); + glrParameters(pixmap.filter, pixmap.wrap); } unsigned bid = 0; - for(auto &texture : p.textures) { - glrUniform1i({"texture[", bid, "]"}, aid + bid); - glrUniform4f({"textureSize[", bid, "]"}, texture.width, texture.height, 1.0 / texture.width, 1.0 / texture.height); - //glrUniform4f({"textureActualSize[", bid, "]"}, glrSize(texture.width), glrSize(texture.height), 1.0 / glrSize(texture.width), 1.0 / glrSize(texture.height)); + for(auto &pixmap : p.pixmaps) { + glrUniform1i({"pixmap[", bid, "]"}, aid + bid); + glrUniform4f({"pixmapSize[", bid, "]"}, pixmap.width, pixmap.height, 1.0 / pixmap.width, 1.0 / pixmap.height); + //glrUniform4f({"pixmapActualSize[", bid, "]"}, glrSize(pixmap.width), glrSize(pixmap.height), 1.0 / glrSize(pixmap.width), 1.0 / glrSize(pixmap.height)); glActiveTexture(GL_TEXTURE0 + aid + (bid++)); - glBindTexture(GL_TEXTURE_2D, texture.texture); - glrParameters(texture.filter, texture.wrap); + glBindTexture(GL_TEXTURE_2D, pixmap.texture); + glrParameters(pixmap.filter, pixmap.wrap); } glActiveTexture(GL_TEXTURE0); glrParameters(p.filter, p.wrap); - glrRender(sourceWidth, sourceHeight, targetWidth, targetHeight); + p.render(sourceWidth, sourceHeight, targetWidth, targetHeight); glBindTexture(GL_TEXTURE_2D, p.texture); p.phase = (p.phase + 1) % p.modulo; @@ -115,7 +115,7 @@ void OpenGL::refresh() { glrUniform4f("outputSize", outputWidth, outputHeight, 1.0 / outputWidth, 1.0 / outputHeight); glrParameters(filter, wrap); - glrRender(sourceWidth, sourceHeight, outputWidth, outputHeight); + render(sourceWidth, sourceHeight, outputWidth, outputHeight); } bool OpenGL::init() { @@ -134,6 +134,7 @@ bool OpenGL::init() { vertex = glrCreateShader(program, GL_VERTEX_SHADER, OpenGLOutputVertexShader); //geometry = glrCreateShader(program, GL_GEOMETRY_SHADER, OpenGLGeometryShader); fragment = glrCreateShader(program, GL_FRAGMENT_SHADER, OpenGLFragmentShader); + OpenGLSurface::allocate(); glrLinkProgram(program); shader(nullptr); diff --git a/higan/ruby/video/opengl/opengl.hpp b/higan/ruby/video/opengl/opengl.hpp index f8419c4f..17cb9eb1 100644 --- a/higan/ruby/video/opengl/opengl.hpp +++ b/higan/ruby/video/opengl/opengl.hpp @@ -4,6 +4,7 @@ #define glGetProcAddress(name) (*glXGetProcAddress)((const GLubyte*)(name)) #elif defined(PLATFORM_OSX) #include + #include #elif defined(PLATFORM_WIN) #include #include @@ -32,13 +33,17 @@ struct OpenGLTexture { struct OpenGLSurface : OpenGLTexture { GLuint program = 0; GLuint framebuffer = 0; + GLuint vao = 0; + GLuint vbo[3] = {0, 0, 0}; GLuint vertex = 0; GLuint geometry = 0; GLuint fragment = 0; uint32_t *buffer = nullptr; + void allocate(); void size(unsigned width, unsigned height); void release(); + void render(unsigned sourceWidth, unsigned sourceHeight, unsigned targetWidth, unsigned targetHeight); }; struct OpenGLProgram : OpenGLSurface { @@ -49,7 +54,7 @@ struct OpenGLProgram : OpenGLSurface { unsigned absoluteHeight = 0; double relativeWidth = 0; double relativeHeight = 0; - vector textures; + vector pixmaps; void bind(OpenGL *instance, const Markup::Node &node, const string &pathname); void release(); @@ -57,7 +62,6 @@ struct OpenGLProgram : OpenGLSurface { struct OpenGL : OpenGLProgram { vector programs; - string settings; GLuint inputFormat = GL_UNSIGNED_INT_8_8_8_8_REV; unsigned outputWidth = 0; diff --git a/higan/ruby/video/opengl/program.hpp b/higan/ruby/video/opengl/program.hpp index 0c22c24b..19663885 100644 --- a/higan/ruby/video/opengl/program.hpp +++ b/higan/ruby/video/opengl/program.hpp @@ -16,16 +16,14 @@ void OpenGLProgram::bind(OpenGL *instance, const Markup::Node &node, const strin glGenFramebuffers(1, &framebuffer); if(file::exists({pathname, node["vertex"].text()})) { - string source(instance->settings); - source.append(file::read({pathname, node["vertex"].text()})); + string source = file::read({pathname, node["vertex"].text()}); vertex = glrCreateShader(program, GL_VERTEX_SHADER, source); } else { vertex = glrCreateShader(program, GL_VERTEX_SHADER, OpenGLVertexShader); } if(file::exists({pathname, node["geometry"].text()})) { - string source(instance->settings); - source.append(file::read({pathname, node["geometry"].text()})); + string source = file::read({pathname, node["geometry"].text()}); geometry = glrCreateShader(program, GL_GEOMETRY_SHADER, source); } else { //geometry shaders, when attached, must pass all vertex output through to the fragment shaders @@ -33,14 +31,13 @@ void OpenGLProgram::bind(OpenGL *instance, const Markup::Node &node, const strin } if(file::exists({pathname, node["fragment"].text()})) { - string source(instance->settings); - source.append(file::read({pathname, node["fragment"].text()})); + string source = file::read({pathname, node["fragment"].text()}); fragment = glrCreateShader(program, GL_FRAGMENT_SHADER, source); } else { fragment = glrCreateShader(program, GL_FRAGMENT_SHADER, OpenGLFragmentShader); } - for(auto &leaf : node.find("texture")) { + for(auto &leaf : node.find("pixmap")) { nall::image image({pathname, leaf.text()}); image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0); if(image.empty()) continue; @@ -48,32 +45,33 @@ void OpenGLProgram::bind(OpenGL *instance, const Markup::Node &node, const strin GLuint texture; glGenTextures(1, &texture); - unsigned n = textures.size(); - textures(n).texture = texture; - textures(n).width = image.width; - textures(n).height = image.height; - textures(n).format = format; - textures(n).filter = filter; - textures(n).wrap = wrap; - if(leaf["format"].exists()) textures(n).format = glrFormat(leaf["format"].text()); - if(leaf["filter"].exists()) textures(n).filter = glrFilter(leaf["filter"].text()); - if(leaf["wrap"].exists()) textures(n).wrap = glrWrap(leaf["wrap"].text()); + unsigned n = pixmaps.size(); + pixmaps(n).texture = texture; + pixmaps(n).width = image.width; + pixmaps(n).height = image.height; + pixmaps(n).format = format; + pixmaps(n).filter = filter; + pixmaps(n).wrap = wrap; + if(leaf["format"].exists()) pixmaps(n).format = glrFormat(leaf["format"].text()); + if(leaf["filter"].exists()) pixmaps(n).filter = glrFilter(leaf["filter"].text()); + if(leaf["wrap"].exists()) pixmaps(n).wrap = glrWrap(leaf["wrap"].text()); unsigned w = glrSize(image.width), h = glrSize(image.height); uint32_t *buffer = new uint32_t[w * h](); glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, textures(n).format, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); + glTexImage2D(GL_TEXTURE_2D, 0, pixmaps(n).format, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.width, image.height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, image.data); delete[] buffer; } + OpenGLSurface::allocate(); glrLinkProgram(program); } void OpenGLProgram::release() { OpenGLSurface::release(); - for(auto &texture : textures) glDeleteTextures(1, &texture.texture); - textures.reset(); + for(auto &pixmap : pixmaps) glDeleteTextures(1, &pixmap.texture); + pixmaps.reset(); width = 0; height = 0; diff --git a/higan/ruby/video/opengl/shaders.hpp b/higan/ruby/video/opengl/shaders.hpp index 7cc9dd08..558283c3 100644 --- a/higan/ruby/video/opengl/shaders.hpp +++ b/higan/ruby/video/opengl/shaders.hpp @@ -87,6 +87,6 @@ static string OpenGLFragmentShader = R"( out vec4 fragColor; void main() { - fragColor = texture2D(source[0], texCoord); + fragColor = texture(source[0], texCoord); } )"; diff --git a/higan/ruby/video/opengl/surface.hpp b/higan/ruby/video/opengl/surface.hpp index 37a507c4..91faa0ab 100644 --- a/higan/ruby/video/opengl/surface.hpp +++ b/higan/ruby/video/opengl/surface.hpp @@ -1,3 +1,9 @@ +void OpenGLSurface::allocate() { + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + glGenBuffers(3, &vbo[0]); +} + void OpenGLSurface::size(unsigned w, unsigned h) { if(width == w && height == h) return; width = w, height = h; @@ -20,6 +26,8 @@ void OpenGLSurface::size(unsigned w, unsigned h) { } void OpenGLSurface::release() { + if(vbo[0]) { glDeleteBuffers(3, &vbo[0]); for(auto &o : vbo) o = 0; } + if(vao) { glDeleteVertexArrays(1, &vao); vao = 0; } if(vertex) { glDetachShader(program, vertex); glDeleteShader(vertex); vertex = 0; } if(geometry) { glDetachShader(program, geometry); glDeleteShader(geometry); geometry = 0; } if(fragment) { glDetachShader(program, fragment); glDeleteShader(fragment); fragment = 0; } @@ -28,3 +36,79 @@ void OpenGLSurface::release() { if(program) { glDeleteProgram(program); program = 0; } width = 0, height = 0; } + +void OpenGLSurface::render(unsigned sourceWidth, unsigned sourceHeight, unsigned targetWidth, unsigned targetHeight) { + glViewport(0, 0, targetWidth, targetHeight); + + float w = (float)sourceWidth / (float)glrSize(sourceWidth); + float h = (float)sourceHeight / (float)glrSize(sourceHeight); + float u = (float)targetWidth, v = (float)targetHeight; + GLint location; + + GLfloat modelView[] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1, + }; + + GLfloat projection[] = { + 2.0f/u, 0.0f, 0.0f, 0.0f, + 0.0f, 2.0f/v, 0.0f, 0.0f, + 0.0f, 0.0f, -1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, 1.0f, + }; + + GLfloat modelViewProjection[4 * 4]; + Matrix::Multiply(modelViewProjection, modelView, 4, 4, projection, 4, 4); + + GLfloat vertices[] = { + 0, 0, 0, 1, + u, 0, 0, 1, + 0, v, 0, 1, + u, v, 0, 1, + }; + + GLfloat positions[4 * 4]; + for(unsigned n = 0; n < 16; n += 4) { + Matrix::Multiply(&positions[n], &vertices[n], 1, 4, modelViewProjection, 4, 4); + } + + GLfloat texCoords[] = { + 0, 0, + w, 0, + 0, h, + w, h, + }; + + glrUniformMatrix4fv("modelView", modelView); + glrUniformMatrix4fv("projection", projection); + glrUniformMatrix4fv("modelViewProjection", modelViewProjection); + + glBindVertexArray(vao); + + glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), vertices, GL_STATIC_DRAW); + GLuint locationVertex = glGetAttribLocation(program, "vertex"); + glEnableVertexAttribArray(locationVertex); + glVertexAttribPointer(locationVertex, 4, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); + glBufferData(GL_ARRAY_BUFFER, 16 * sizeof(GLfloat), positions, GL_STATIC_DRAW); + GLuint locationPosition = glGetAttribLocation(program, "position"); + glEnableVertexAttribArray(locationPosition); + glVertexAttribPointer(locationPosition, 4, GL_FLOAT, GL_FALSE, 0, 0); + + glBindBuffer(GL_ARRAY_BUFFER, vbo[2]); + glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), texCoords, GL_STATIC_DRAW); + GLuint locationTexCoord = glGetAttribLocation(program, "texCoord"); + glEnableVertexAttribArray(locationTexCoord); + glVertexAttribPointer(locationTexCoord, 2, GL_FLOAT, GL_FALSE, 0, 0); + + glBindFragDataLocation(program, 0, "fragColor"); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + + glDisableVertexAttribArray(locationVertex); + glDisableVertexAttribArray(locationPosition); + glDisableVertexAttribArray(locationTexCoord); +} diff --git a/higan/ruby/video/opengl/utility.hpp b/higan/ruby/video/opengl/utility.hpp index 142822f6..aa7e843f 100644 --- a/higan/ruby/video/opengl/utility.hpp +++ b/higan/ruby/video/opengl/utility.hpp @@ -59,77 +59,6 @@ static void glrParameters(GLuint filter, GLuint wrap) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); } -static void glrRender(unsigned sourceWidth, unsigned sourceHeight, unsigned targetWidth, unsigned targetHeight) { - glViewport(0, 0, targetWidth, targetHeight); - - float w = (float)sourceWidth / (float)glrSize(sourceWidth); - float h = (float)sourceHeight / (float)glrSize(sourceHeight); - float u = (float)targetWidth, v = (float)targetHeight; - GLint location; - - GLfloat modelView[] = { - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, - }; - - GLfloat projection[] = { - 2.0f/u, 0.0f, 0.0f, 0.0f, - 0.0f, 2.0f/v, 0.0f, 0.0f, - 0.0f, 0.0f, -1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, 1.0f, - }; - - GLfloat modelViewProjection[4 * 4]; - Matrix::Multiply(modelViewProjection, modelView, 4, 4, projection, 4, 4); - - GLfloat vertices[] = { - 0, 0, 0, 1, - u, 0, 0, 1, - 0, v, 0, 1, - u, v, 0, 1, - }; - - GLfloat positions[4 * 4]; - for(unsigned n = 0; n < 16; n += 4) { - Matrix::Multiply(&positions[n], &vertices[n], 1, 4, modelViewProjection, 4, 4); - } - - GLfloat texCoords[] = { - 0, 0, - w, 0, - 0, h, - w, h, - }; - - glrUniformMatrix4fv("modelView", modelView); - glrUniformMatrix4fv("projection", projection); - glrUniformMatrix4fv("modelViewProjection", modelViewProjection); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - - GLint locationVertex = glGetAttribLocation(glrProgram(), "vertex"); - glEnableVertexAttribArray(locationVertex); - glVertexAttribPointer(locationVertex, 4, GL_FLOAT, GL_FALSE, 0, vertices); - - GLint locationPosition = glGetAttribLocation(glrProgram(), "position"); - glEnableVertexAttribArray(locationPosition); - glVertexAttribPointer(locationPosition, 4, GL_FLOAT, GL_FALSE, 0, positions); - - GLint locationTexCoord = glGetAttribLocation(glrProgram(), "texCoord"); - glEnableVertexAttribArray(locationTexCoord); - glVertexAttribPointer(locationTexCoord, 2, GL_FLOAT, GL_FALSE, 0, texCoords); - - glBindFragDataLocation(glrProgram(), 0, "fragColor"); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - glDisableVertexAttribArray(locationVertex); - glDisableVertexAttribArray(locationPosition); - glDisableVertexAttribArray(locationTexCoord); -} - static GLuint glrCreateShader(GLuint program, GLuint type, const char *source) { GLuint shader = glCreateShader(type); glShaderSource(shader, 1, &source, 0); @@ -149,7 +78,7 @@ static GLuint glrCreateShader(GLuint program, GLuint type, const char *source) { return shader; } -static GLint glrLinkProgram(GLuint program) { +static void glrLinkProgram(GLuint program) { glLinkProgram(program); GLint result = GL_FALSE; glGetProgramiv(program, GL_LINK_STATUS, &result); @@ -161,4 +90,15 @@ static GLint glrLinkProgram(GLuint program) { text[length] = 0; print("[ruby::OpenGL: shader linker error]\n", (const char*)text, "\n\n"); } + glValidateProgram(program); + result = GL_FALSE; + glGetProgramiv(program, GL_VALIDATE_STATUS, &result); + if(result == GL_FALSE) { + GLint length = 0; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); + char text[length + 1]; + glGetProgramInfoLog(program, length, &length, text); + text[length] = 0; + print("[ruby::OpenGL: shader validation error]\n", (const char*)text, "\n\n"); + } } diff --git a/higan/target-ethos/Makefile b/higan/target-ethos/Makefile index 26267959..2a3a3acc 100755 --- a/higan/target-ethos/Makefile +++ b/higan/target-ethos/Makefile @@ -86,18 +86,20 @@ resource: sourcery $(ui)/resource/resource.bml $(ui)/resource/resource.cpp $(ui)/resource/resource.hpp install: -ifeq ($(USER),root) - @echo Please do not run make install as root. - @echo The installer needs to know your home directory to install important files. -else ifeq ($(platform),x) +ifeq ($(platform),x) sudo install -D -m 755 out/$(name) $(DESTDIR)$(prefix)/bin/$(name) sudo install -D -m 644 data/$(name).png $(DESTDIR)$(prefix)/share/pixmaps/$(name).png sudo install -D -m 644 data/$(name).desktop $(DESTDIR)$(prefix)/share/applications/$(name).desktop - mkdir -p ~/.config/$(name) - cp -R profile/* ~/.config/$(name) - cp data/cheats.bml ~/.config/$(name)/cheats.bml - chmod -R 777 ~/.config/$(name) + sudo mkdir -p /usr/share/$(name) + sudo cp -R profile/* /usr/share/$(name) + sudo cp data/cheats.bml /usr/share/$(name)/cheats.bml + sudo chmod -R 777 /usr/share/$(name) +else ifeq ($(platform),osx) + sudo mkdir -p /Library/Application\ Support/$(name) + sudo cp -R profile/* /Library/Application\ Support/$(name) + sudo cp data/cheats.bml /Library/Application\ Support/$(name)/cheats.bml + sudo chmod -R 777 /Library/Application\ Support/$(name) endif uninstall: diff --git a/higan/target-ethos/configuration/configuration.cpp b/higan/target-ethos/configuration/configuration.cpp index 5b24f2e2..816e24f4 100755 --- a/higan/target-ethos/configuration/configuration.cpp +++ b/higan/target-ethos/configuration/configuration.cpp @@ -1,42 +1,54 @@ #include "../ethos.hpp" -Configuration *config = nullptr; +ConfigurationSettings *config = nullptr; + +ConfigurationSettings::ConfigurationSettings() { + video.append(video.driver = ruby::video.default_driver(), "Driver"); + video.append(video.synchronize = false, "Synchronize"); + video.append(video.shader = "Blur", "Shader"); + video.append(video.scaleMode = 0, "ScaleMode"); + video.append(video.aspectCorrection = true, "AspectCorrection"); + video.maskOverscan.assign(video.maskOverscan.enable = false); + video.maskOverscan.append(video.maskOverscan.horizontal = 8, "Horizontal"); + video.maskOverscan.append(video.maskOverscan.vertical = 8, "Vertical"); + video.append(video.maskOverscan, "MaskOverscan"); + video.append(video.saturation = 100, "Saturation"); + video.append(video.gamma = 150, "Gamma"); + video.append(video.luminance = 100, "Luminance"); + video.append(video.startFullScreen = false, "StartFullScreen"); + append(video, "Video"); + + audio.append(audio.driver = ruby::audio.default_driver(), "Driver"); + audio.append(audio.synchronize = true, "Synchronize"); + audio.append(audio.frequency = 48000, "Frequency"); + audio.append(audio.latency = 60, "Latency"); + audio.append(audio.resampler = 2, "Resampler"); + audio.append(audio.volume = 100, "Volume"); + audio.append(audio.mute = false, "Mute"); + append(audio, "Audio"); + + input.append(input.driver = ruby::input.default_driver(), "Driver"); + input.focus.append(input.focus.pause = false, "Pause"); + input.focus.append(input.focus.allow = false, "AllowInput"); + input.append(input.focus, "Focus"); + append(input, "Input"); + + timing.append(timing.video = 60.0, "Video"); + timing.append(timing.audio = 48000.0, "Audio"); + append(timing, "Timing"); + + server.append(server.hostname = "", "Hostname"); + server.append(server.username = "", "Username"); + server.append(server.password = "", "Password"); + append(server, "Server"); -Configuration::Configuration() { - append(video.driver = ruby::video.default_driver(), "Video::Driver"); - append(video.synchronize = false, "Video::Synchronize"); - append(video.shader = "Blur", "Video::Shader"); - append(video.scaleMode = 0, "Video::ScaleMode"); - append(video.aspectCorrection = true, "Video::AspectCorrection"); - append(video.maskOverscan = false, "Video::MaskOverscan"); - append(video.maskOverscanHorizontal = 8, "Video::MaskOverscan::Horizontal"); - append(video.maskOverscanVertical = 8, "Video::MaskOverscan::Vertical"); - append(video.saturation = 100, "Video::Saturation"); - append(video.gamma = 150, "Video::Gamma"); - append(video.luminance = 100, "Video::Luminance"); - append(video.startFullScreen = false, "Video::StartFullScreen"); - append(audio.driver = ruby::audio.default_driver(), "Audio::Driver"); - append(audio.synchronize = true, "Audio::Synchronize"); - append(audio.frequency = 48000, "Audio::Frequency"); - append(audio.latency = 60, "Audio::Latency"); - append(audio.resampler = 2, "Audio::Resampler"); - append(audio.volume = 100, "Audio::Volume"); - append(audio.mute = false, "Audio::Mute"); - append(input.driver = ruby::input.default_driver(), "Input::Driver"); - append(input.focusPause = false, "Input::Focus::Pause"); - append(input.focusAllow = false, "Input::Focus::AllowInput"); - append(timing.video = 60.0, "Timing::Video"); - append(timing.audio = 48000.0, "Timing::Audio"); - append(server.hostname = "", "Server::Hostname"); - append(server.username = "", "Server::Username"); - append(server.password = "", "Server::Password"); load(); } -void Configuration::load() { - configuration::load(program->path("settings.cfg")); +void ConfigurationSettings::load() { + Configuration::Document::load(program->path("settings.bml")); save(); //creates file if it does not exist } -void Configuration::save() { - configuration::save(program->path("settings.cfg")); +void ConfigurationSettings::save() { + Configuration::Document::save(program->path("settings.bml")); } diff --git a/higan/target-ethos/configuration/configuration.hpp b/higan/target-ethos/configuration/configuration.hpp index 79c01ced..47268467 100755 --- a/higan/target-ethos/configuration/configuration.hpp +++ b/higan/target-ethos/configuration/configuration.hpp @@ -1,20 +1,22 @@ -struct Configuration : configuration { - struct Video { +struct ConfigurationSettings : Configuration::Document { + struct Video : Configuration::Node { string driver; bool synchronize; string shader; unsigned scaleMode; bool aspectCorrection; - bool maskOverscan; - unsigned maskOverscanHorizontal; - unsigned maskOverscanVertical; + struct MaskOverscan : Configuration::Node { + bool enable; + unsigned horizontal; + unsigned vertical; + } maskOverscan; unsigned saturation; unsigned gamma; unsigned luminance; bool startFullScreen; } video; - struct Audio { + struct Audio : Configuration::Node { string driver; bool synchronize; unsigned frequency; @@ -24,18 +26,20 @@ struct Configuration : configuration { bool mute; } audio; - struct Input { + struct Input : Configuration::Node { string driver; - bool focusPause; - bool focusAllow; + struct Focus : Configuration::Node { + bool pause; + bool allow; + } focus; } input; - struct Timing { + struct Timing : Configuration::Node { double video; double audio; } timing; - struct Server { + struct Server : Configuration::Node { string hostname; string username; string password; @@ -43,7 +47,7 @@ struct Configuration : configuration { void load(); void save(); - Configuration(); + ConfigurationSettings(); }; -extern Configuration *config; +extern ConfigurationSettings *config; diff --git a/higan/target-ethos/ethos.cpp b/higan/target-ethos/ethos.cpp index c590b1d2..b0c28ff3 100755 --- a/higan/target-ethos/ethos.cpp +++ b/higan/target-ethos/ethos.cpp @@ -11,7 +11,7 @@ Emulator::Interface& system() { } bool Program::focused() { - return config->input.focusAllow || presentation->focused(); + return config->input.focus.allow || presentation->focused(); } string Program::path(const string &name) { @@ -27,7 +27,7 @@ string Program::path(const string &name) { void Program::main() { inputManager->poll(); utility->updateStatus(); - autopause = config->input.focusPause && presentation->focused() == false; + autopause = config->input.focus.pause && presentation->focused() == false; if(active == nullptr || system().loaded() == false || pause || autopause) { audio.clear(); @@ -65,7 +65,7 @@ Program::Program(int argc, char **argv) { monospaceFont = Font::monospace(8); } - config = new Configuration; + config = new ConfigurationSettings; video.driver(config->video.driver); audio.driver(config->audio.driver); input.driver(config->input.driver); diff --git a/higan/target-ethos/general/browser.cpp b/higan/target-ethos/general/browser.cpp index d514bd5f..194dd2e5 100755 --- a/higan/target-ethos/general/browser.cpp +++ b/higan/target-ethos/general/browser.cpp @@ -61,7 +61,7 @@ void Browser::synchronize() { } void Browser::saveConfiguration() { - config.save(program->path("paths.cfg")); + config.save(program->path("paths.bml")); } void Browser::bootstrap() { @@ -85,12 +85,14 @@ void Browser::bootstrap() { } for(auto &folder : folderList) { - config.append(folder.path, folder.extension); - config.append(folder.selection, string{folder.extension, "::selection"}); + Configuration::Node node; + node.append(folder.path, "Path"); + node.append(folder.selection, "Selection"); + config.append(node, folder.extension); } - config.load(program->path("paths.cfg")); - config.save(program->path("paths.cfg")); + config.load(program->path("paths.bml")); + config.save(program->path("paths.bml")); } string Browser::select(const string &title, const string &extension) { diff --git a/higan/target-ethos/general/browser.hpp b/higan/target-ethos/general/browser.hpp index c116fd46..7fb8bb1a 100755 --- a/higan/target-ethos/general/browser.hpp +++ b/higan/target-ethos/general/browser.hpp @@ -16,7 +16,7 @@ struct Browser : Window { Browser(); private: - configuration config; + Configuration::Document config; struct Folder { string extension; string path; diff --git a/higan/target-ethos/general/presentation.cpp b/higan/target-ethos/general/presentation.cpp index 54c53df0..bbd5da61 100755 --- a/higan/target-ethos/general/presentation.cpp +++ b/higan/target-ethos/general/presentation.cpp @@ -23,7 +23,7 @@ void Presentation::synchronize() { case 2: stretchVideo.setChecked(); break; } aspectCorrection.setChecked(config->video.aspectCorrection); - maskOverscan.setChecked(config->video.maskOverscan); + maskOverscan.setChecked(config->video.maskOverscan.enable); synchronizeVideo.setChecked(config->video.synchronize); synchronizeAudio.setChecked(config->audio.synchronize); muteAudio.setChecked(config->audio.mute); @@ -140,7 +140,7 @@ Presentation::Presentation() : active(nullptr) { scaleVideo.onActivate = [&] { config->video.scaleMode = 1; utility->resize(); }; stretchVideo.onActivate = [&] { config->video.scaleMode = 2; utility->resize(); }; aspectCorrection.onToggle = [&] { config->video.aspectCorrection = aspectCorrection.checked(); utility->resize(); }; - maskOverscan.onToggle = [&] { config->video.maskOverscan = maskOverscan.checked(); }; + maskOverscan.onToggle = [&] { config->video.maskOverscan.enable = maskOverscan.checked(); }; synchronizeVideo.onToggle = [&] { config->video.synchronize = synchronizeVideo.checked(); utility->synchronizeRuby(); }; synchronizeAudio.onToggle = [&] { config->audio.synchronize = synchronizeAudio.checked(); utility->synchronizeRuby(); }; muteAudio.onToggle = [&] { config->audio.mute = muteAudio.checked(); utility->synchronizeRuby(); }; @@ -217,21 +217,22 @@ void Presentation::bootstrap() { } void Presentation::loadShaders() { - if(config->video.driver != "OpenGL") return; //only the OpenGL driver has shader support - - string pathname = program->path("Video Shaders/"); - lstring shaders = directory::folders(pathname, "*.shader"); - for(auto &name : shaders) { - auto shader = new RadioItem; - shader->setText(name.split<1>(".shader/")(0)); - shader->onActivate = [=] { - config->video.shader = {pathname, name}; - utility->updateShader(); - }; - shaderList.append(shader); + //only the OpenGL driver has video shader support + if(config->video.driver == "OpenGL") { + string pathname = program->path("Video Shaders/"); + lstring shaders = directory::folders(pathname, "*.shader"); + for(auto &name : shaders) { + auto shader = new RadioItem; + shader->setText(name.split<1>(".shader/")(0)); + shader->onActivate = [=] { + config->video.shader = {pathname, name}; + utility->updateShader(); + }; + shaderList.append(shader); + } } - set group; + nall::group group; group.append(shaderNone); group.append(shaderBlur); for(auto &shader : shaderList) group.append(*shader); diff --git a/higan/target-ethos/general/presentation.hpp b/higan/target-ethos/general/presentation.hpp index da260008..0f5a4175 100755 --- a/higan/target-ethos/general/presentation.hpp +++ b/higan/target-ethos/general/presentation.hpp @@ -12,7 +12,7 @@ struct Presentation : Window { Separator controllerSeparator; struct Port { Menu menu; - set group; + nall::group group; vector device; }; vector port; diff --git a/higan/target-ethos/input/hotkeys.cpp b/higan/target-ethos/input/hotkeys.cpp index 60f70887..1bc59a29 100755 --- a/higan/target-ethos/input/hotkeys.cpp +++ b/higan/target-ethos/input/hotkeys.cpp @@ -141,11 +141,11 @@ void InputManager::appendHotkeys() { }; } + Configuration::Node node; for(auto &hotkey : hotkeyMap) { - string name = {"Hotkey::", hotkey->name}; - name.replace(" ", ""); - config.append(hotkey->mapping, name); + node.append(hotkey->mapping, string{hotkey->name}.replace(" ", "")); } + config.append(node, "Hotkey"); } void InputManager::pollHotkeys() { diff --git a/higan/target-ethos/input/input.cpp b/higan/target-ethos/input/input.cpp index 0c2ab8f3..69a9f91a 100755 --- a/higan/target-ethos/input/input.cpp +++ b/higan/target-ethos/input/input.cpp @@ -245,7 +245,7 @@ int16_t InputManager::poll(unsigned scancode) { } void InputManager::saveConfiguration() { - config.save(program->path("input.cfg")); + config.save(program->path("input.bml")); } InputManager::InputManager() { @@ -257,8 +257,14 @@ InputManager::InputManager() { void InputManager::bootstrap() { unsigned guid = 0; for(auto &emulator : program->emulator) { + Configuration::Node emulatorNode; + for(auto &port : emulator->port) { + Configuration::Node portNode; + for(auto &device : port.device) { + Configuration::Node deviceNode; + for(auto &number : device.order) { auto &input = device.input[number]; @@ -268,26 +274,29 @@ void InputManager::bootstrap() { if(input.type == 2) abstract = new AbsoluteInput; if(input.type >= 3) continue; - abstract->name = {emulator->information.name, "::", port.name, "::", device.name, "::", input.name}; - abstract->name.replace(" ", ""); + abstract->name = string{input.name}.replace(" ", ""); abstract->mapping = "None"; abstract->logic = 0; //OR input.guid = guid++; inputMap.append(abstract); - } - } - } - } - for(auto &input : inputMap) { - config.append(input->mapping, input->name); + deviceNode.append(abstract->mapping, abstract->name); + } + + portNode.append(deviceNode, string{device.name}.replace(" ", "")); + } + + emulatorNode.append(portNode, string{port.name}.replace(" ", "")); + } + + config.append(emulatorNode, string{emulator->information.name}.replace(" ", "")); } appendHotkeys(); - config.load(program->path("input.cfg")); - config.save(program->path("input.cfg")); + config.load(program->path("input.bml")); + config.save(program->path("input.bml")); bind(); } diff --git a/higan/target-ethos/input/input.hpp b/higan/target-ethos/input/input.hpp index c6f7e2b3..ac49f98b 100755 --- a/higan/target-ethos/input/input.hpp +++ b/higan/target-ethos/input/input.hpp @@ -59,7 +59,7 @@ struct InputManager { void pollHotkeys(); private: - configuration config; + Configuration::Document config; }; extern InputManager *inputManager; diff --git a/higan/target-ethos/interface/interface.cpp b/higan/target-ethos/interface/interface.cpp index 16ad4e63..5cdb19a6 100755 --- a/higan/target-ethos/interface/interface.cpp +++ b/higan/target-ethos/interface/interface.cpp @@ -62,9 +62,9 @@ void Interface::videoRefresh(const uint32_t *data, unsigned pitch, unsigned widt memcpy(output + y * outputPitch, data + y * pitch, 4 * width); } - if(system().information.overscan && config->video.maskOverscan) { - unsigned h = config->video.maskOverscanHorizontal; - unsigned v = config->video.maskOverscanVertical; + if(system().information.overscan && config->video.maskOverscan.enable) { + unsigned h = config->video.maskOverscan.horizontal; + unsigned v = config->video.maskOverscan.vertical; if(h) for(unsigned y = 0; y < height; y++) { memset(output + y * outputPitch, 0, 4 * h); diff --git a/higan/target-ethos/settings/advanced.cpp b/higan/target-ethos/settings/advanced.cpp index e0bdff6b..5134b026 100644 --- a/higan/target-ethos/settings/advanced.cpp +++ b/higan/target-ethos/settings/advanced.cpp @@ -10,7 +10,7 @@ AdvancedSettings::AdvancedSettings() { libraryTitle.setText("Game Library Path"); libraryLabel.setText("Path:"); libraryPath.setEditable(false); - string path = string::read({configpath(), "higan/library.cfg"}).strip().transform("\\", "/"); + string path = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/"); if(path.empty()) path = {userpath(), "Emulation/"}; if(path.endswith("/") == false) path.append("/"); libraryPath.setText(path); @@ -69,7 +69,7 @@ AdvancedSettings::AdvancedSettings() { libraryBrowse.onActivate = [&] { string path = BrowserWindow().setParent(*settings).setPath(userpath()).directory(); if(path.empty()) return; - file::write({configpath(), "higan/library.cfg"}, path); + file::write({configpath(), "higan/library.bml"}, {"Path: ", path, "\n"}); libraryPath.setText(path); }; } diff --git a/higan/target-ethos/settings/input.cpp b/higan/target-ethos/settings/input.cpp index 4bd7c548..7a3b2d7d 100755 --- a/higan/target-ethos/settings/input.cpp +++ b/higan/target-ethos/settings/input.cpp @@ -33,12 +33,12 @@ InputSettings::InputSettings() : activeInput(nullptr) { systemList.append(emulator->information.name); } - focusPause.setChecked(config->input.focusPause); - focusAllow.setChecked(config->input.focusAllow); - focusAllow.setEnabled(!config->input.focusPause); + focusPause.setChecked(config->input.focus.pause); + focusAllow.setChecked(config->input.focus.allow); + focusAllow.setEnabled(!config->input.focus.pause); - focusPause.onToggle = [&] { config->input.focusPause = focusPause.checked(); focusAllow.setEnabled(!focusPause.checked()); }; - focusAllow.onToggle = [&] { config->input.focusAllow = focusAllow.checked(); }; + focusPause.onToggle = [&] { config->input.focus.pause = focusPause.checked(); focusAllow.setEnabled(!focusPause.checked()); }; + focusAllow.onToggle = [&] { config->input.focus.allow = focusAllow.checked(); }; systemList.onChange = {&InputSettings::systemChanged, this}; portList.onChange = {&InputSettings::portChanged, this}; deviceList.onChange = {&InputSettings::deviceChanged, this}; diff --git a/higan/target-ethos/settings/video.cpp b/higan/target-ethos/settings/video.cpp index 3f190ee8..224d4f6e 100755 --- a/higan/target-ethos/settings/video.cpp +++ b/higan/target-ethos/settings/video.cpp @@ -36,8 +36,8 @@ VideoSettings::VideoSettings() { saturation.slider.setPosition(config->video.saturation); gamma.slider.setPosition(config->video.gamma - 100); luminance.slider.setPosition(config->video.luminance); - overscanHorizontal.slider.setPosition(config->video.maskOverscanHorizontal); - overscanVertical.slider.setPosition(config->video.maskOverscanVertical); + overscanHorizontal.slider.setPosition(config->video.maskOverscan.horizontal); + overscanVertical.slider.setPosition(config->video.maskOverscan.vertical); synchronize(); @@ -50,14 +50,14 @@ void VideoSettings::synchronize() { config->video.saturation = saturation.slider.position(); config->video.gamma = 100 + gamma.slider.position(); config->video.luminance = luminance.slider.position(); - config->video.maskOverscanHorizontal = overscanHorizontal.slider.position(); - config->video.maskOverscanVertical = overscanVertical.slider.position(); + config->video.maskOverscan.horizontal = overscanHorizontal.slider.position(); + config->video.maskOverscan.vertical = overscanVertical.slider.position(); saturation.value.setText({config->video.saturation, "%"}); gamma.value.setText({config->video.gamma, "%"}); luminance.value.setText({config->video.luminance, "%"}); - overscanHorizontal.value.setText({config->video.maskOverscanHorizontal, "px"}); - overscanVertical.value.setText({config->video.maskOverscanVertical, "px"}); + overscanHorizontal.value.setText({config->video.maskOverscan.horizontal, "px"}); + overscanVertical.value.setText({config->video.maskOverscan.vertical, "px"}); if(program->active) system().paletteUpdate(); } diff --git a/higan/target-ethos/utility/utility.cpp b/higan/target-ethos/utility/utility.cpp index 0d39f836..1c71df02 100755 --- a/higan/target-ethos/utility/utility.cpp +++ b/higan/target-ethos/utility/utility.cpp @@ -197,12 +197,12 @@ void Utility::synchronizeRuby() { void Utility::updateShader() { if(config->video.shader == "None") { video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, (unsigned)Video::FilterPoint); + video.set(Video::Filter, Video::FilterNearest); return; } if(config->video.shader == "Blur") { video.set(Video::Shader, (const char*)""); - video.set(Video::Filter, (unsigned)Video::FilterLinear); + video.set(Video::Filter, Video::FilterLinear); return; } video.set(Video::Shader, (const char*)config->video.shader); diff --git a/higan/target-ethos/window/window.cpp b/higan/target-ethos/window/window.cpp index afe70a1a..318a35a9 100755 --- a/higan/target-ethos/window/window.cpp +++ b/higan/target-ethos/window/window.cpp @@ -9,11 +9,17 @@ void WindowManager::append(Window *window, const string &name) { } void WindowManager::loadGeometry() { - for(auto &window : windowList) { - config.append(window.geometry, window.name); + static bool initialized = false; + if(initialized == false) { + initialized = true; + Configuration::Node geometry; + for(auto &window : windowList) { + geometry.append(window.geometry, window.name); + } + config.append(geometry, "Geometry"); } - config.load(program->path("geometry.cfg")); - config.save(program->path("geometry.cfg")); + config.load(program->path("geometry.bml")); + config.save(program->path("geometry.bml")); for(auto &window : windowList) { window.window->setGeometry(window.geometry); } @@ -23,7 +29,7 @@ void WindowManager::saveGeometry() { for(auto &window : windowList) { window.geometry = window.window->geometry().text(); } - config.save(program->path("geometry.cfg")); + config.save(program->path("geometry.bml")); } void WindowManager::hideAll() { diff --git a/higan/target-ethos/window/window.hpp b/higan/target-ethos/window/window.hpp index 90659a48..13cbb9b9 100755 --- a/higan/target-ethos/window/window.hpp +++ b/higan/target-ethos/window/window.hpp @@ -12,7 +12,7 @@ struct WindowManager { void hideAll(); private: - configuration config; + Configuration::Document config; }; extern WindowManager *windowManager;