diff --git a/bsnes/nall/Makefile b/bsnes/nall/Makefile index 8c6c9405..a542beeb 100755 --- a/bsnes/nall/Makefile +++ b/bsnes/nall/Makefile @@ -19,6 +19,9 @@ ifeq ($(platform),) ifeq ($(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 diff --git a/bsnes/nall/string/base.hpp b/bsnes/nall/string/base.hpp index 64dd4a97..e93cc07c 100755 --- a/bsnes/nall/string/base.hpp +++ b/bsnes/nall/string/base.hpp @@ -36,6 +36,11 @@ namespace nall { inline unsigned length() 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; @@ -102,9 +107,7 @@ namespace nall { #endif }; - struct lstring : public linear_vector { - template inline lstring& operator<<(T value); - + struct lstring : vector { inline optional find(const char*) const; template inline lstring& split(const char*, const char*); template inline lstring& isplit(const char*, const char*); diff --git a/bsnes/nall/string/cast.hpp b/bsnes/nall/string/cast.hpp index 8996c10a..43ffdabd 100755 --- a/bsnes/nall/string/cast.hpp +++ b/bsnes/nall/string/cast.hpp @@ -16,11 +16,6 @@ template<> inline const char* to_string (const string &v) { retu template<> inline const char* to_string (cstring v) { return v; } template<> inline const char* to_string(const cstring &v) { return v; } -template lstring& lstring::operator<<(T value) { - operator[](size()).assign(to_string(value)); - return *this; -} - #if defined(QSTRING_H) template<> inline const char* to_string(QString v) { return v.toUtf8().constData(); } template<> inline const char* to_string(const QString &v) { return v.toUtf8().constData(); } diff --git a/bsnes/nall/string/core.hpp b/bsnes/nall/string/core.hpp index 26d8b776..95a778a6 100755 --- a/bsnes/nall/string/core.hpp +++ b/bsnes/nall/string/core.hpp @@ -151,9 +151,7 @@ inline lstring::lstring() { } inline lstring::lstring(std::initializer_list list) { - for(const string *s = list.begin(); s != list.end(); ++s) { - operator<<(*s); - } + for(auto &data : list) append(data); } } diff --git a/bsnes/nall/string/split.hpp b/bsnes/nall/string/split.hpp index 8bf97f2e..bb12a91b 100755 --- a/bsnes/nall/string/split.hpp +++ b/bsnes/nall/string/split.hpp @@ -7,14 +7,13 @@ template lstring& lstring::usplit if(!key || !*key) return *this; const char *p = base; - unsigned counter = 0; while(*p) { - if(Limit) if(counter >= Limit) break; + if(Limit) if(size() >= Limit) break; if(quoteskip(p)) continue; for(unsigned n = 0;; n++) { if(key[n] == 0) { - strlcpy(operator[](counter++), base, (unsigned)(p - base + 1)); + append(substr(base, 0, p - base)); p += n; base = p; break; @@ -23,7 +22,7 @@ template lstring& lstring::usplit } } - operator[](counter) = base; + append(base); return *this; } diff --git a/bsnes/nall/string/wrapper.hpp b/bsnes/nall/string/wrapper.hpp index 0aee887b..c02d5396 100755 --- a/bsnes/nall/string/wrapper.hpp +++ b/bsnes/nall/string/wrapper.hpp @@ -4,6 +4,11 @@ namespace nall { unsigned string::length() const { return strlen(data); } +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); } diff --git a/bsnes/nall/vector.hpp b/bsnes/nall/vector.hpp index 681d595f..7c605855 100755 --- a/bsnes/nall/vector.hpp +++ b/bsnes/nall/vector.hpp @@ -11,6 +11,116 @@ #include namespace nall { + template struct vector { + struct exception_out_of_bounds{}; + + protected: + T *pool; + unsigned poolsize; + unsigned objectsize; + + public: + unsigned size() const { return objectsize; } + unsigned capacity() const { return poolsize; } + + 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) { + size = bit::round(size); //amortize growth + T *copy = (T*)calloc(size, sizeof(T)); + for(unsigned n = 0; n < min(size, objectsize); n++) new(copy + n) T(pool[n]); + for(unsigned n = 0; n < objectsize; n++) pool[n].~T(); + free(pool); + pool = copy; + poolsize = size; + objectsize = min(size, objectsize); + } + + 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); + } + + void remove(unsigned index, unsigned count = 1) { + for(unsigned n = index; count + n < objectsize; n++) { + pool[n] = pool[count + n]; + } + objectsize = (count + index >= objectsize) ? index : objectsize - count; + } + + //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 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(); + } + }; + //linear_vector //memory: O(capacity * 2) // @@ -23,7 +133,7 @@ namespace nall { //if objects hold memory address references to themselves (introspection), a //valid copy constructor will be needed to keep pointers valid. - template class linear_vector { + template struct linear_vector { protected: T *pool; unsigned poolsize, objectsize; @@ -160,7 +270,7 @@ namespace nall { //by guaranteeing that the base memory address of each objects never changes, //this avoids the need for an object to have a valid copy constructor. - template class pointer_vector { + template struct pointer_vector { protected: T **pool; unsigned poolsize, objectsize; diff --git a/bsnes/phoenix/core/state.hpp b/bsnes/phoenix/core/state.hpp index 6fb24ed6..937da316 100755 --- a/bsnes/phoenix/core/state.hpp +++ b/bsnes/phoenix/core/state.hpp @@ -130,7 +130,7 @@ struct CheckBox::State { struct ComboBox::State { unsigned selection; - linear_vector text; + vector text; State() { selection = 0; @@ -191,7 +191,7 @@ struct ListView::State { bool headerVisible; bool selected; unsigned selection; - linear_vector text; + vector text; State() { checkable = false; diff --git a/bsnes/phoenix/gtk/font.cpp b/bsnes/phoenix/gtk/font.cpp index 1db7b756..cb6889d1 100755 --- a/bsnes/phoenix/gtk/font.cpp +++ b/bsnes/phoenix/gtk/font.cpp @@ -10,12 +10,15 @@ PangoFontDescription* pFont::create(const string &description) { part.split(",", description); for(auto &item : part) item.trim(" "); - string family = part[0]; - unsigned size = decimal(part[1]); - bool bold = part[2].position("Bold"); - bool italic = part[2].position("Italic"); - if(family == "") family = "Sans"; - if(size == 0) size = 8; + string family = "Sans"; + unsigned size = 8u; + bool bold = false; + bool italic = false; + + if(part[0] != "") family = part[0]; + if(part.size() >= 2) size = decimal(part[1]); + if(part.size() >= 3) bold = part[2].position("Bold"); + if(part.size() >= 3) italic = part[2].position("Italic"); PangoFontDescription *font = pango_font_description_new(); pango_font_description_set_family(font, family); diff --git a/bsnes/phoenix/qt/font.cpp b/bsnes/phoenix/qt/font.cpp index b1b51e18..bb3261cd 100755 --- a/bsnes/phoenix/qt/font.cpp +++ b/bsnes/phoenix/qt/font.cpp @@ -7,13 +7,18 @@ QFont pFont::create(const string &description) { part.split(",", description); for(auto &item : part) item.trim(" "); - string name = part[0] != "" ? part[0] : "Sans"; - unsigned size = part.size() >= 2 ? decimal(part[1]) : 8u; - bool bold = part[2].position("Bold"); - bool italic = part[2].position("Italic"); + string family = "Sans"; + unsigned size = 8u; + bool bold = false; + bool italic = false; + + if(part[0] != "") family = part[0]; + if(part.size() >= 2) size = decimal(part[1]); + if(part.size() >= 3) bold = part[2].position("Bold"); + if(part.size() >= 3) italic = part[2].position("Italic"); QFont qtFont; - qtFont.setFamily(name); + qtFont.setFamily(family); qtFont.setPointSize(size); if(bold) qtFont.setBold(true); if(italic) qtFont.setItalic(true); diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index cc4b8604..a021d38a 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Tue Sep 27 01:00:52 2011 +** Created: Tue Oct 11 18:59:15 2011 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! diff --git a/bsnes/phoenix/windows/font.cpp b/bsnes/phoenix/windows/font.cpp index 71e7a213..de42f24d 100755 --- a/bsnes/phoenix/windows/font.cpp +++ b/bsnes/phoenix/windows/font.cpp @@ -10,12 +10,15 @@ HFONT pFont::create(const string &description) { part.split(",", description); for(auto &item : part) item.trim(" "); - string family = part[0]; - unsigned size = decimal(part[1]); - bool bold = part[2].position("Bold"); - bool italic = part[2].position("Italic"); - if(family == "") family = "Tahoma"; - if(size == 0) size = 8; + string family = "Sans"; + unsigned size = 8u; + bool bold = false; + bool italic = false; + + if(part[0] != "") family = part[0]; + if(part.size() >= 2) size = decimal(part[1]); + if(part.size() >= 3) bold = part[2].position("Bold"); + if(part.size() >= 3) italic = part[2].position("Italic"); return CreateFont( -(size * 96.0 / 72.0 + 0.5), diff --git a/bsnes/ui/general/file-browser.cpp b/bsnes/ui/general/file-browser.cpp index 047a8c09..ba936da4 100755 --- a/bsnes/ui/general/file-browser.cpp +++ b/bsnes/ui/general/file-browser.cpp @@ -41,12 +41,12 @@ FileBrowser::FileBrowser() { fileList.onActivate = openButton.onTick = { &FileBrowser::fileListActivate, this }; - filterModes[Mode::Default ] = { "Default", "", { "*" } }; - filterModes[Mode::NES ] = { "NES", "", { "*.fc", "*.nes" } }; - filterModes[Mode::SNES ] = { "SNES", "", { "*.sfc" } }; - filterModes[Mode::GameBoy ] = { "GameBoy", "", { "*.gb", "*.gbc" } }; - filterModes[Mode::Satellaview] = { "Satellaview", "", { "*.bs" } }; - filterModes[Mode::SufamiTurbo] = { "SufamiTurbo", "", { "*.st" } }; + filterModes.append({ "Default", "", { "*" } }); + filterModes.append({ "NES", "", { "*.fc", "*.nes" } }); + filterModes.append({ "SNES", "", { "*.sfc" } }); + filterModes.append({ "GameBoy", "", { "*.gb", "*.gbc" } }); + filterModes.append({ "Satellaview", "", { "*.bs" } }); + filterModes.append({ "SufamiTurbo", "", { "*.st" } }); mode = &filterModes[Mode::Default]; for(auto &mode : filterModes) config.attach(mode.path, mode.name); diff --git a/bsnes/ui/general/file-browser.hpp b/bsnes/ui/general/file-browser.hpp index c261ce7e..c0b3067c 100755 --- a/bsnes/ui/general/file-browser.hpp +++ b/bsnes/ui/general/file-browser.hpp @@ -22,7 +22,7 @@ private: string path; lstring filter; } *mode; - linear_vector filterModes; + vector filterModes; lstring fileNameList; function callback; diff --git a/bsnes/ui/interface/nes.cpp b/bsnes/ui/interface/nes.cpp index 3fff497d..03229b75 100755 --- a/bsnes/ui/interface/nes.cpp +++ b/bsnes/ui/interface/nes.cpp @@ -114,26 +114,59 @@ int16_t InterfaceNES::inputPoll(bool port, unsigned device, unsigned id) { return 0; } -InterfaceNES::InterfaceNES() { - unsigned base_palette[] = { - 0x7c7c7c, 0x0000fc, 0x0000bc, 0x4428bc, - 0x940084, 0xa80020, 0xa81000, 0x881400, - 0x503000, 0x007800, 0x006800, 0x005800, - 0x004058, 0x000000, 0x000000, 0x000000, - 0xbcbcbc, 0x0078f8, 0x0058f8, 0x6844fc, - 0xd800cc, 0xe40058, 0xf83800, 0xe45c10, - 0xac7c00, 0x00b800, 0x00a800, 0x00a844, - 0x008888, 0x000000, 0x000000, 0x000000, - 0xf8f8f8, 0x3cbcfc, 0x6888fc, 0x9878f8, - 0xf878f8, 0xf85898, 0xf87858, 0xfca044, - 0xf8b800, 0xb8f818, 0x58d854, 0x58f898, - 0x00e8d8, 0x787878, 0x000000, 0x000000, - 0xfcfcfc, 0xa4e4fc, 0xb8b8b8, 0xd8d8f8, - 0xf8b8f8, 0xf8a4c0, 0xf0d0b0, 0xfce0a8, - 0xf8d878, 0xd8f878, 0xb8f8b8, 0xb8f8d8, - 0x00fcfc, 0xf8d8f8, 0x000000, 0x000000, +// + +//n = BGRCCCCCC (BGR=emphasis bits; C=color) +unsigned InterfaceNES::paletteColor( + unsigned n, double saturation, double hue, + double contrast, double brightness, double gamma +) { + signed color = (n & 0x0f), level = color < 0xe ? (n >> 4) & 3 : 1; + + static const double black = 0.518, white = 1.962, attenuation = 0.746; + static const double levels[8] = { + 0.350, 0.518, 0.962, 1.550, + 1.094, 1.506, 1.962, 1.962, }; - memcpy(palette, base_palette, sizeof base_palette); + + double lo_and_hi[2] = { + levels[level + 4 * (color == 0x0)], + levels[level + 4 * (color < 0xd)], + }; + + double y = 0.0, i = 0.0, q = 0.0; + auto wave = [](signed p, signed color) { return (color + p + 8) % 12 < 6; }; + for(signed p = 0; p < 12; p++) { + double spot = lo_and_hi[wave(p, color)]; + + if(((n & 0x040) && wave(p, 12)) + || ((n & 0x080) && wave(p, 4)) + || ((n & 0x100) && wave(p, 8)) + ) spot *= attenuation; + + double v = (spot - black) / (white - black); + + v = (v - 0.5) * contrast + 0.5; + v *= brightness / 12.0; + + y += v; + i += v * std::cos((3.141592653 / 6.0) * (p + hue)); + q += v * std::sin((3.141592653 / 6.0) * (p + hue)); + } + + i *= saturation; + q *= saturation; + + auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); }; + return (uclamp<8>(255.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q)) << 16) + + (uclamp<8>(255.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q)) << 8) + + (uclamp<8>(255.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q)) << 0); +} + +InterfaceNES::InterfaceNES() { + for(unsigned n = 0; n < 512; n++) { + palette[n] = paletteColor(n, 2.0); + } for(unsigned e = 1; e < 8; e++) { static const double rfactor[8] = { 1.000, 1.239, 0.794, 1.019, 0.905, 1.023, 0.741, 0.750 }; diff --git a/bsnes/ui/interface/nes.hpp b/bsnes/ui/interface/nes.hpp index 3d1f0b0e..5f28a624 100755 --- a/bsnes/ui/interface/nes.hpp +++ b/bsnes/ui/interface/nes.hpp @@ -15,4 +15,8 @@ struct InterfaceNES : NES::Interface { private: unsigned palette[512]; + unsigned paletteColor( + unsigned color, double saturation = 1.0, double hue = 0.0, + double contrast = 1.0, double brightness = 1.0, double gamma = 1.8 + ); }; diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 7c8dbf20..9a4fbf04 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) { inputManager = new InputManager; utility = new Utility; - title = "bsnes v083"; + title = "bsnes v083.01"; string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, "; normalFont = { fontFamily, "8" }; diff --git a/bsnes/ui/window/window.hpp b/bsnes/ui/window/window.hpp index ba643da3..e67ab928 100755 --- a/bsnes/ui/window/window.hpp +++ b/bsnes/ui/window/window.hpp @@ -4,7 +4,7 @@ struct WindowManager { string name; string geometry; }; - linear_vector windowList; + vector windowList; void append(Window *window, const string &name);