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:
Tim Allen 2013-10-21 22:45:39 +11:00
parent 4e2eb23835
commit 66f136718e
23 changed files with 242 additions and 117 deletions

View File

@ -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

View File

@ -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/";

View File

@ -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 :=

View File

@ -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);

View File

@ -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__)

View File

@ -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() {}

View File

@ -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) {

View File

@ -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";
}

View File

@ -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;

View File

@ -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--) {

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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; }
}

View File

@ -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();

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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) {