mirror of https://github.com/bsnes-emu/bsnes.git
Update to v093r01 release.
byuu says: Changelog: - added SA-1 MDR; fixes bug in SD Gundam G-Next where the main battleship was unable to fire - added out-of-the-box support for any BSD running Clang 3.3+ (FreeBSD 10+, notably) - added new video shader, "Display Emulation", which changes the shader based on the emulated system - fixed the home button to go to your default library path - phoenix: Windows port won't send onActivate unless an item is selected (prevents crashing on pressing enter in file dialog) - ruby: removed vec4 position from out Vertex {} (helps AMD cards) - shaders: updated all shaders to use texture() instead of texture2D() (helps AMD cards) The "Display Emulation" option works like this: when selected, it tries to load "<path>/Video Shaders/Emulation/<systemName>.shader/"; otherwise it falls back to the blur shader. <path> is the usual (next to binary, then in <config>/higan, then in /usr/share/higan, etc); and <systemName> is "Famicom", "Super Famicom", "Game Boy", "Game Boy Color", "Game Boy Advance" To support BSD, I had to modify the $(platform) variable to differentiate between Linux and BSD. As such, the new $(platform) values are: win -> windows osx -> macosx x -> linux or bsd I am also checking uname -s instead of uname -a now. No reason to potentially match the hostname to the wrong OS type.
This commit is contained in:
parent
4e2eb23835
commit
66f136718e
17
Makefile
17
Makefile
|
@ -29,13 +29,8 @@ else ifeq ($(pgo),optimize)
|
|||
endif
|
||||
|
||||
# platform
|
||||
ifeq ($(platform),x)
|
||||
flags += -march=native
|
||||
link += -s -Wl,-export-dynamic -ldl -lX11 -lXext
|
||||
else ifeq ($(platform),osx)
|
||||
flags += -march=native
|
||||
else ifeq ($(platform),win)
|
||||
ifeq ($(arch),win32)
|
||||
ifeq ($(platform),windows)
|
||||
ifeq ($(arch),x86)
|
||||
flags += -m32
|
||||
link += -m32
|
||||
endif
|
||||
|
@ -46,6 +41,14 @@ else ifeq ($(platform),win)
|
|||
endif
|
||||
link += -s -mthreads -luuid -lkernel32 -luser32 -lgdi32 -lcomctl32 -lcomdlg32 -lshell32 -lole32 -lws2_32
|
||||
link += -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
|
||||
else ifeq ($(platform),macosx)
|
||||
flags += -march=native
|
||||
else ifeq ($(platform),linux)
|
||||
flags += -march=native
|
||||
link += -s -Wl,-export-dynamic -lX11 -lXext -ldl
|
||||
else ifeq ($(platform),bsd)
|
||||
flags += -march=native
|
||||
link += -s -Wl,-export-dynamic -lX11 -lXext
|
||||
else
|
||||
$(error unsupported platform.)
|
||||
endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
namespace Emulator {
|
||||
static const char Name[] = "higan";
|
||||
static const char Version[] = "093";
|
||||
static const char Version[] = "093.01";
|
||||
static const char Author[] = "byuu";
|
||||
static const char License[] = "GPLv3";
|
||||
static const char Website[] = "http://byuu.org/";
|
||||
|
|
|
@ -15,34 +15,40 @@
|
|||
#####
|
||||
|
||||
ifeq ($(platform),)
|
||||
uname := $(shell uname -a)
|
||||
uname := $(shell uname -s)
|
||||
ifeq ($(uname),)
|
||||
platform := win
|
||||
platform := windows
|
||||
delete = del $(subst /,\,$1)
|
||||
else ifneq ($(findstring Windows,$(uname)),)
|
||||
platform := win
|
||||
platform := windows
|
||||
delete = del $(subst /,\,$1)
|
||||
else ifneq ($(findstring CYGWIN,$(uname)),)
|
||||
platform := win
|
||||
platform := windows
|
||||
delete = del $(subst /,\,$1)
|
||||
else ifneq ($(findstring Darwin,$(uname)),)
|
||||
platform := osx
|
||||
platform := macosx
|
||||
delete = rm -f $1
|
||||
else ifneq ($(findstring BSD,$(uname)),)
|
||||
platform := bsd
|
||||
delete = rm -f $1
|
||||
else
|
||||
platform := x
|
||||
platform := linux
|
||||
delete = rm -f $1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(compiler),)
|
||||
ifeq ($(platform),win)
|
||||
ifeq ($(platform),windows)
|
||||
compiler := g++
|
||||
flags :=
|
||||
link :=
|
||||
else ifeq ($(platform),osx)
|
||||
else ifeq ($(platform),macosx)
|
||||
compiler := clang
|
||||
flags := -w -stdlib=libc++
|
||||
link := -lc++ -lobjc
|
||||
else ifeq ($(platform),bsd)
|
||||
compiler := clang++
|
||||
flags := -w
|
||||
else
|
||||
compiler := g++-4.7
|
||||
flags :=
|
||||
|
|
|
@ -227,8 +227,8 @@ struct file {
|
|||
|
||||
static bool exists(const string& filename) {
|
||||
#if !defined(_WIN32)
|
||||
struct stat64 data;
|
||||
if(stat64(filename, &data) != 0) return false;
|
||||
struct stat data;
|
||||
if(stat(filename, &data) != 0) return false;
|
||||
#else
|
||||
struct __stat64 data;
|
||||
if(_wstat64(utf16_t(filename), &data) != 0) return false;
|
||||
|
@ -239,8 +239,8 @@ struct file {
|
|||
|
||||
static uintmax_t size(const string& filename) {
|
||||
#if !defined(_WIN32)
|
||||
struct stat64 data;
|
||||
stat64(filename, &data);
|
||||
struct stat data;
|
||||
stat(filename, &data);
|
||||
#else
|
||||
struct __stat64 data;
|
||||
_wstat64(utf16_t(filename), &data);
|
||||
|
@ -250,8 +250,8 @@ struct file {
|
|||
|
||||
static time_t timestamp(const string& filename, file::time mode = file::time::create) {
|
||||
#if !defined(_WIN32)
|
||||
struct stat64 data;
|
||||
stat64(filename, &data);
|
||||
struct stat data;
|
||||
stat(filename, &data);
|
||||
#else
|
||||
struct __stat64 data;
|
||||
_wstat64(utf16_t(filename), &data);
|
||||
|
|
|
@ -32,7 +32,7 @@ struct Intrinsics {
|
|||
|
||||
/* Platform detection */
|
||||
|
||||
#if defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#if defined(linux) || 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__)
|
||||
|
|
|
@ -153,7 +153,8 @@ public:
|
|||
//list.hpp
|
||||
struct lstring : vector<string> {
|
||||
inline optional<unsigned> find(rstring) const;
|
||||
inline string concatenate(const string&) const;
|
||||
inline string merge(const string&) const;
|
||||
inline string concatenate(const string&) const; //deprecated
|
||||
inline lstring& isort();
|
||||
inline lstring& strip();
|
||||
inline void append() {}
|
||||
|
|
|
@ -38,7 +38,14 @@ inline string evaluateExpression(Node* node) {
|
|||
}
|
||||
|
||||
inline int64_t evaluateInteger(Node* node) {
|
||||
if(node->type == Node::Type::Literal) return nall::integer(node->literal);
|
||||
if(node->type == Node::Type::Literal) {
|
||||
if(node->literal.beginswith("0b")) return nall::binary(node->literal);
|
||||
if(node->literal.beginswith("0o")) return nall::octal(node->literal);
|
||||
if(node->literal.beginswith("0x")) return nall::hex(node->literal);
|
||||
if(node->literal.beginswith("%")) return nall::binary(node->literal);
|
||||
if(node->literal.beginswith("$")) return nall::hex(node->literal);
|
||||
return nall::integer(node->literal);
|
||||
}
|
||||
|
||||
#define p(n) evaluateInteger(node->link[n])
|
||||
switch(node->type) {
|
||||
|
|
|
@ -8,17 +8,19 @@ inline bool isLiteral(const char*& s) {
|
|||
return (n >= 'A' && n <= 'Z')
|
||||
|| (n >= 'a' && n <= 'z')
|
||||
|| (n >= '0' && n <= '9')
|
||||
|| n == '_' || n == '\"';
|
||||
|| (n == '%' || n == '$' || n == '_' || n == '.')
|
||||
|| (n == '\'' || n == '\"');
|
||||
}
|
||||
|
||||
inline string literalNumber(const char*& s) {
|
||||
const char* p = s;
|
||||
|
||||
//binary
|
||||
if(p[0] == '0' && p[1] == 'b') {
|
||||
p += 2;
|
||||
if(p[0] == '%' || (p[0] == '0' && p[1] == 'b')) {
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while(p[0] == '0' || p[0] == '1') p++;
|
||||
if(p - s < 3) throw "invalid binary literal";
|
||||
if(p - s <= prefix) throw "invalid binary literal";
|
||||
string result = substr(s, 0, p - s);
|
||||
s = p;
|
||||
return result;
|
||||
|
@ -26,19 +28,21 @@ inline string literalNumber(const char*& s) {
|
|||
|
||||
//octal
|
||||
if(p[0] == '0' && p[1] == 'o') {
|
||||
p += 2;
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while(p[0] >= '0' && p[0] <= '7') p++;
|
||||
if(p - s < 3) throw "invalid octal literal";
|
||||
if(p - s <= prefix) throw "invalid octal literal";
|
||||
string result = substr(s, 0, p - s);
|
||||
s = p;
|
||||
return result;
|
||||
}
|
||||
|
||||
//hex
|
||||
if(p[0] == '0' && p[1] == 'x') {
|
||||
p += 2;
|
||||
if(p[0] == '$' || (p[0] == '0' && p[1] == 'x')) {
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F') || (p[0] >= 'a' && p[0] <= 'f')) p++;
|
||||
if(p - s < 3) throw "invalid hex literal";
|
||||
if(p - s <= prefix) throw "invalid hex literal";
|
||||
string result = substr(s, 0, p - s);
|
||||
s = p;
|
||||
return result;
|
||||
|
@ -61,10 +65,11 @@ inline string literalNumber(const char*& s) {
|
|||
}
|
||||
|
||||
inline string literalString(const char*& s) {
|
||||
const char* p = s + 1;
|
||||
const char* p = s;
|
||||
char escape = *p++;
|
||||
|
||||
while(p[0] && p[0] != '\"') p++;
|
||||
if(*p++ != '\"') throw "unclosed string literal";
|
||||
while(p[0] && p[0] != escape) p++;
|
||||
if(*p++ != escape) throw "unclosed string literal";
|
||||
|
||||
string result = substr(s, 0, p - s);
|
||||
s = p;
|
||||
|
@ -74,7 +79,7 @@ inline string literalString(const char*& s) {
|
|||
inline string literalVariable(const char*& s) {
|
||||
const char* p = s;
|
||||
|
||||
while(p[0] == '_' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || (p[0] >= '0' && p[0] <= '9')) p++;
|
||||
while(p[0] == '_' || p[0] == '.' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || (p[0] >= '0' && p[0] <= '9')) p++;
|
||||
|
||||
string result = substr(s, 0, p - s);
|
||||
s = p;
|
||||
|
@ -85,8 +90,9 @@ inline string literal(const char*& s) {
|
|||
const char* p = s;
|
||||
|
||||
if(p[0] >= '0' && p[0] <= '9') return literalNumber(s);
|
||||
if(p[0] == '\"') return literalString(s);
|
||||
if(p[0] == '_' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) return literalVariable(s);
|
||||
if(p[0] == '%' || p[0] == '$') return literalNumber(s);
|
||||
if(p[0] == '\'' || p[0] == '\"') return literalString(s);
|
||||
if(p[0] == '_' || p[0] == '.' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) return literalVariable(s);
|
||||
|
||||
throw "invalid literal";
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ optional<unsigned> lstring::find(rstring key) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
string lstring::concatenate(const string& separator) const {
|
||||
string lstring::merge(const string& separator) const {
|
||||
string output;
|
||||
for(unsigned i = 0; i < size(); i++) {
|
||||
output.append(operator[](i));
|
||||
|
@ -18,6 +18,11 @@ string lstring::concatenate(const string& separator) const {
|
|||
return output;
|
||||
}
|
||||
|
||||
//deprecated: alias to merge()
|
||||
string lstring::concatenate(const string& separator) const {
|
||||
return merge(separator);
|
||||
}
|
||||
|
||||
lstring& lstring::isort() {
|
||||
nall::sort(pool, objectsize, [](const string& x, const string& y) {
|
||||
return istrcmp(x, y) < 0;
|
||||
|
|
|
@ -22,7 +22,7 @@ protected:
|
|||
unsigned objectsize = 0;
|
||||
|
||||
public:
|
||||
explicit operator bool() const { return pool; }
|
||||
explicit operator bool() const { return objectsize; }
|
||||
T* data() { return pool + poolbase; }
|
||||
const T* data() const { return pool + poolbase; }
|
||||
|
||||
|
@ -136,6 +136,9 @@ public:
|
|||
objectsize -= length;
|
||||
}
|
||||
|
||||
void removefirst() { return remove(0); }
|
||||
void removelast() { return remove(~0u); }
|
||||
|
||||
T take(unsigned position = ~0u) {
|
||||
if(position == ~0u) position = objectsize - 1;
|
||||
T object = pool[poolbase + position];
|
||||
|
@ -143,6 +146,9 @@ public:
|
|||
return object;
|
||||
}
|
||||
|
||||
T takefirst() { return take(0); }
|
||||
T takelast() { return take(~0u); }
|
||||
|
||||
void reverse() {
|
||||
unsigned pivot = size() / 2;
|
||||
for(unsigned l = 0, r = size() - 1; l < pivot; l++, r--) {
|
||||
|
|
|
@ -1,4 +1,13 @@
|
|||
ifeq ($(platform),x)
|
||||
ifeq ($(platform),)
|
||||
phoenixflags = $(cppflags) $(flags) -DPHOENIX_REFERENCE
|
||||
phoenixlink =
|
||||
else ifeq ($(platform),windows)
|
||||
phoenixflags = $(cppflags) $(flags) -DPHOENIX_WINDOWS
|
||||
phoenixlink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||
else ifeq ($(platform),macosx)
|
||||
phoenixflags = $(objcppflags) $(flags) -DPHOENIX_COCOA
|
||||
phoenixlink = -framework Cocoa -framework Carbon
|
||||
else
|
||||
ifeq ($(phoenix),)
|
||||
phoenix := gtk
|
||||
endif
|
||||
|
@ -12,13 +21,4 @@ ifeq ($(platform),x)
|
|||
phoenixflags = $(cppflags) $(flags) -DPHOENIX_QT `pkg-config --cflags QtCore QtGui`
|
||||
phoenixlink = `pkg-config --libs QtCore QtGui`
|
||||
endif
|
||||
else ifeq ($(platform),osx)
|
||||
phoenixflags = $(objcppflags) $(flags) -DPHOENIX_COCOA
|
||||
phoenixlink = -framework Cocoa -framework Carbon
|
||||
else ifeq ($(platform),win)
|
||||
phoenixflags = $(cppflags) $(flags) -DPHOENIX_WINDOWS
|
||||
phoenixlink = -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32 -lshlwapi
|
||||
else
|
||||
phoenixflags = $(cppflags) $(flags) -DPHOENIX_REFERENCE
|
||||
phoenixlink =
|
||||
endif
|
||||
|
|
|
@ -134,7 +134,9 @@ static bool Application_keyboardProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM
|
|||
if(dynamic_cast<ListView*>(object)) {
|
||||
ListView& listView = (ListView&)*object;
|
||||
if(wparam == VK_RETURN) {
|
||||
if(listView.onActivate) listView.onActivate();
|
||||
if(listView.state.text.size() && listView.selected()) {
|
||||
if(listView.onActivate) listView.onActivate();
|
||||
}
|
||||
}
|
||||
} else if(dynamic_cast<LineEdit*>(object)) {
|
||||
LineEdit& lineEdit = (LineEdit&)*object;
|
||||
|
@ -369,7 +371,9 @@ static LRESULT CALLBACK Application_windowProc(HWND hwnd, UINT msg, WPARAM wpara
|
|||
if(listView.p.locked == false && listView.onChange) listView.onChange();
|
||||
}
|
||||
} else if(nmhdr->code == LVN_ITEMACTIVATE) {
|
||||
if(listView.onActivate) listView.onActivate();
|
||||
if(listView.state.text.size() && listView.selected()) {
|
||||
if(listView.onActivate) listView.onActivate();
|
||||
}
|
||||
} else if(nmhdr->code == NM_CUSTOMDRAW) {
|
||||
LPNMLVCUSTOMDRAW lvcd = (LPNMLVCUSTOMDRAW)nmhdr;
|
||||
switch(lvcd->nmcd.dwDrawStage) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
ifeq ($(platform),osx)
|
||||
ifeq ($(platform),macosx)
|
||||
rubyflags = $(objcppflags) $(flags)
|
||||
else
|
||||
rubyflags = $(cppflags) $(flags)
|
||||
|
@ -28,10 +28,10 @@ rubylink += $(if $(findstring input.rawinput,$(ruby)),-ldinput8 -ldxguid)
|
|||
|
||||
rubylink += $(if $(findstring .sdl,$(ruby)),`sdl-config --libs`)
|
||||
|
||||
ifeq ($(platform),x)
|
||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
||||
else ifeq ($(platform),osx)
|
||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
||||
else ifeq ($(platform),win)
|
||||
ifeq ($(platform),windows)
|
||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal32)
|
||||
else ifeq ($(platform),macosx)
|
||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-framework OpenAL)
|
||||
else
|
||||
rubylink += $(if $(findstring audio.openal,$(ruby)),-lopenal)
|
||||
endif
|
||||
|
|
|
@ -84,15 +84,12 @@ public:
|
|||
DWORD pos, size;
|
||||
void* output;
|
||||
|
||||
if(settings.synchronize == true) {
|
||||
if(settings.synchronize) {
|
||||
//wait until playback buffer has an empty ring to write new audio data to
|
||||
while(device.distance >= device.rings - 1) {
|
||||
dsb_b->GetCurrentPosition(&pos, 0);
|
||||
unsigned activering = pos / (device.latency * 4);
|
||||
if(activering == device.readring) {
|
||||
if(settings.synchronize == false) Sleep(1);
|
||||
continue;
|
||||
}
|
||||
if(activering == device.readring) continue;
|
||||
|
||||
//subtract number of played rings from ring distance counter
|
||||
device.distance -= (device.rings + activering - device.readring) % device.rings;
|
||||
|
|
|
@ -2,6 +2,9 @@ void OpenGL::shader(const char* pathname) {
|
|||
for(auto& program : programs) program.release();
|
||||
programs.reset();
|
||||
|
||||
for(auto& frame : frames) glDeleteTextures(1, &frame.texture);
|
||||
frames.reset();
|
||||
|
||||
format = GL_RGBA8;
|
||||
filter = GL_LINEAR;
|
||||
wrap = GL_CLAMP_TO_BORDER;
|
||||
|
@ -15,10 +18,24 @@ void OpenGL::shader(const char* pathname) {
|
|||
programs(n).bind(this, node, pathname);
|
||||
}
|
||||
|
||||
bind(this, document["output"], pathname);
|
||||
bind(document, pathname);
|
||||
OpenGLProgram::bind(this, document["output"], pathname);
|
||||
} else {
|
||||
//no shader; assign default values
|
||||
history.length = 0;
|
||||
history.format = GL_RGBA8;
|
||||
history.filter = GL_LINEAR;
|
||||
history.wrap = GL_CLAMP_TO_BORDER;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL::bind(const Markup::Node& node, const string& pathname) {
|
||||
history.length = node["history/frames"].decimal();
|
||||
if(node["history/format"].exists()) history.format = glrFormat(node["history/format"].text());
|
||||
if(node["history/filter"].exists()) history.filter = glrFilter(node["history/filter"].text());
|
||||
if(node["history/wrap"].exists()) history.wrap = glrWrap(node["history/wrap"].text());
|
||||
}
|
||||
|
||||
bool OpenGL::lock(uint32_t*& data, unsigned& pitch) {
|
||||
pitch = width * sizeof(uint32_t);
|
||||
return data = buffer;
|
||||
|
@ -40,19 +57,30 @@ void OpenGL::clear() {
|
|||
void OpenGL::refresh() {
|
||||
clear();
|
||||
|
||||
//frame[] must always contain max# of previous frames: allocate them now, so first few frames can use them
|
||||
while(frames.size() < history.length) {
|
||||
OpenGLTexture frame;
|
||||
glGenTextures(1, &frame.texture);
|
||||
glBindTexture(GL_TEXTURE_2D, frame.texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, frame.format = history.format, frame.width = width, frame.height = height, 0, GL_BGRA, inputFormat, buffer);
|
||||
frame.filter = history.filter;
|
||||
frame.wrap = history.wrap;
|
||||
frames.append(frame);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, inputFormat, buffer);
|
||||
|
||||
struct History {
|
||||
struct Source {
|
||||
GLuint texture;
|
||||
unsigned width, height;
|
||||
GLuint filter, wrap;
|
||||
};
|
||||
vector<History> history;
|
||||
vector<Source> sources;
|
||||
|
||||
unsigned sourceWidth = width, sourceHeight = height;
|
||||
history.prepend({texture, sourceWidth, sourceHeight, filter, wrap});
|
||||
sources.prepend({texture, sourceWidth, sourceHeight, filter, wrap});
|
||||
|
||||
for(auto& p : programs) {
|
||||
unsigned targetWidth = p.absoluteWidth ? p.absoluteWidth : outputWidth;
|
||||
|
@ -65,29 +93,35 @@ void OpenGL::refresh() {
|
|||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, p.framebuffer);
|
||||
|
||||
glrUniform1i("phase", p.phase);
|
||||
glrUniform1i("sourceLength", history.size());
|
||||
glrUniform1i("frameLength", frames.size());
|
||||
glrUniform1i("sourceLength", sources.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& pixmap : history) {
|
||||
glrUniform1i({"source[", aid, "]"}, aid);
|
||||
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));
|
||||
for(auto& frame : frames) {
|
||||
glrUniform1i({"frame[", aid, "]"}, aid);
|
||||
glrUniform4f({"frameSize[", aid, "]"}, frame.width, frame.height, 1.0 / frame.width, 1.0 / frame.height);
|
||||
glActiveTexture(GL_TEXTURE0 + (aid++));
|
||||
glBindTexture(GL_TEXTURE_2D, pixmap.texture);
|
||||
glrParameters(pixmap.filter, pixmap.wrap);
|
||||
glBindTexture(GL_TEXTURE_2D, frame.texture);
|
||||
glrParameters(frame.filter, frame.wrap);
|
||||
}
|
||||
|
||||
unsigned bid = 0;
|
||||
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));
|
||||
for(auto& source : sources) {
|
||||
glrUniform1i({"source[", bid, "]"}, aid + bid);
|
||||
glrUniform4f({"sourceSize[", bid, "]"}, source.width, source.height, 1.0 / source.width, 1.0 / source.height);
|
||||
glActiveTexture(GL_TEXTURE0 + aid + (bid++));
|
||||
glBindTexture(GL_TEXTURE_2D, source.texture);
|
||||
glrParameters(source.filter, source.wrap);
|
||||
}
|
||||
|
||||
unsigned cid = 0;
|
||||
for(auto& pixmap : p.pixmaps) {
|
||||
glrUniform1i({"pixmap[", cid, "]"}, aid + bid + cid);
|
||||
glrUniform4f({"pixmapSize[", bid, "]"}, pixmap.width, pixmap.height, 1.0 / pixmap.width, 1.0 / pixmap.height);
|
||||
glActiveTexture(GL_TEXTURE0 + aid + bid + (cid++));
|
||||
glBindTexture(GL_TEXTURE_2D, pixmap.texture);
|
||||
glrParameters(pixmap.filter, pixmap.wrap);
|
||||
}
|
||||
|
@ -99,7 +133,7 @@ void OpenGL::refresh() {
|
|||
|
||||
p.phase = (p.phase + 1) % p.modulo;
|
||||
sourceWidth = p.width, sourceHeight = p.height;
|
||||
history.prepend({p.texture, sourceWidth, sourceHeight, p.filter, p.wrap});
|
||||
sources.prepend({p.texture, sourceWidth, sourceHeight, p.filter, p.wrap});
|
||||
}
|
||||
|
||||
unsigned targetWidth = absoluteWidth ? absoluteWidth : outputWidth;
|
||||
|
@ -116,6 +150,19 @@ void OpenGL::refresh() {
|
|||
|
||||
glrParameters(filter, wrap);
|
||||
render(sourceWidth, sourceHeight, outputWidth, outputHeight);
|
||||
|
||||
if(frames.size() > 0) {
|
||||
OpenGLTexture frame = frames.take();
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, frame.texture);
|
||||
if(width == frame.width && height == frame.height) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, inputFormat, buffer);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, frame.format, frame.width = width, frame.height = height, 0, GL_BGRA, inputFormat, buffer);
|
||||
}
|
||||
|
||||
frames.prepend(frame);
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGL::init() {
|
||||
|
@ -142,6 +189,7 @@ bool OpenGL::init() {
|
|||
}
|
||||
|
||||
void OpenGL::term() {
|
||||
shader(nullptr); //release shader resources (eg frame[] history)
|
||||
OpenGLSurface::release();
|
||||
if(buffer) { delete[] buffer; buffer = nullptr; }
|
||||
}
|
||||
|
|
|
@ -62,12 +62,20 @@ struct OpenGLProgram : OpenGLSurface {
|
|||
|
||||
struct OpenGL : OpenGLProgram {
|
||||
vector<OpenGLProgram> programs;
|
||||
vector<OpenGLTexture> frames;
|
||||
struct History {
|
||||
unsigned length = 0;
|
||||
GLuint format = GL_RGBA8;
|
||||
GLuint filter = GL_LINEAR;
|
||||
GLuint wrap = GL_CLAMP_TO_BORDER;
|
||||
} history;
|
||||
|
||||
GLuint inputFormat = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||
unsigned outputWidth = 0;
|
||||
unsigned outputHeight = 0;
|
||||
|
||||
void shader(const char* pathname);
|
||||
void bind(const Markup::Node& node, const string& pathname);
|
||||
bool lock(uint32_t*& data, unsigned& pitch);
|
||||
void clear();
|
||||
void refresh();
|
||||
|
|
|
@ -7,7 +7,6 @@ static string OpenGLOutputVertexShader = R"(
|
|||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec4 position;
|
||||
vec2 texCoord;
|
||||
} vertexOut;
|
||||
|
||||
|
@ -42,7 +41,6 @@ static string OpenGLVertexShader = R"(
|
|||
in vec2 texCoord;
|
||||
|
||||
out Vertex {
|
||||
vec4 position;
|
||||
vec2 texCoord;
|
||||
} vertexOut;
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ uint8 SA1::bus_read(unsigned addr) {
|
|||
synchronize_cpu();
|
||||
return bitmap_read(addr & 0x0fffff);
|
||||
}
|
||||
|
||||
//unmapped region
|
||||
return regs.mdr;
|
||||
}
|
||||
|
||||
void SA1::bus_write(unsigned addr, uint8 data) {
|
||||
|
@ -116,7 +119,7 @@ uint8 SA1::op_read(unsigned addr) {
|
|||
void SA1::op_write(unsigned addr, uint8 data) {
|
||||
tick();
|
||||
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
|
||||
bus_write(addr, data);
|
||||
bus_write(addr, regs.mdr = data);
|
||||
}
|
||||
|
||||
uint8 SA1::mmcrom_read(unsigned addr) {
|
||||
|
|
|
@ -11,21 +11,25 @@ include gba/Makefile
|
|||
ui_objects := ui-ethos ui-configuration ui-interface ui-utility
|
||||
ui_objects += ui-input ui-window ui-general ui-settings ui-tools
|
||||
ui_objects += phoenix ruby
|
||||
ui_objects += $(if $(call streq,$(platform),win),resource)
|
||||
ui_objects += $(if $(call streq,$(platform),windows),resource)
|
||||
|
||||
# platform
|
||||
ifeq ($(platform),x)
|
||||
ruby := video.glx video.xv video.sdl
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
|
||||
ruby += input.sdl input.x
|
||||
else ifeq ($(platform),osx)
|
||||
ruby := video.cgl
|
||||
ruby += audio.openal
|
||||
ruby += input.carbon
|
||||
else ifeq ($(platform),win)
|
||||
ifeq ($(platform),windows)
|
||||
ruby := video.direct3d video.wgl video.directdraw video.gdi
|
||||
ruby += audio.directsound audio.xaudio2
|
||||
ruby += input.rawinput input.directinput
|
||||
else ifeq ($(platform),macosx)
|
||||
ruby := video.cgl
|
||||
ruby += audio.openal
|
||||
ruby += input.carbon
|
||||
else ifeq ($(platform),linux)
|
||||
ruby := video.glx video.xv video.sdl
|
||||
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.pulseaudiosimple audio.ao
|
||||
ruby += input.sdl input.x
|
||||
else ifeq ($(platform),bsd)
|
||||
ruby := video.glx
|
||||
ruby += audio.openal audio.oss
|
||||
ruby += input.x
|
||||
endif
|
||||
|
||||
# phoenix
|
||||
|
@ -65,9 +69,10 @@ endif
|
|||
|
||||
# targets
|
||||
build: $(objects)
|
||||
ifeq ($(platform),x)
|
||||
$(strip $(compiler) -o out/$(name) $(objects) $(link))
|
||||
else ifeq ($(platform),osx)
|
||||
ifeq ($(platform),windows)
|
||||
$(strip $(compiler) -shared -o out/phoenix.dll obj/phoenix.o $(phoenixlink))
|
||||
$(strip $(compiler) -o out/$(name) $(subst obj/phoenix.o,,$(objects)) $(link) -Lout -lphoenix)
|
||||
else ifeq ($(platform),macosx)
|
||||
if [ -d out/$(name).app ]; then rm -r out/$(name).app; fi
|
||||
mkdir out/$(name).app
|
||||
mkdir out/$(name).app/Contents
|
||||
|
@ -76,16 +81,21 @@ else ifeq ($(platform),osx)
|
|||
cp data/Info.plist out/$(name).app/Contents/Info.plist
|
||||
sips -s format icns data/higan512.png --out out/$(name).app/Contents/Resources/higan.icns
|
||||
$(strip $(compiler) -o out/$(name).app/Contents/MacOS/$(name) $(objects) $(link))
|
||||
else ifeq ($(platform),win)
|
||||
$(strip $(compiler) -shared -o out/phoenix.dll obj/phoenix.o $(phoenixlink))
|
||||
$(strip $(compiler) -o out/$(name) $(subst obj/phoenix.o,,$(objects)) $(link) -Lout -lphoenix)
|
||||
else
|
||||
$(strip $(compiler) -o out/$(name) $(objects) $(link))
|
||||
endif
|
||||
|
||||
resource:
|
||||
sourcery $(ui)/resource/resource.bml $(ui)/resource/resource.cpp $(ui)/resource/resource.hpp
|
||||
|
||||
install:
|
||||
ifeq ($(platform),x)
|
||||
ifeq ($(platform),windows)
|
||||
else ifeq ($(platform),macosx)
|
||||
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)
|
||||
else
|
||||
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
|
||||
|
@ -94,14 +104,11 @@ ifeq ($(platform),x)
|
|||
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:
|
||||
ifeq ($(platform),x)
|
||||
ifeq ($(platform),windows)
|
||||
else ifeq ($(platform),macosx)
|
||||
else
|
||||
sudo rm $(DESTDIR)$(prefix)/bin/$(name)
|
||||
endif
|
||||
|
|
|
@ -28,7 +28,7 @@ Browser::Browser() {
|
|||
};
|
||||
|
||||
homeButton.onActivate = [&] {
|
||||
string libraryPath = string::read({configpath(), "higan/library.cfg"}).strip();
|
||||
string libraryPath = string::read({configpath(), "higan/library.bml"}).strip().ltrim<1>("Path: ").transform("\\", "/");
|
||||
if(libraryPath.empty()) libraryPath = {userpath(), "Emulation/"};
|
||||
if(libraryPath.endswith("/") == false) libraryPath.append("/");
|
||||
setPath(libraryPath);
|
||||
|
|
|
@ -12,6 +12,7 @@ void Presentation::synchronize() {
|
|||
shaderNone.setChecked();
|
||||
if(config->video.shader == "None") shaderNone.setChecked();
|
||||
if(config->video.shader == "Blur") shaderBlur.setChecked();
|
||||
if(config->video.shader == "Emulation") shaderEmulation.setChecked();
|
||||
for(auto& shader : shaderList) {
|
||||
string name = notdir(config->video.shader.split<1>(".shader/")(0));
|
||||
if(name == shader->text()) shader->setChecked();
|
||||
|
@ -43,7 +44,7 @@ void Presentation::synchronize() {
|
|||
}
|
||||
|
||||
void Presentation::setSystemName(string name) {
|
||||
if(active) active->menu.setText(name);
|
||||
if(active) active->menu.setText(systemName = name);
|
||||
}
|
||||
|
||||
Presentation::Presentation() {
|
||||
|
@ -73,6 +74,7 @@ Presentation::Presentation() {
|
|||
shaderMenu.setText("Shader");
|
||||
shaderNone.setText("None");
|
||||
shaderBlur.setText("Blur");
|
||||
shaderEmulation.setText("Display Emulation");
|
||||
synchronizeVideo.setText("Synchronize Video");
|
||||
synchronizeAudio.setText("Synchronize Audio");
|
||||
muteAudio.setText("Mute Audio");
|
||||
|
@ -96,8 +98,11 @@ Presentation::Presentation() {
|
|||
videoMenu.append(centerVideo, scaleVideo, stretchVideo, *new Separator, aspectCorrection, maskOverscan);
|
||||
settingsMenu.append(shaderMenu);
|
||||
shaderMenu.append(shaderNone, shaderBlur);
|
||||
if(shaderList.size() > 0) shaderMenu.append(*new Separator);
|
||||
for(auto& shader : shaderList) shaderMenu.append(*shader);
|
||||
if(config->video.driver == "OpenGL") shaderMenu.append(shaderEmulation);
|
||||
if(shaderList.size() > 0) {
|
||||
shaderMenu.append(*new Separator);
|
||||
for(auto& shader : shaderList) shaderMenu.append(*shader);
|
||||
}
|
||||
settingsMenu.append(*new Separator);
|
||||
settingsMenu.append(synchronizeVideo, synchronizeAudio, muteAudio);
|
||||
if(Intrinsics::platform() != Intrinsics::Platform::OSX) {
|
||||
|
@ -146,6 +151,7 @@ Presentation::Presentation() {
|
|||
|
||||
shaderNone.onActivate = [&] { config->video.shader = "None"; utility->updateShader(); };
|
||||
shaderBlur.onActivate = [&] { config->video.shader = "Blur"; utility->updateShader(); };
|
||||
shaderEmulation.onActivate = [&] { config->video.shader = "Emulation"; utility->updateShader(); };
|
||||
centerVideo.onActivate = [&] { config->video.scaleMode = 0; utility->resize(); };
|
||||
scaleVideo.onActivate = [&] { config->video.scaleMode = 1; utility->resize(); };
|
||||
stretchVideo.onActivate = [&] { config->video.scaleMode = 2; utility->resize(); };
|
||||
|
@ -245,6 +251,7 @@ void Presentation::loadShaders() {
|
|||
nall::group<RadioItem> group;
|
||||
group.append(shaderNone);
|
||||
group.append(shaderBlur);
|
||||
group.append(shaderEmulation);
|
||||
for(auto& shader : shaderList) group.append(*shader);
|
||||
RadioItem::group(group);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ struct Presentation : Window {
|
|||
Menu shaderMenu;
|
||||
RadioItem shaderNone;
|
||||
RadioItem shaderBlur;
|
||||
RadioItem shaderEmulation;
|
||||
vector<RadioItem*> shaderList;
|
||||
CheckItem synchronizeVideo;
|
||||
CheckItem synchronizeAudio;
|
||||
|
@ -56,6 +57,9 @@ struct Presentation : Window {
|
|||
void loadShaders();
|
||||
void bootstrap();
|
||||
Presentation();
|
||||
|
||||
//internal:
|
||||
string systemName;
|
||||
};
|
||||
|
||||
extern Presentation* presentation;
|
||||
|
|
|
@ -110,6 +110,7 @@ void Utility::load() {
|
|||
synchronizeDSP();
|
||||
|
||||
resize();
|
||||
updateShader();
|
||||
cheatEditor->synchronize();
|
||||
cheatEditor->refresh();
|
||||
}
|
||||
|
@ -198,14 +199,28 @@ void Utility::updateShader() {
|
|||
if(config->video.shader == "None") {
|
||||
video.set(Video::Shader, (const char*)"");
|
||||
video.set(Video::Filter, Video::FilterNearest);
|
||||
return;
|
||||
}
|
||||
if(config->video.shader == "Blur") {
|
||||
} else if(config->video.shader == "Blur") {
|
||||
video.set(Video::Shader, (const char*)"");
|
||||
video.set(Video::Filter, Video::FilterLinear);
|
||||
return;
|
||||
} else if(config->video.shader == "Emulation") {
|
||||
if(program->active) {
|
||||
string pathname = program->path("Video Shaders/");
|
||||
pathname.append("Emulation/");
|
||||
pathname.append(presentation->systemName, ".shader/");
|
||||
if(directory::exists(pathname)) {
|
||||
video.set(Video::Shader, (const char*)pathname);
|
||||
} else {
|
||||
video.set(Video::Shader, (const char*)"");
|
||||
video.set(Video::Filter, Video::FilterLinear);
|
||||
}
|
||||
} else {
|
||||
video.set(Video::Shader, (const char*)"");
|
||||
video.set(Video::Filter, Video::FilterLinear);
|
||||
}
|
||||
} else {
|
||||
video.set(Video::Shader, (const char*)config->video.shader);
|
||||
}
|
||||
video.set(Video::Shader, (const char*)config->video.shader);
|
||||
}
|
||||
|
||||
void Utility::resize(bool resizeWindow) {
|
||||
|
|
Loading…
Reference in New Issue