mirror of https://github.com/bsnes-emu/bsnes.git
Update to v070r03 release.
byuu says: - fixed a bug in xml_element::parse() with <![CDATA[...]]> tags - merged FragmentShader and and VertexShader into Shader, which is an XML file that contains all relevant data - updated Qt port to reflect the above - added support for pixel shaders to the phoenix port - updated all pixel shaders to use the new format - ruby won't crash if you give an HLSL driver a GLSL shader or vice versa, but it will still crash on bad programs - phoenix::Viewport has its own window class, that paints a black brush background [The XML shader] format is subject to change, more specifically I may change the <source> tag from HLSL shaders. In the long-long term, it'd be nice to extend the format to allow multiple shaders to be chained together and to encode base64 texture files. But for now, this is good enough.
This commit is contained in:
parent
73fdbf893f
commit
f28d70f9e6
|
@ -17,31 +17,44 @@ namespace nall {
|
||||||
|
|
||||||
struct data_t {
|
struct data_t {
|
||||||
R (*callback)(const data_t&, P...);
|
R (*callback)(const data_t&, P...);
|
||||||
union {
|
|
||||||
R (*callback_global)(P...);
|
R (*callback_global)(P...);
|
||||||
struct {
|
struct {
|
||||||
R (derived::*callback_member)(P...);
|
R (derived::*callback_member)(P...);
|
||||||
void *object;
|
void *callback_object;
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
std::function<R (P...)> callback_lambda;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
static R callback_global(const data_t &data, P... p) {
|
static R callback_global(const data_t &data, P... p) {
|
||||||
return data.callback_global(p...);
|
return data.callback_global(std::forward<P>(p)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
static R callback_member(const data_t &data, P... p) {
|
static R callback_member(const data_t &data, P... p) {
|
||||||
return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...);
|
return (((C*)data.callback_object)->*((R (C::*&)(P...))data.callback_member))(std::forward<P>(p)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
static R callback_lambda(const data_t &data, P... p) {
|
||||||
|
return data.callback_lambda(std::forward<P>(p)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
R operator()(P... p) const { return data.callback(data, p...); }
|
R operator()(P... p) const { return data.callback(data, std::forward<P>(p)...); }
|
||||||
operator bool() const { return data.callback; }
|
operator bool() const { return data.callback; }
|
||||||
void reset() { data.callback = 0; }
|
void reset() { data.callback = 0; }
|
||||||
|
|
||||||
function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; }
|
function& operator=(const function &source) {
|
||||||
function(const function &source) { operator=(source); }
|
data.callback = source.data.callback;
|
||||||
|
data.callback_global = source.data.callback_global;
|
||||||
|
data.callback_member = source.data.callback_member;
|
||||||
|
data.callback_object = source.data.callback_object;
|
||||||
|
data.callback_lambda = source.data.callback_lambda;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function(const function &source) {
|
||||||
|
operator=(source);
|
||||||
|
}
|
||||||
|
|
||||||
//no pointer
|
//no pointer
|
||||||
function() {
|
function() {
|
||||||
|
@ -66,7 +79,7 @@ namespace nall {
|
||||||
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
|
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
|
||||||
data.callback = &callback_member<C>;
|
data.callback = &callback_member<C>;
|
||||||
(R (C::*&)(P...))data.callback_member = callback;
|
(R (C::*&)(P...))data.callback_member = callback;
|
||||||
data.object = object;
|
data.callback_object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
//const member function pointer
|
//const member function pointer
|
||||||
|
@ -75,15 +88,15 @@ namespace nall {
|
||||||
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
|
static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small");
|
||||||
data.callback = &callback_member<C>;
|
data.callback = &callback_member<C>;
|
||||||
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
|
(R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback;
|
||||||
data.object = object;
|
data.callback_object = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
//lambda function pointer
|
//lambda function pointer
|
||||||
template<typename T>
|
template<typename T>
|
||||||
function(T callback) {
|
function(const T &callback) {
|
||||||
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
|
static_assert(std::is_same<R, typename std::result_of<T(P...)>::type>::value, "lambda mismatch");
|
||||||
data.callback = &callback_global;
|
data.callback = &callback_lambda;
|
||||||
data.callback_global = (R (*)(P...))callback;
|
data.callback_lambda = callback;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ inline string xml_element::parse() const {
|
||||||
data << cdata;
|
data << cdata;
|
||||||
offset += strlen(cdata);
|
offset += strlen(cdata);
|
||||||
|
|
||||||
source += offset + 3;
|
source += 9 + offset + 3;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
|
void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, unsigned height) {
|
||||||
widget->window = CreateWindow(
|
widget->window = CreateWindow(
|
||||||
L"phoenix_window", L"",
|
L"phoenix_viewport", L"",
|
||||||
WS_CHILD | WS_VISIBLE | WS_DISABLED,
|
WS_CHILD | WS_VISIBLE | WS_DISABLED,
|
||||||
x, y, width, height,
|
x, y, width, height,
|
||||||
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
|
parent.widget->window, (HMENU)object->id, GetModuleHandle(0), 0
|
||||||
|
@ -11,3 +11,7 @@ void Viewport::create(Window &parent, unsigned x, unsigned y, unsigned width, un
|
||||||
uintptr_t Viewport::handle() {
|
uintptr_t Viewport::handle() {
|
||||||
return (uintptr_t)widget->window;
|
return (uintptr_t)widget->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
||||||
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
|
@ -440,6 +440,18 @@ OS::OS() {
|
||||||
wc.lpszMenuName = 0;
|
wc.lpszMenuName = 0;
|
||||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
RegisterClass(&wc);
|
RegisterClass(&wc);
|
||||||
|
|
||||||
|
wc.cbClsExtra = 0;
|
||||||
|
wc.cbWndExtra = 0;
|
||||||
|
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
|
||||||
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||||
|
wc.hInstance = GetModuleHandle(0);
|
||||||
|
wc.lpfnWndProc = Viewport_windowProc;
|
||||||
|
wc.lpszClassName = L"phoenix_viewport";
|
||||||
|
wc.lpszMenuName = 0;
|
||||||
|
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
RegisterClass(&wc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ InputInterface input;
|
||||||
const char *Video::Handle = "Handle";
|
const char *Video::Handle = "Handle";
|
||||||
const char *Video::Synchronize = "Synchronize";
|
const char *Video::Synchronize = "Synchronize";
|
||||||
const char *Video::Filter = "Filter";
|
const char *Video::Filter = "Filter";
|
||||||
|
const char *Video::Shader = "Shader";
|
||||||
const char *Video::FragmentShader = "FragmentShader";
|
const char *Video::FragmentShader = "FragmentShader";
|
||||||
const char *Video::VertexShader = "VertexShader";
|
const char *Video::VertexShader = "VertexShader";
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ public:
|
||||||
static const char *Handle;
|
static const char *Handle;
|
||||||
static const char *Synchronize;
|
static const char *Synchronize;
|
||||||
static const char *Filter;
|
static const char *Filter;
|
||||||
|
static const char *Shader;
|
||||||
static const char *FragmentShader;
|
static const char *FragmentShader;
|
||||||
static const char *VertexShader;
|
static const char *VertexShader;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ public:
|
||||||
LPDIRECT3DTEXTURE9 texture;
|
LPDIRECT3DTEXTURE9 texture;
|
||||||
LPDIRECT3DSURFACE9 surface;
|
LPDIRECT3DSURFACE9 surface;
|
||||||
LPD3DXEFFECT effect;
|
LPD3DXEFFECT effect;
|
||||||
string shaderSource;
|
string shader_source_xml;
|
||||||
|
|
||||||
bool lost;
|
bool lost;
|
||||||
unsigned iwidth, iheight;
|
unsigned iwidth, iheight;
|
||||||
|
@ -64,7 +64,7 @@ public:
|
||||||
if(name == Video::Handle) return true;
|
if(name == Video::Handle) return true;
|
||||||
if(name == Video::Synchronize) return true;
|
if(name == Video::Synchronize) return true;
|
||||||
if(name == Video::Filter) return true;
|
if(name == Video::Filter) return true;
|
||||||
if(name == Video::FragmentShader) return true;
|
if(name == Video::Shader) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name == Video::FragmentShader) {
|
if(name == Video::Shader) {
|
||||||
set_fragment_shader(any_cast<const char*>(value));
|
set_shader(any_cast<const char*>(value));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ public:
|
||||||
//failure to do so causes scaling issues on some video drivers.
|
//failure to do so causes scaling issues on some video drivers.
|
||||||
if(state.width != rd.right || state.height != rd.bottom) {
|
if(state.width != rd.right || state.height != rd.bottom) {
|
||||||
init();
|
init();
|
||||||
set_fragment_shader(shaderSource);
|
set_shader(shader_source_xml);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ public:
|
||||||
if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true;
|
if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_fragment_shader(const char *source) {
|
void set_shader(const char *source) {
|
||||||
if(!caps.shader) return;
|
if(!caps.shader) return;
|
||||||
|
|
||||||
if(effect) {
|
if(effect) {
|
||||||
|
@ -336,11 +336,27 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!source || !*source) {
|
if(!source || !*source) {
|
||||||
shaderSource = "";
|
shader_source_xml = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
shader_source_xml = source;
|
||||||
|
|
||||||
shaderSource = source;
|
bool is_hlsl = false;
|
||||||
|
string shader_source;
|
||||||
|
xml_element document = xml_parse(shader_source_xml);
|
||||||
|
foreach(head, document.element) {
|
||||||
|
if(head.name == "shader") {
|
||||||
|
foreach(attribute, head.attribute) {
|
||||||
|
if(attribute.name == "language" && attribute.content == "HLSL") is_hlsl = true;
|
||||||
|
}
|
||||||
|
foreach(element, head.element) {
|
||||||
|
if(element.name == "source") {
|
||||||
|
if(is_hlsl) shader_source = element.parse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(shader_source == "") return;
|
||||||
|
|
||||||
HMODULE d3dx;
|
HMODULE d3dx;
|
||||||
for(unsigned i = 0; i < 256; i++) {
|
for(unsigned i = 0; i < 256; i++) {
|
||||||
|
@ -356,7 +372,7 @@ public:
|
||||||
TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA");
|
TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA");
|
||||||
|
|
||||||
LPD3DXBUFFER pBufferErrors = NULL;
|
LPD3DXBUFFER pBufferErrors = NULL;
|
||||||
effectProc(device, shaderSource, lstrlenA(source), NULL, NULL, 0, NULL, &effect, &pBufferErrors);
|
effectProc(device, shader_source, lstrlenA(shader_source), NULL, NULL, 0, NULL, &effect, &pBufferErrors);
|
||||||
|
|
||||||
D3DXHANDLE hTech;
|
D3DXHANDLE hTech;
|
||||||
effect->FindNextValidTechnique(NULL, &hTech);
|
effect->FindNextValidTechnique(NULL, &hTech);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
video.glx
|
video.glx
|
||||||
author: byuu
|
author: byuu
|
||||||
license: public domain
|
license: public domain
|
||||||
last updated: 2010-01-05
|
last updated: 2010-09-28
|
||||||
|
|
||||||
Design notes:
|
Design notes:
|
||||||
SGI's GLX is the X11/Xlib interface to OpenGL.
|
SGI's GLX is the X11/Xlib interface to OpenGL.
|
||||||
|
@ -62,6 +62,7 @@ public:
|
||||||
if(name == Video::Handle) return true;
|
if(name == Video::Handle) return true;
|
||||||
if(name == Video::Synchronize) return true;
|
if(name == Video::Synchronize) return true;
|
||||||
if(name == Video::Filter) return true;
|
if(name == Video::Filter) return true;
|
||||||
|
if(name == Video::Shader) return true;
|
||||||
if(name == Video::FragmentShader) return true;
|
if(name == Video::FragmentShader) return true;
|
||||||
if(name == Video::VertexShader) return true;
|
if(name == Video::VertexShader) return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -93,6 +94,11 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(name == Video::Shader) {
|
||||||
|
OpenGL::set_shader(any_cast<const char*>(value));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if(name == Video::FragmentShader) {
|
if(name == Video::FragmentShader) {
|
||||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -122,7 +122,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_fragment_shader(const char *source) {
|
void set_shader(const char *source) {
|
||||||
if(!shader_support) return;
|
if(!shader_support) return;
|
||||||
|
|
||||||
if(fragmentshader) {
|
if(fragmentshader) {
|
||||||
|
@ -131,19 +131,6 @@ public:
|
||||||
fragmentshader = 0;
|
fragmentshader = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(source) {
|
|
||||||
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
glShaderSource(fragmentshader, 1, &source, 0);
|
|
||||||
glCompileShader(fragmentshader);
|
|
||||||
glAttachShader(glprogram, fragmentshader);
|
|
||||||
}
|
|
||||||
|
|
||||||
glLinkProgram(glprogram);
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_vertex_shader(const char *source) {
|
|
||||||
if(!shader_support) return;
|
|
||||||
|
|
||||||
if(vertexshader) {
|
if(vertexshader) {
|
||||||
glDetachShader(glprogram, vertexshader);
|
glDetachShader(glprogram, vertexshader);
|
||||||
glDeleteShader(vertexshader);
|
glDeleteShader(vertexshader);
|
||||||
|
@ -151,15 +138,49 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(source) {
|
if(source) {
|
||||||
|
bool is_glsl = false;
|
||||||
|
string fragment_source;
|
||||||
|
string vertex_source;
|
||||||
|
|
||||||
|
xml_element document = xml_parse(source);
|
||||||
|
foreach(head, document.element) {
|
||||||
|
if(head.name == "shader") {
|
||||||
|
foreach(attribute, head.attribute) {
|
||||||
|
if(attribute.name == "language" && attribute.content == "GLSL") is_glsl = true;
|
||||||
|
}
|
||||||
|
foreach(element, head.element) {
|
||||||
|
if(element.name == "fragment") {
|
||||||
|
fragment_source = element.parse();
|
||||||
|
} else if(element.name == "vertex") {
|
||||||
|
vertex_source = element.parse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(is_glsl) {
|
||||||
|
if(fragment_source != "") set_fragment_shader(fragment_source);
|
||||||
|
if(vertex_source != "") set_vertex_shader(vertex_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glLinkProgram(glprogram);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_fragment_shader(const char *source) {
|
||||||
|
fragmentshader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fragmentshader, 1, &source, 0);
|
||||||
|
glCompileShader(fragmentshader);
|
||||||
|
glAttachShader(glprogram, fragmentshader);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_vertex_shader(const char *source) {
|
||||||
vertexshader = glCreateShader(GL_VERTEX_SHADER);
|
vertexshader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vertexshader, 1, &source, 0);
|
glShaderSource(vertexshader, 1, &source, 0);
|
||||||
glCompileShader(vertexshader);
|
glCompileShader(vertexshader);
|
||||||
glAttachShader(glprogram, vertexshader);
|
glAttachShader(glprogram, vertexshader);
|
||||||
}
|
}
|
||||||
|
|
||||||
glLinkProgram(glprogram);
|
|
||||||
}
|
|
||||||
|
|
||||||
void init() {
|
void init() {
|
||||||
//disable unused features
|
//disable unused features
|
||||||
glDisable(GL_ALPHA_TEST);
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
|
@ -29,8 +29,7 @@ public:
|
||||||
if(name == Video::Handle) return true;
|
if(name == Video::Handle) return true;
|
||||||
if(name == Video::Synchronize) return true;
|
if(name == Video::Synchronize) return true;
|
||||||
if(name == Video::Filter) return true;
|
if(name == Video::Filter) return true;
|
||||||
if(name == Video::FragmentShader) return true;
|
if(name == Video::Shader) return true;
|
||||||
if(name == Video::VertexShader) return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,13 +58,8 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name == Video::FragmentShader) {
|
if(name == Video::Shader) {
|
||||||
OpenGL::set_fragment_shader(any_cast<const char*>(value));
|
OpenGL::set_shader(any_cast<const char*>(value));
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(name == Video::VertexShader) {
|
|
||||||
OpenGL::set_vertex_shader(any_cast<const char*>(value));
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "070.02";
|
static const char Version[] = "070.03";
|
||||||
static const unsigned SerializerVersion = 13;
|
static const unsigned SerializerVersion = 13;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,9 @@ void Configuration::create() {
|
||||||
|
|
||||||
attach(video.driver = "", "video.driver");
|
attach(video.driver = "", "video.driver");
|
||||||
attach(video.synchronize = false, "video.synchronize");
|
attach(video.synchronize = false, "video.synchronize");
|
||||||
attach(video.region = 0, "video.region");
|
|
||||||
attach(video.smooth = true, "video.smooth");
|
attach(video.smooth = true, "video.smooth");
|
||||||
|
attach(video.shader = "", "video.shader");
|
||||||
|
attach(video.region = 0, "video.region");
|
||||||
attach(video.scale = 2, "video.scale");
|
attach(video.scale = 2, "video.scale");
|
||||||
attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection");
|
attach(video.aspectRatioCorrection = true, "video.aspectRatioCorrection");
|
||||||
attach(video.contrast = 100, "video.contrast");
|
attach(video.contrast = 100, "video.contrast");
|
||||||
|
|
|
@ -11,8 +11,9 @@ struct Configuration : public configuration {
|
||||||
struct Video {
|
struct Video {
|
||||||
string driver;
|
string driver;
|
||||||
bool synchronize;
|
bool synchronize;
|
||||||
bool region;
|
|
||||||
bool smooth;
|
bool smooth;
|
||||||
|
string shader;
|
||||||
|
bool region;
|
||||||
unsigned scale;
|
unsigned scale;
|
||||||
bool aspectRatioCorrection;
|
bool aspectRatioCorrection;
|
||||||
unsigned contrast;
|
unsigned contrast;
|
||||||
|
|
|
@ -48,6 +48,9 @@ void FileBrowser::fileOpen(FileBrowser::Mode requestedMode, function<void (strin
|
||||||
filters.append(".gbc");
|
filters.append(".gbc");
|
||||||
filters.append(".sgb");
|
filters.append(".sgb");
|
||||||
}
|
}
|
||||||
|
case Mode::Shader: {
|
||||||
|
filters.append(".shader");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct FileBrowser : Window {
|
||||||
Button upButton;
|
Button upButton;
|
||||||
ListBox contentsBox;
|
ListBox contentsBox;
|
||||||
|
|
||||||
enum class Mode : unsigned { Cartridge, Satellaview, SufamiTurbo, GameBoy } mode;
|
enum class Mode : unsigned { Cartridge, Satellaview, SufamiTurbo, GameBoy, Shader } mode;
|
||||||
void fileOpen(Mode mode, function<void (string)> callback);
|
void fileOpen(Mode mode, function<void (string)> callback);
|
||||||
void create();
|
void create();
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,7 @@ void Application::main(int argc, char **argv) {
|
||||||
video.driver("None");
|
video.driver("None");
|
||||||
video.init();
|
video.init();
|
||||||
}
|
}
|
||||||
|
utility.setShader();
|
||||||
|
|
||||||
audio.driver(config.audio.driver);
|
audio.driver(config.audio.driver);
|
||||||
audio.set(Audio::Handle, mainWindow.viewport.handle());
|
audio.set(Audio::Handle, mainWindow.viewport.handle());
|
||||||
|
|
|
@ -5,7 +5,7 @@ void VideoSettings::create() {
|
||||||
Window::create(0, 0, 256, 256, "Video Settings");
|
Window::create(0, 0, 256, 256, "Video Settings");
|
||||||
setDefaultFont(application.proportionalFont);
|
setDefaultFont(application.proportionalFont);
|
||||||
|
|
||||||
unsigned x = 5, y = 5;
|
unsigned x = 5, y = 5, height = Style::TextBoxHeight;
|
||||||
|
|
||||||
colorAdjustmentLabel.create(*this, x, y, 430, Style::LabelHeight, "Color Adjustment :."); y += Style::LabelHeight + 5;
|
colorAdjustmentLabel.create(*this, x, y, 430, Style::LabelHeight, "Color Adjustment :."); y += Style::LabelHeight + 5;
|
||||||
colorAdjustmentLabel.setFont(application.proportionalFontBold);
|
colorAdjustmentLabel.setFont(application.proportionalFontBold);
|
||||||
|
@ -24,6 +24,15 @@ void VideoSettings::create() {
|
||||||
|
|
||||||
gammaRampCheck.create (*this, x, y, 430, Style::CheckBoxHeight, "Enable NTSC gamma ramp simulation"); y += Style::CheckBoxHeight + 5;
|
gammaRampCheck.create (*this, x, y, 430, Style::CheckBoxHeight, "Enable NTSC gamma ramp simulation"); y += Style::CheckBoxHeight + 5;
|
||||||
|
|
||||||
|
shaderLabel.create(*this, x, y, 340, Style::LabelHeight, "Pixel Shader :."); y += Style::LabelHeight + 5;
|
||||||
|
shaderLabel.setFont(application.proportionalFontBold);
|
||||||
|
|
||||||
|
shaderPath.create(*this, x, y, 430 - height - height - 10, height);
|
||||||
|
shaderPath.setEditable(false);
|
||||||
|
shaderPath.setText(config.video.shader);
|
||||||
|
shaderClear.create(*this, x + 430 - height - height - 5, y, height, height, "");
|
||||||
|
shaderSelect.create(*this, x + 430 - height, y, height, height, "..."); y += height + 5;
|
||||||
|
|
||||||
setGeometry(160, 160, 440, y);
|
setGeometry(160, 160, 440, y);
|
||||||
|
|
||||||
contrastSlider.setPosition(config.video.contrast);
|
contrastSlider.setPosition(config.video.contrast);
|
||||||
|
@ -33,6 +42,20 @@ void VideoSettings::create() {
|
||||||
|
|
||||||
contrastSlider.onChange = brightnessSlider.onChange = gammaSlider.onChange = gammaRampCheck.onTick =
|
contrastSlider.onChange = brightnessSlider.onChange = gammaSlider.onChange = gammaRampCheck.onTick =
|
||||||
{ &VideoSettings::adjust, this };
|
{ &VideoSettings::adjust, this };
|
||||||
|
|
||||||
|
shaderClear.onTick = []() {
|
||||||
|
config.video.shader = "";
|
||||||
|
videoSettings.shaderPath.setText(config.video.shader);
|
||||||
|
utility.setShader();
|
||||||
|
};
|
||||||
|
|
||||||
|
shaderSelect.onTick = []() {
|
||||||
|
fileBrowser.fileOpen(FileBrowser::Mode::Shader, [](string filename) {
|
||||||
|
config.video.shader = filename;
|
||||||
|
videoSettings.shaderPath.setText(config.video.shader);
|
||||||
|
utility.setShader();
|
||||||
|
});
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSettings::adjust() {
|
void VideoSettings::adjust() {
|
||||||
|
|
|
@ -10,6 +10,10 @@ struct VideoSettings : Window {
|
||||||
Label gammaValue;
|
Label gammaValue;
|
||||||
HorizontalSlider gammaSlider;
|
HorizontalSlider gammaSlider;
|
||||||
CheckBox gammaRampCheck;
|
CheckBox gammaRampCheck;
|
||||||
|
Label shaderLabel;
|
||||||
|
TextBox shaderPath;
|
||||||
|
Button shaderClear;
|
||||||
|
Button shaderSelect;
|
||||||
|
|
||||||
void create();
|
void create();
|
||||||
void adjust();
|
void adjust();
|
||||||
|
|
|
@ -51,6 +51,12 @@ void Utility::setScale(unsigned scale) {
|
||||||
mainWindow.setGeometry(128, 128, width, height);
|
mainWindow.setGeometry(128, 128, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Utility::setShader() {
|
||||||
|
string data;
|
||||||
|
data.readfile(config.video.shader);
|
||||||
|
video.set(Video::Shader, (const char*)data);
|
||||||
|
}
|
||||||
|
|
||||||
void Utility::cartridgeLoaded() {
|
void Utility::cartridgeLoaded() {
|
||||||
SNES::system.power();
|
SNES::system.power();
|
||||||
cheatEditor.load(cartridge.baseName);
|
cheatEditor.load(cartridge.baseName);
|
||||||
|
|
|
@ -5,6 +5,7 @@ struct Utility : property<Utility> {
|
||||||
void showMessage(const char *text);
|
void showMessage(const char *text);
|
||||||
|
|
||||||
void setScale(unsigned scale = 0);
|
void setScale(unsigned scale = 0);
|
||||||
|
void setShader();
|
||||||
|
|
||||||
void cartridgeLoaded();
|
void cartridgeLoaded();
|
||||||
void cartridgeUnloaded();
|
void cartridgeUnloaded();
|
||||||
|
|
|
@ -60,8 +60,7 @@ Configuration::Configuration() {
|
||||||
attach(path.bsx = "", "path.bsx");
|
attach(path.bsx = "", "path.bsx");
|
||||||
attach(path.st = "", "path.st");
|
attach(path.st = "", "path.st");
|
||||||
attach(path.sgb = "", "path.sgb");
|
attach(path.sgb = "", "path.sgb");
|
||||||
attach(path.fragmentShader = "", "path.fragmentShader");
|
attach(path.shader = "", "path.shader");
|
||||||
attach(path.vertexShader = "", "path.vertexShader");
|
|
||||||
|
|
||||||
attach(path.current.folder = "", "path.current.folder");
|
attach(path.current.folder = "", "path.current.folder");
|
||||||
attach(path.current.movie = "", "path.current.movie");
|
attach(path.current.movie = "", "path.current.movie");
|
||||||
|
|
|
@ -30,7 +30,7 @@ public:
|
||||||
string startup; //startup path
|
string startup; //startup path
|
||||||
string rom, save, state, patch, cheat, data;
|
string rom, save, state, patch, cheat, data;
|
||||||
string bsx, st, sgb;
|
string bsx, st, sgb;
|
||||||
string fragmentShader, vertexShader;
|
string shader;
|
||||||
|
|
||||||
struct Current {
|
struct Current {
|
||||||
string folder, movie, shader, cartridge;
|
string folder, movie, shader, cartridge;
|
||||||
|
|
|
@ -138,29 +138,14 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
||||||
pixelShaderLayout = new QGridLayout;
|
pixelShaderLayout = new QGridLayout;
|
||||||
layout->addLayout(pixelShaderLayout);
|
layout->addLayout(pixelShaderLayout);
|
||||||
|
|
||||||
fragmentShaderLabel = new QLabel("Fragment:");
|
shaderValue = new QLineEdit;
|
||||||
pixelShaderLayout->addWidget(fragmentShaderLabel, 0, 0);
|
pixelShaderLayout->addWidget(shaderValue, 0, 0);
|
||||||
|
|
||||||
fragmentShaderValue = new QLineEdit;
|
shaderSelect = new QPushButton("Select ...");
|
||||||
pixelShaderLayout->addWidget(fragmentShaderValue, 0, 1);
|
pixelShaderLayout->addWidget(shaderSelect, 0, 1);
|
||||||
|
|
||||||
fragmentShaderSelect = new QPushButton("Select ...");
|
shaderDefault = new QPushButton("Default");
|
||||||
pixelShaderLayout->addWidget(fragmentShaderSelect, 0, 2);
|
pixelShaderLayout->addWidget(shaderDefault, 0, 2);
|
||||||
|
|
||||||
fragmentShaderDefault = new QPushButton("Default");
|
|
||||||
pixelShaderLayout->addWidget(fragmentShaderDefault, 0, 3);
|
|
||||||
|
|
||||||
vertexShaderLabel = new QLabel("Vertex:");
|
|
||||||
pixelShaderLayout->addWidget(vertexShaderLabel, 1, 0);
|
|
||||||
|
|
||||||
vertexShaderValue = new QLineEdit;
|
|
||||||
pixelShaderLayout->addWidget(vertexShaderValue, 1, 1);
|
|
||||||
|
|
||||||
vertexShaderSelect = new QPushButton("Select ...");
|
|
||||||
pixelShaderLayout->addWidget(vertexShaderSelect, 1, 2);
|
|
||||||
|
|
||||||
vertexShaderDefault = new QPushButton("Default");
|
|
||||||
pixelShaderLayout->addWidget(vertexShaderDefault, 1, 3);
|
|
||||||
|
|
||||||
connect(autoHideFullscreenMenu, SIGNAL(stateChanged(int)), this, SLOT(autoHideFullscreenMenuToggle()));
|
connect(autoHideFullscreenMenu, SIGNAL(stateChanged(int)), this, SLOT(autoHideFullscreenMenuToggle()));
|
||||||
connect(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int)));
|
connect(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int)));
|
||||||
|
@ -172,31 +157,18 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
||||||
connect(cropTopSlider, SIGNAL(valueChanged(int)), this, SLOT(cropTopAdjust(int)));
|
connect(cropTopSlider, SIGNAL(valueChanged(int)), this, SLOT(cropTopAdjust(int)));
|
||||||
connect(cropRightSlider, SIGNAL(valueChanged(int)), this, SLOT(cropRightAdjust(int)));
|
connect(cropRightSlider, SIGNAL(valueChanged(int)), this, SLOT(cropRightAdjust(int)));
|
||||||
connect(cropBottomSlider, SIGNAL(valueChanged(int)), this, SLOT(cropBottomAdjust(int)));
|
connect(cropBottomSlider, SIGNAL(valueChanged(int)), this, SLOT(cropBottomAdjust(int)));
|
||||||
connect(fragmentShaderSelect, SIGNAL(released()), this, SLOT(selectFragmentShader()));
|
connect(shaderSelect, SIGNAL(released()), this, SLOT(selectShader()));
|
||||||
connect(fragmentShaderDefault, SIGNAL(released()), this, SLOT(defaultFragmentShader()));
|
connect(shaderDefault, SIGNAL(released()), this, SLOT(defaultShader()));
|
||||||
connect(vertexShaderSelect, SIGNAL(released()), this, SLOT(selectVertexShader()));
|
|
||||||
connect(vertexShaderDefault, SIGNAL(released()), this, SLOT(defaultVertexShader()));
|
|
||||||
|
|
||||||
syncUi();
|
syncUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSettingsWindow::synchronizePixelShaderSettings() {
|
void VideoSettingsWindow::synchronizePixelShaderSettings() {
|
||||||
if(!video.cap(Video::FragmentShader) && !video.cap(Video::VertexShader)) {
|
if(video.cap(Video::Shader) == false) {
|
||||||
pixelShaderLabel->hide();
|
pixelShaderLabel->hide();
|
||||||
}
|
shaderValue->hide();
|
||||||
|
shaderSelect->hide();
|
||||||
if(!video.cap(Video::FragmentShader)) {
|
shaderDefault->hide();
|
||||||
fragmentShaderLabel->hide();
|
|
||||||
fragmentShaderValue->hide();
|
|
||||||
fragmentShaderSelect->hide();
|
|
||||||
fragmentShaderDefault->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!video.cap(Video::VertexShader)) {
|
|
||||||
vertexShaderLabel->hide();
|
|
||||||
vertexShaderValue->hide();
|
|
||||||
vertexShaderSelect->hide();
|
|
||||||
vertexShaderDefault->hide();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +211,7 @@ void VideoSettingsWindow::syncUi() {
|
||||||
cropBottomValue->setText(string() << n << "%");
|
cropBottomValue->setText(string() << n << "%");
|
||||||
cropBottomSlider->setSliderPosition(n);
|
cropBottomSlider->setSliderPosition(n);
|
||||||
|
|
||||||
fragmentShaderValue->setText(config().path.fragmentShader);
|
shaderValue->setText(config().path.shader);
|
||||||
vertexShaderValue->setText(config().path.vertexShader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSettingsWindow::autoHideFullscreenMenuToggle() {
|
void VideoSettingsWindow::autoHideFullscreenMenuToggle() {
|
||||||
|
@ -301,41 +272,21 @@ void VideoSettingsWindow::cropBottomAdjust(int state) {
|
||||||
syncUi();
|
syncUi();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSettingsWindow::selectFragmentShader() {
|
void VideoSettingsWindow::selectShader() {
|
||||||
fileBrowser->onChange.reset();
|
fileBrowser->onChange.reset();
|
||||||
fileBrowser->onActivate = { &VideoSettingsWindow::assignFragmentShader, this };
|
fileBrowser->onActivate = { &VideoSettingsWindow::assignShader, this };
|
||||||
fileBrowser->onAccept = { &VideoSettingsWindow::assignFragmentShader, this };
|
fileBrowser->onAccept = { &VideoSettingsWindow::assignShader, this };
|
||||||
fileBrowser->setWindowTitle("Select Fragment Shader");
|
fileBrowser->setWindowTitle("Select Pixel Shader");
|
||||||
fileBrowser->setPath(config().path.current.shader);
|
fileBrowser->setPath(config().path.current.shader);
|
||||||
fileBrowser->setNameFilters("All files (*)");
|
fileBrowser->setNameFilters("Shader files (*.shader)");
|
||||||
fileBrowser->chooseFile();
|
fileBrowser->chooseFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoSettingsWindow::selectVertexShader() {
|
void VideoSettingsWindow::defaultShader() { assignShader(""); }
|
||||||
fileBrowser->onChange.reset();
|
|
||||||
fileBrowser->onActivate = { &VideoSettingsWindow::assignVertexShader, this };
|
|
||||||
fileBrowser->onAccept = { &VideoSettingsWindow::assignVertexShader, this };
|
|
||||||
fileBrowser->setWindowTitle("Select Vertex Shader");
|
|
||||||
fileBrowser->setPath(config().path.current.shader);
|
|
||||||
fileBrowser->setNameFilters("All files (*)");
|
|
||||||
fileBrowser->chooseFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoSettingsWindow::defaultFragmentShader() { assignFragmentShader(""); }
|
void VideoSettingsWindow::assignShader(const string &filename) {
|
||||||
void VideoSettingsWindow::defaultVertexShader() { assignVertexShader(""); }
|
|
||||||
|
|
||||||
void VideoSettingsWindow::assignFragmentShader(const string &filename) {
|
|
||||||
if(filename == "" || QDir(filename).exists() == false) {
|
if(filename == "" || QDir(filename).exists() == false) {
|
||||||
config().path.fragmentShader = filename;
|
config().path.shader = filename;
|
||||||
if(filename != "") config().path.current.shader = dir(filename);
|
|
||||||
syncUi();
|
|
||||||
utility.updatePixelShader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoSettingsWindow::assignVertexShader(const string &filename) {
|
|
||||||
if(filename == "" || QDir(filename).exists() == false) {
|
|
||||||
config().path.vertexShader = filename;
|
|
||||||
if(filename != "") config().path.current.shader = dir(filename);
|
if(filename != "") config().path.current.shader = dir(filename);
|
||||||
syncUi();
|
syncUi();
|
||||||
utility.updatePixelShader();
|
utility.updatePixelShader();
|
||||||
|
|
|
@ -37,14 +37,9 @@ public:
|
||||||
QSlider *cropBottomSlider;
|
QSlider *cropBottomSlider;
|
||||||
QLabel *pixelShaderLabel;
|
QLabel *pixelShaderLabel;
|
||||||
QGridLayout *pixelShaderLayout;
|
QGridLayout *pixelShaderLayout;
|
||||||
QLabel *fragmentShaderLabel;
|
QLineEdit *shaderValue;
|
||||||
QLineEdit *fragmentShaderValue;
|
QPushButton *shaderSelect;
|
||||||
QPushButton *fragmentShaderSelect;
|
QPushButton *shaderDefault;
|
||||||
QPushButton *fragmentShaderDefault;
|
|
||||||
QLabel *vertexShaderLabel;
|
|
||||||
QLineEdit *vertexShaderValue;
|
|
||||||
QPushButton *vertexShaderSelect;
|
|
||||||
QPushButton *vertexShaderDefault;
|
|
||||||
|
|
||||||
void synchronizePixelShaderSettings();
|
void synchronizePixelShaderSettings();
|
||||||
void syncUi();
|
void syncUi();
|
||||||
|
@ -61,14 +56,11 @@ private slots:
|
||||||
void cropTopAdjust(int);
|
void cropTopAdjust(int);
|
||||||
void cropRightAdjust(int);
|
void cropRightAdjust(int);
|
||||||
void cropBottomAdjust(int);
|
void cropBottomAdjust(int);
|
||||||
void selectFragmentShader();
|
void selectShader();
|
||||||
void selectVertexShader();
|
void defaultShader();
|
||||||
void defaultFragmentShader();
|
|
||||||
void defaultVertexShader();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void assignFragmentShader(const string &filename);
|
void assignShader(const string &filename);
|
||||||
void assignVertexShader(const string &filename);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern VideoSettingsWindow *videoSettingsWindow;
|
extern VideoSettingsWindow *videoSettingsWindow;
|
||||||
|
|
|
@ -73,16 +73,10 @@ void Utility::updateColorFilter() {
|
||||||
void Utility::updatePixelShader() {
|
void Utility::updatePixelShader() {
|
||||||
string filedata;
|
string filedata;
|
||||||
|
|
||||||
if(filedata.readfile(config().path.fragmentShader)) {
|
if(filedata.readfile(config().path.shader)) {
|
||||||
video.set(Video::FragmentShader, (const char*)filedata);
|
video.set(Video::Shader, (const char*)filedata);
|
||||||
} else {
|
} else {
|
||||||
video.set(Video::FragmentShader, (const char*)0);
|
video.set(Video::Shader, (const char*)0);
|
||||||
}
|
|
||||||
|
|
||||||
if(filedata.readfile(config().path.vertexShader)) {
|
|
||||||
video.set(Video::VertexShader, (const char*)filedata);
|
|
||||||
} else {
|
|
||||||
video.set(Video::VertexShader, (const char*)0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue