Update to v083r01 release.

byuu says:

This adds Bisqwit's NES palette generation code:

    http://nesdev.parodius.com/bbs/viewtopic.php?p=85060#85060

I set the saturation to 2.0 to closer match the existing "bright"
palette, although it still has a greater contrast range (some colors are
darker.) The gamma ramp option works now. Like SNES, best to also set
gamma to 0.8 afterward.  Once I think of a good way to expose the
saturation/hue settings, I'll do so.

I've also merged in the updated nall. Adds Cygwin uname check, and
replaces linear_vector with vector in lstring and the GUI.
This commit is contained in:
Tim Allen
2011-10-16 20:44:48 +11:00
parent 7fa8ad755d
commit 13ac6104e3
18 changed files with 226 additions and 65 deletions

View File

@@ -19,6 +19,9 @@ ifeq ($(platform),)
ifeq ($(uname),) ifeq ($(uname),)
platform := win platform := win
delete = del $(subst /,\,$1) delete = del $(subst /,\,$1)
else ifneq ($(findstring CYGWIN,$(uname)),)
platform := win
delete = del $(subst /,\,$1)
else ifneq ($(findstring Darwin,$(uname)),) else ifneq ($(findstring Darwin,$(uname)),)
platform := osx platform := osx
delete = rm -f $1 delete = rm -f $1

View File

@@ -36,6 +36,11 @@ namespace nall {
inline unsigned length() const; inline unsigned length() const;
template<unsigned Limit = 0> inline lstring split(const char*) const;
template<unsigned Limit = 0> inline lstring isplit(const char*) const;
template<unsigned Limit = 0> inline lstring qsplit(const char*) const;
template<unsigned Limit = 0> inline lstring iqsplit(const char*) const;
inline bool equals(const char*) const; inline bool equals(const char*) const;
inline bool iequals(const char*) const; inline bool iequals(const char*) const;
@@ -102,9 +107,7 @@ namespace nall {
#endif #endif
}; };
struct lstring : public linear_vector<string> { struct lstring : vector<string> {
template<typename T> inline lstring& operator<<(T value);
inline optional<unsigned> find(const char*) const; inline optional<unsigned> find(const char*) const;
template<unsigned Limit = 0> inline lstring& split(const char*, const char*); template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
template<unsigned Limit = 0> inline lstring& isplit(const char*, const char*); template<unsigned Limit = 0> inline lstring& isplit(const char*, const char*);

View File

@@ -16,11 +16,6 @@ template<> inline const char* to_string<const string&> (const string &v) { retu
template<> inline const char* to_string<cstring> (cstring v) { return v; } template<> inline const char* to_string<cstring> (cstring v) { return v; }
template<> inline const char* to_string<const cstring&>(const cstring &v) { return v; } template<> inline const char* to_string<const cstring&>(const cstring &v) { return v; }
template<typename T> lstring& lstring::operator<<(T value) {
operator[](size()).assign(to_string<T>(value));
return *this;
}
#if defined(QSTRING_H) #if defined(QSTRING_H)
template<> inline const char* to_string<QString>(QString v) { return v.toUtf8().constData(); } template<> inline const char* to_string<QString>(QString v) { return v.toUtf8().constData(); }
template<> inline const char* to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); } template<> inline const char* to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }

View File

@@ -151,9 +151,7 @@ inline lstring::lstring() {
} }
inline lstring::lstring(std::initializer_list<string> list) { inline lstring::lstring(std::initializer_list<string> list) {
for(const string *s = list.begin(); s != list.end(); ++s) { for(auto &data : list) append(data);
operator<<(*s);
}
} }
} }

View File

@@ -7,14 +7,13 @@ template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit
if(!key || !*key) return *this; if(!key || !*key) return *this;
const char *p = base; const char *p = base;
unsigned counter = 0;
while(*p) { while(*p) {
if(Limit) if(counter >= Limit) break; if(Limit) if(size() >= Limit) break;
if(quoteskip<Quoted>(p)) continue; if(quoteskip<Quoted>(p)) continue;
for(unsigned n = 0;; n++) { for(unsigned n = 0;; n++) {
if(key[n] == 0) { if(key[n] == 0) {
strlcpy(operator[](counter++), base, (unsigned)(p - base + 1)); append(substr(base, 0, p - base));
p += n; p += n;
base = p; base = p;
break; break;
@@ -23,7 +22,7 @@ template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit
} }
} }
operator[](counter) = base; append(base);
return *this; return *this;
} }

View File

@@ -4,6 +4,11 @@ namespace nall {
unsigned string::length() const { return strlen(data); } unsigned string::length() const { return strlen(data); }
template<unsigned limit> lstring string::split(const char *key) const { lstring result; result.split<limit>(key, data); return result; }
template<unsigned limit> lstring string::isplit(const char *key) const { lstring result; result.isplit<limit>(key, data); return result; }
template<unsigned limit> lstring string::qsplit(const char *key) const { lstring result; result.qsplit<limit>(key, data); return result; }
template<unsigned limit> lstring string::iqsplit(const char *key) const { lstring result; result.iqsplit<limit>(key, data); return result; }
bool string::equals(const char *str) const { return !strcmp(data, str); } bool string::equals(const char *str) const { return !strcmp(data, str); }
bool string::iequals(const char *str) const { return !istrcmp(data, str); } bool string::iequals(const char *str) const { return !istrcmp(data, str); }

View File

@@ -11,6 +11,116 @@
#include <nall/utility.hpp> #include <nall/utility.hpp>
namespace nall { namespace nall {
template<typename T> 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<typename... Args>
void append(const T& data, Args&&... args) {
append(data);
append(std::forward<Args>(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<T> list) : pool(nullptr), poolsize(0), objectsize(0) {
for(auto &data : list) append(data);
}
~vector() {
reset();
}
};
//linear_vector //linear_vector
//memory: O(capacity * 2) //memory: O(capacity * 2)
// //
@@ -23,7 +133,7 @@ namespace nall {
//if objects hold memory address references to themselves (introspection), a //if objects hold memory address references to themselves (introspection), a
//valid copy constructor will be needed to keep pointers valid. //valid copy constructor will be needed to keep pointers valid.
template<typename T> class linear_vector { template<typename T> struct linear_vector {
protected: protected:
T *pool; T *pool;
unsigned poolsize, objectsize; unsigned poolsize, objectsize;
@@ -160,7 +270,7 @@ namespace nall {
//by guaranteeing that the base memory address of each objects never changes, //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. //this avoids the need for an object to have a valid copy constructor.
template<typename T> class pointer_vector { template<typename T> struct pointer_vector {
protected: protected:
T **pool; T **pool;
unsigned poolsize, objectsize; unsigned poolsize, objectsize;

View File

@@ -130,7 +130,7 @@ struct CheckBox::State {
struct ComboBox::State { struct ComboBox::State {
unsigned selection; unsigned selection;
linear_vector<string> text; vector<string> text;
State() { State() {
selection = 0; selection = 0;
@@ -191,7 +191,7 @@ struct ListView::State {
bool headerVisible; bool headerVisible;
bool selected; bool selected;
unsigned selection; unsigned selection;
linear_vector<lstring> text; vector<lstring> text;
State() { State() {
checkable = false; checkable = false;

View File

@@ -10,12 +10,15 @@ PangoFontDescription* pFont::create(const string &description) {
part.split(",", description); part.split(",", description);
for(auto &item : part) item.trim(" "); for(auto &item : part) item.trim(" ");
string family = part[0]; string family = "Sans";
unsigned size = decimal(part[1]); unsigned size = 8u;
bool bold = part[2].position("Bold"); bool bold = false;
bool italic = part[2].position("Italic"); bool italic = false;
if(family == "") family = "Sans";
if(size == 0) size = 8; 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(); PangoFontDescription *font = pango_font_description_new();
pango_font_description_set_family(font, family); pango_font_description_set_family(font, family);

View File

@@ -7,13 +7,18 @@ QFont pFont::create(const string &description) {
part.split(",", description); part.split(",", description);
for(auto &item : part) item.trim(" "); for(auto &item : part) item.trim(" ");
string name = part[0] != "" ? part[0] : "Sans"; string family = "Sans";
unsigned size = part.size() >= 2 ? decimal(part[1]) : 8u; unsigned size = 8u;
bool bold = part[2].position("Bold"); bool bold = false;
bool italic = part[2].position("Italic"); 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; QFont qtFont;
qtFont.setFamily(name); qtFont.setFamily(family);
qtFont.setPointSize(size); qtFont.setPointSize(size);
if(bold) qtFont.setBold(true); if(bold) qtFont.setBold(true);
if(italic) qtFont.setItalic(true); if(italic) qtFont.setItalic(true);

View File

@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
** Meta object code from reading C++ file 'platform.moc.hpp' ** 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) ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
** **
** WARNING! All changes made in this file will be lost! ** WARNING! All changes made in this file will be lost!

View File

@@ -10,12 +10,15 @@ HFONT pFont::create(const string &description) {
part.split(",", description); part.split(",", description);
for(auto &item : part) item.trim(" "); for(auto &item : part) item.trim(" ");
string family = part[0]; string family = "Sans";
unsigned size = decimal(part[1]); unsigned size = 8u;
bool bold = part[2].position("Bold"); bool bold = false;
bool italic = part[2].position("Italic"); bool italic = false;
if(family == "") family = "Tahoma";
if(size == 0) size = 8; 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( return CreateFont(
-(size * 96.0 / 72.0 + 0.5), -(size * 96.0 / 72.0 + 0.5),

View File

@@ -41,12 +41,12 @@ FileBrowser::FileBrowser() {
fileList.onActivate = openButton.onTick = { &FileBrowser::fileListActivate, this }; fileList.onActivate = openButton.onTick = { &FileBrowser::fileListActivate, this };
filterModes[Mode::Default ] = { "Default", "", { "*" } }; filterModes.append({ "Default", "", { "*" } });
filterModes[Mode::NES ] = { "NES", "", { "*.fc", "*.nes" } }; filterModes.append({ "NES", "", { "*.fc", "*.nes" } });
filterModes[Mode::SNES ] = { "SNES", "", { "*.sfc" } }; filterModes.append({ "SNES", "", { "*.sfc" } });
filterModes[Mode::GameBoy ] = { "GameBoy", "", { "*.gb", "*.gbc" } }; filterModes.append({ "GameBoy", "", { "*.gb", "*.gbc" } });
filterModes[Mode::Satellaview] = { "Satellaview", "", { "*.bs" } }; filterModes.append({ "Satellaview", "", { "*.bs" } });
filterModes[Mode::SufamiTurbo] = { "SufamiTurbo", "", { "*.st" } }; filterModes.append({ "SufamiTurbo", "", { "*.st" } });
mode = &filterModes[Mode::Default]; mode = &filterModes[Mode::Default];
for(auto &mode : filterModes) config.attach(mode.path, mode.name); for(auto &mode : filterModes) config.attach(mode.path, mode.name);

View File

@@ -22,7 +22,7 @@ private:
string path; string path;
lstring filter; lstring filter;
} *mode; } *mode;
linear_vector<FilterMode> filterModes; vector<FilterMode> filterModes;
lstring fileNameList; lstring fileNameList;
function<void (string)> callback; function<void (string)> callback;

View File

@@ -114,26 +114,59 @@ int16_t InterfaceNES::inputPoll(bool port, unsigned device, unsigned id) {
return 0; return 0;
} }
InterfaceNES::InterfaceNES() { //
unsigned base_palette[] = {
0x7c7c7c, 0x0000fc, 0x0000bc, 0x4428bc, //n = BGRCCCCCC (BGR=emphasis bits; C=color)
0x940084, 0xa80020, 0xa81000, 0x881400, unsigned InterfaceNES::paletteColor(
0x503000, 0x007800, 0x006800, 0x005800, unsigned n, double saturation, double hue,
0x004058, 0x000000, 0x000000, 0x000000, double contrast, double brightness, double gamma
0xbcbcbc, 0x0078f8, 0x0058f8, 0x6844fc, ) {
0xd800cc, 0xe40058, 0xf83800, 0xe45c10, signed color = (n & 0x0f), level = color < 0xe ? (n >> 4) & 3 : 1;
0xac7c00, 0x00b800, 0x00a800, 0x00a844,
0x008888, 0x000000, 0x000000, 0x000000, static const double black = 0.518, white = 1.962, attenuation = 0.746;
0xf8f8f8, 0x3cbcfc, 0x6888fc, 0x9878f8, static const double levels[8] = {
0xf878f8, 0xf85898, 0xf87858, 0xfca044, 0.350, 0.518, 0.962, 1.550,
0xf8b800, 0xb8f818, 0x58d854, 0x58f898, 1.094, 1.506, 1.962, 1.962,
0x00e8d8, 0x787878, 0x000000, 0x000000,
0xfcfcfc, 0xa4e4fc, 0xb8b8b8, 0xd8d8f8,
0xf8b8f8, 0xf8a4c0, 0xf0d0b0, 0xfce0a8,
0xf8d878, 0xd8f878, 0xb8f8b8, 0xb8f8d8,
0x00fcfc, 0xf8d8f8, 0x000000, 0x000000,
}; };
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++) { 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 }; static const double rfactor[8] = { 1.000, 1.239, 0.794, 1.019, 0.905, 1.023, 0.741, 0.750 };

View File

@@ -15,4 +15,8 @@ struct InterfaceNES : NES::Interface {
private: private:
unsigned palette[512]; 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
);
}; };

View File

@@ -49,7 +49,7 @@ Application::Application(int argc, char **argv) {
inputManager = new InputManager; inputManager = new InputManager;
utility = new Utility; utility = new Utility;
title = "bsnes v083"; title = "bsnes v083.01";
string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, "; string fontFamily = Intrinsics::platform() == Intrinsics::Platform::Windows ? "Tahoma, " : "Sans, ";
normalFont = { fontFamily, "8" }; normalFont = { fontFamily, "8" };

View File

@@ -4,7 +4,7 @@ struct WindowManager {
string name; string name;
string geometry; string geometry;
}; };
linear_vector<WindowList> windowList; vector<WindowList> windowList;
void append(Window *window, const string &name); void append(Window *window, const string &name);