mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v060 release.
This is a long-term stable release. A full changelog will be available at the forum link below later in the day. Also, please note that I have merged all of the various distributions into two packages. The Windows binary package now contains both the profile-optimized (fast) build, and the debugger build. The source code package now contains sources for bsnes, snesreader, snesfilter and supergameboy. Changelog: - added Direct3D HLSL pixel shader support [mudlord] - fixed a signal issue that caused loading games to take 1-2 seconds longer in v059 - 21fx API revised to its final form, S-MSU (public documentation pending) - worked around QTBUG-7188 to fix multi-file 7-zip file listbox to update when scrolling - added scale max - normal, wide, and wide zoom modes to fullscreen mode - added overscan cropping tool (needed for wide zoom mode; useful for developers simulating games on a real TV) - added "go up one folder" button to file load dialog - added group (un)assignment to the input settings window - now honors input.allowInvalidInput setting; defaults to false [Jonas Quinn] - cheat code editor grays out empty slots - cheat code editor adds "clear selected" button to quickly erase multiple cheat codes - to load folders as game images, folders must end in .sfc, .bs, .st, .gb now - debugger: added S-CPU (H)DMA registers; S-SMP registers; S-DSP registers to properties list - snesfilter: HQ2x filter is now multi-threaded (scales infinitely: the more cores you have, the less overhead required) - pixelshaders: added screen curvature shader to simulate curved CRT tubes - source: lots of code cleanup, as always
This commit is contained in:
parent
a9943ab4f4
commit
a8263afc24
BIN
QtCore4.dll
BIN
QtCore4.dll
Binary file not shown.
BIN
QtGui4.dll
BIN
QtGui4.dll
Binary file not shown.
BIN
bsnesd.exe
BIN
bsnesd.exe
Binary file not shown.
BIN
libgomp-1.dll
BIN
libgomp-1.dll
Binary file not shown.
BIN
mingwm10.dll
BIN
mingwm10.dll
Binary file not shown.
|
@ -0,0 +1,17 @@
|
|||
//CRT curvature shader
|
||||
//license: GPL
|
||||
//author: DOLLS
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
#define distortion 0.2
|
||||
|
||||
vec2 barrelDistortion(vec2 coord) {
|
||||
vec2 cc = coord - 0.5;
|
||||
float dist = dot(cc, cc);
|
||||
return coord + cc * (dist + distortion * dist * dist) * distortion;
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = texture2D(rubyTexture, barrelDistortion(gl_TexCoord[0].xy));
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
//HDRTV GLSL shader
|
||||
//license: GPL
|
||||
//original version by SimoneT
|
||||
//ruby port by byuu
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
void main(void) {
|
||||
vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy);
|
||||
vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0));
|
||||
|
||||
if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8;
|
||||
gl_FragColor = intens;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
//HDRTV GLSL shader
|
||||
//license: GPL
|
||||
//original version by SimoneT
|
||||
//ruby port by byuu
|
||||
|
||||
void main(void) {
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
texture rubyTexture;
|
||||
|
||||
float4 vec;
|
||||
|
||||
sampler s0 = sampler_state { texture = <rubyTexture>; };
|
||||
float3 LightColor = { 1.0, 0.7, 0.5 };
|
||||
float3 DarkColor = { 0.2, 0.05, 0.0 };
|
||||
|
||||
float4 DiffColorPass(in float2 Tex : TEXCOORD0) : COLOR0
|
||||
{
|
||||
vec.x = 0.5;
|
||||
vec.y = 1.0;
|
||||
float3 scnColor = LightColor * tex2D(s0, Tex).xyz;
|
||||
float3 grayXfer = float3(0.3, 0.59, 0.11);
|
||||
float gray = dot(grayXfer, scnColor);
|
||||
float3 muted = lerp(scnColor, gray.xxx, vec.x);
|
||||
float3 sepia = lerp(DarkColor, LightColor, gray);
|
||||
float3 result = lerp(muted, sepia, vec.y);
|
||||
return float4(result, 1);
|
||||
}
|
||||
|
||||
Technique T0
|
||||
{
|
||||
pass p0 { PixelShader = compile ps_2_0 DiffColorPass(); }
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//HQ2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by guest(r)
|
||||
//ruby port by byuu
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
|
||||
const float mx = 0.325; // start smoothing wt.
|
||||
const float k = -0.250; // wt. decrease factor
|
||||
const float max_w = 0.25; // max filter weigth
|
||||
const float min_w =-0.05; // min filter weigth
|
||||
const float lum_add = 0.25; // effects smoothing
|
||||
|
||||
void main() {
|
||||
vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz;
|
||||
vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz;
|
||||
vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz;
|
||||
vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz;
|
||||
vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz;
|
||||
vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz;
|
||||
vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz;
|
||||
vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz;
|
||||
vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz;
|
||||
vec3 dt = vec3(1.0, 1.0, 1.0);
|
||||
|
||||
float md1 = dot(abs(c00 - c22), dt);
|
||||
float md2 = dot(abs(c02 - c20), dt);
|
||||
|
||||
float w1 = dot(abs(c22 - c11), dt) * md2;
|
||||
float w2 = dot(abs(c02 - c11), dt) * md1;
|
||||
float w3 = dot(abs(c00 - c11), dt) * md2;
|
||||
float w4 = dot(abs(c20 - c11), dt) * md1;
|
||||
|
||||
float t1 = w1 + w3;
|
||||
float t2 = w2 + w4;
|
||||
float ww = max(t1, t2) + 0.0001;
|
||||
|
||||
c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww);
|
||||
|
||||
float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add);
|
||||
float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add);
|
||||
|
||||
w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w);
|
||||
w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w);
|
||||
w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w);
|
||||
w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w);
|
||||
|
||||
gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11;
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
//HQ2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by guest(r)
|
||||
//ruby port by byuu
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
float x = 0.5 * (1.0 / rubyTextureSize.x);
|
||||
float y = 0.5 * (1.0 / rubyTextureSize.y);
|
||||
vec2 dg1 = vec2( x, y);
|
||||
vec2 dg2 = vec2(-x, y);
|
||||
vec2 dx = vec2(x, 0.0);
|
||||
vec2 dy = vec2(0.0, y);
|
||||
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1;
|
||||
gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy;
|
||||
gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2;
|
||||
gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx;
|
||||
gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1;
|
||||
gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy;
|
||||
gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2;
|
||||
gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
//Pixellate shader
|
||||
//license: GPL
|
||||
//author: Fes
|
||||
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec2 texelSize = 1.0 / rubyTextureSize;
|
||||
|
||||
vec2 range;
|
||||
range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99;
|
||||
range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99;
|
||||
|
||||
float left = gl_TexCoord[0].x - range.x;
|
||||
float top = gl_TexCoord[0].y + range.y;
|
||||
float right = gl_TexCoord[0].x + range.x;
|
||||
float bottom = gl_TexCoord[0].y - range.y;
|
||||
|
||||
vec4 topLeftColor = texture2D(rubyTexture, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize);
|
||||
vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize);
|
||||
vec4 bottomLeftColor = texture2D(rubyTexture, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize);
|
||||
vec4 topRightColor = texture2D(rubyTexture, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize);
|
||||
|
||||
vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top));
|
||||
|
||||
float totalArea = 4.0 * range.x * range.y;
|
||||
|
||||
vec4 averageColor;
|
||||
averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor;
|
||||
averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor;
|
||||
averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor;
|
||||
averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor;
|
||||
|
||||
gl_FragColor = averageColor;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
//Pixellate shader
|
||||
//license: GPL
|
||||
//author: Fes
|
||||
|
||||
void main() {
|
||||
gl_Position = ftransform();
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//Scale2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by Pete Bernert
|
||||
//ruby port by byuu
|
||||
uniform sampler2D rubyTexture;
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec4 colD, colF, colB, colH, col, tmp;
|
||||
vec2 sel;
|
||||
|
||||
col = texture2DProj(rubyTexture, gl_TexCoord[0]); //central (can be E0-E3)
|
||||
colD = texture2DProj(rubyTexture, gl_TexCoord[1]); //D (left)
|
||||
colF = texture2DProj(rubyTexture, gl_TexCoord[2]); //F (right)
|
||||
colB = texture2DProj(rubyTexture, gl_TexCoord[3]); //B (top)
|
||||
colH = texture2DProj(rubyTexture, gl_TexCoord[4]); //H (bottom)
|
||||
|
||||
sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy); //where are we (E0-E3)?
|
||||
//E0 is default
|
||||
if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; } //E1 (or E3): swap B and H
|
||||
if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; } //E2 (or E3): swap D and F
|
||||
|
||||
if(colB == colD && colB != colF && colD != colH) { //do the Scale2x rule
|
||||
col = colD;
|
||||
}
|
||||
|
||||
gl_FragColor = col;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//Scale2x GLSL shader
|
||||
//license: GPL
|
||||
//original version by Pete Bernert
|
||||
//ruby port by byuu
|
||||
|
||||
uniform vec2 rubyTextureSize;
|
||||
|
||||
void main() {
|
||||
vec4 offsetx;
|
||||
vec4 offsety;
|
||||
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||
|
||||
offsetx.x = 1.0 / rubyTextureSize.x;
|
||||
offsetx.y = 0.0;
|
||||
offsetx.w = 0.0;
|
||||
offsetx.z = 0.0;
|
||||
offsety.y = 1.0 / rubyTextureSize.y;
|
||||
offsety.x = 0.0;
|
||||
offsety.w = 0.0;
|
||||
offsety.z = 0.0;
|
||||
|
||||
gl_TexCoord[0] = gl_MultiTexCoord0; //center
|
||||
gl_TexCoord[1] = gl_TexCoord[0] - offsetx; //left
|
||||
gl_TexCoord[2] = gl_TexCoord[0] + offsetx; //right
|
||||
gl_TexCoord[3] = gl_TexCoord[0] - offsety; //top
|
||||
gl_TexCoord[4] = gl_TexCoord[0] + offsety; //bottom
|
||||
}
|
BIN
pthreadGC2.dll
BIN
pthreadGC2.dll
Binary file not shown.
BIN
snesfilter.dll
BIN
snesfilter.dll
Binary file not shown.
|
@ -1,6 +1,8 @@
|
|||
#ifndef NALL_PLATFORM_HPP
|
||||
#define NALL_PLATFORM_HPP
|
||||
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
//=========================
|
||||
//standard platform headers
|
||||
//=========================
|
||||
|
@ -50,7 +52,7 @@
|
|||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define putenv _putenv
|
||||
#define mkdir(n, m) mkdir(n)
|
||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
#define usleep(n) Sleep(n / 1000)
|
||||
|
|
|
@ -21,7 +21,7 @@ ifeq ($(platform),x)
|
|||
qtinc := `pkg-config --cflags $(qtlibs)`
|
||||
qtlib := `pkg-config --libs $(qtlibs)`
|
||||
else ifeq ($(platform),osx)
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers)
|
||||
|
||||
qtlib := -L/Library/Frameworks
|
||||
qtlib += $(foreach lib,$(qtlibs),-framework $(lib))
|
||||
|
|
|
@ -342,6 +342,7 @@ inline FileDialog::FileDialog() {
|
|||
fileSystemModel->setNameFilterDisables(false);
|
||||
|
||||
fileView = new FileView;
|
||||
fileView->setMinimumWidth(320);
|
||||
fileView->setModel(fileSystemModel);
|
||||
fileView->setIconSize(QSize(16, 16));
|
||||
browseLayout->addWidget(fileView);
|
||||
|
|
BIN
snesreader.dll
BIN
snesreader.dll
Binary file not shown.
|
@ -1,6 +1,8 @@
|
|||
#ifndef NALL_PLATFORM_HPP
|
||||
#define NALL_PLATFORM_HPP
|
||||
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
//=========================
|
||||
//standard platform headers
|
||||
//=========================
|
||||
|
@ -50,7 +52,7 @@
|
|||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define putenv _putenv
|
||||
#define mkdir(n, m) mkdir(n)
|
||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
#define usleep(n) Sleep(n / 1000)
|
||||
|
|
|
@ -21,7 +21,7 @@ ifeq ($(platform),x)
|
|||
qtinc := `pkg-config --cflags $(qtlibs)`
|
||||
qtlib := `pkg-config --libs $(qtlibs)`
|
||||
else ifeq ($(platform),osx)
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers)
|
||||
|
||||
qtlib := -L/Library/Frameworks
|
||||
qtlib += $(foreach lib,$(qtlibs),-framework $(lib))
|
||||
|
|
|
@ -342,6 +342,7 @@ inline FileDialog::FileDialog() {
|
|||
fileSystemModel->setNameFilterDisables(false);
|
||||
|
||||
fileView = new FileView;
|
||||
fileView->setMinimumWidth(320);
|
||||
fileView->setModel(fileSystemModel);
|
||||
fileView->setIconSize(QSize(16, 16));
|
||||
browseLayout->addWidget(fileView);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
static const char bsnesVersion[] = "059.06";
|
||||
static const char bsnesVersion[] = "060";
|
||||
static const char bsnesTitle[] = "bsnes";
|
||||
static const unsigned bsnesSerializerVersion = 4;
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ void MSU::enable() {
|
|||
audio.coprocessor_enable(true);
|
||||
audio.coprocessor_frequency(44100.0);
|
||||
|
||||
for(unsigned i = 0x2200; i <= 0x2207; i++) {
|
||||
for(unsigned i = 0x2000; i <= 0x2007; i++) {
|
||||
memory::mmio.map(i, *this);
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ void MSU::reset() {
|
|||
uint8 MSU::mmio_read(unsigned addr) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2200) {
|
||||
if(addr == 0x2000) {
|
||||
return (mmio.data_busy << 7)
|
||||
| (mmio.audio_busy << 6)
|
||||
| (mmio.audio_repeat << 5)
|
||||
|
@ -82,19 +82,19 @@ uint8 MSU::mmio_read(unsigned addr) {
|
|||
| (Revision << 0);
|
||||
}
|
||||
|
||||
if(addr == 0x2201) {
|
||||
if(addr == 0x2001) {
|
||||
if(mmio.data_busy) return 0x00;
|
||||
mmio.data_offset++;
|
||||
if(datafile.open()) return datafile.read();
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
if(addr == 0x2202) return 'S';
|
||||
if(addr == 0x2203) return '-';
|
||||
if(addr == 0x2204) return 'M';
|
||||
if(addr == 0x2205) return 'S';
|
||||
if(addr == 0x2206) return 'U';
|
||||
if(addr == 0x2207) return '0' + Revision;
|
||||
if(addr == 0x2002) return 'S';
|
||||
if(addr == 0x2003) return '-';
|
||||
if(addr == 0x2004) return 'M';
|
||||
if(addr == 0x2005) return 'S';
|
||||
if(addr == 0x2006) return 'U';
|
||||
if(addr == 0x2007) return '0' + Revision;
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
@ -102,29 +102,29 @@ uint8 MSU::mmio_read(unsigned addr) {
|
|||
void MSU::mmio_write(unsigned addr, uint8 data) {
|
||||
addr &= 0xffff;
|
||||
|
||||
if(addr == 0x2200) {
|
||||
if(addr == 0x2000) {
|
||||
mmio.data_offset = (mmio.data_offset & 0xffffff00) | (data << 0);
|
||||
}
|
||||
|
||||
if(addr == 0x2201) {
|
||||
if(addr == 0x2001) {
|
||||
mmio.data_offset = (mmio.data_offset & 0xffff00ff) | (data << 8);
|
||||
}
|
||||
|
||||
if(addr == 0x2202) {
|
||||
if(addr == 0x2002) {
|
||||
mmio.data_offset = (mmio.data_offset & 0xff00ffff) | (data << 16);
|
||||
}
|
||||
|
||||
if(addr == 0x2203) {
|
||||
if(addr == 0x2003) {
|
||||
mmio.data_offset = (mmio.data_offset & 0x00ffffff) | (data << 24);
|
||||
if(datafile.open()) datafile.seek(mmio.data_offset);
|
||||
mmio.data_busy = false;
|
||||
}
|
||||
|
||||
if(addr == 0x2204) {
|
||||
if(addr == 0x2004) {
|
||||
mmio.audio_track = (mmio.audio_track & 0xff00) | (data << 0);
|
||||
}
|
||||
|
||||
if(addr == 0x2205) {
|
||||
if(addr == 0x2005) {
|
||||
mmio.audio_track = (mmio.audio_track & 0x00ff) | (data << 8);
|
||||
if(audiofile.open()) audiofile.close();
|
||||
char track[16];
|
||||
|
@ -137,11 +137,11 @@ void MSU::mmio_write(unsigned addr, uint8 data) {
|
|||
mmio.audio_play = false;
|
||||
}
|
||||
|
||||
if(addr == 0x2206) {
|
||||
if(addr == 0x2006) {
|
||||
mmio.audio_volume = data;
|
||||
}
|
||||
|
||||
if(addr == 0x2207) {
|
||||
if(addr == 0x2007) {
|
||||
mmio.audio_repeat = data & 2;
|
||||
mmio.audio_play = data & 1;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ ifeq ($(platform),x)
|
|||
qtinc := `pkg-config --cflags $(qtlibs)`
|
||||
qtlib := `pkg-config --libs $(qtlibs)`
|
||||
else ifeq ($(platform),osx)
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers)
|
||||
|
||||
qtlib := -L/Library/Frameworks
|
||||
qtlib += $(foreach lib,$(qtlibs),-framework $(lib))
|
||||
|
|
|
@ -342,6 +342,7 @@ inline FileDialog::FileDialog() {
|
|||
fileSystemModel->setNameFilterDisables(false);
|
||||
|
||||
fileView = new FileView;
|
||||
fileView->setMinimumWidth(320);
|
||||
fileView->setModel(fileSystemModel);
|
||||
fileView->setIconSize(QSize(16, 16));
|
||||
browseLayout->addWidget(fileView);
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
#undef interface
|
||||
#define interface struct
|
||||
#include <d3d9.h>
|
||||
#include <d3dx9.h>
|
||||
#undef interface
|
||||
|
||||
#define D3DVERTEX (D3DFVF_XYZRHW | D3DFVF_TEX1)
|
||||
|
||||
typedef HRESULT (__stdcall *EffectProc)(LPDIRECT3DDEVICE9, LPCVOID, UINT, D3DXMACRO const*, LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL, LPD3DXEFFECT*, LPD3DXBUFFER*);
|
||||
typedef HRESULT (__stdcall *TextureProc)(LPDIRECT3DDEVICE9, LPCTSTR, LPDIRECT3DTEXTURE9*);
|
||||
|
||||
namespace ruby {
|
||||
|
||||
class pVideoD3D {
|
||||
|
@ -19,6 +23,9 @@ public:
|
|||
D3DCAPS9 d3dcaps;
|
||||
LPDIRECT3DTEXTURE9 texture;
|
||||
LPDIRECT3DSURFACE9 surface;
|
||||
LPD3DXEFFECT effect;
|
||||
string shaderSource;
|
||||
|
||||
bool lost;
|
||||
unsigned iwidth, iheight;
|
||||
|
||||
|
@ -36,7 +43,7 @@ public:
|
|||
|
||||
struct {
|
||||
bool dynamic; //device supports dynamic textures
|
||||
bool stretchrect; //device supports StretchRect
|
||||
bool shader; //device supports pixel shaders
|
||||
} caps;
|
||||
|
||||
struct {
|
||||
|
@ -57,6 +64,7 @@ public:
|
|||
if(name == Video::Handle) return true;
|
||||
if(name == Video::Synchronize) return true;
|
||||
if(name == Video::Filter) return true;
|
||||
if(name == Video::FragmentShader) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -84,6 +92,11 @@ public:
|
|||
return true;
|
||||
}
|
||||
|
||||
if(name == Video::FragmentShader) {
|
||||
set_fragment_shader(any_cast<const char*>(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -118,8 +131,7 @@ public:
|
|||
device->SetVertexShader(NULL);
|
||||
device->SetFVF(D3DVERTEX);
|
||||
|
||||
device->CreateVertexBuffer(sizeof(d3dvertex) * 4, flags.v_usage, D3DVERTEX,
|
||||
static_cast<D3DPOOL>(flags.v_pool), &vertex_buffer, NULL);
|
||||
device->CreateVertexBuffer(sizeof(d3dvertex) * 4, flags.v_usage, D3DVERTEX, (D3DPOOL)flags.v_pool, &vertex_buffer, NULL);
|
||||
iwidth = 0;
|
||||
iheight = 0;
|
||||
resize(settings.width = 256, settings.height = 256);
|
||||
|
@ -149,15 +161,8 @@ public:
|
|||
return;
|
||||
}
|
||||
|
||||
if(caps.stretchrect == true) {
|
||||
if(surface) surface->Release();
|
||||
device->CreateOffscreenPlainSurface(iwidth, iheight, D3DFMT_X8R8G8B8,
|
||||
D3DPOOL_DEFAULT, &surface, NULL);
|
||||
} else {
|
||||
if(texture) texture->Release();
|
||||
device->CreateTexture(iwidth, iheight, 1, flags.t_usage, D3DFMT_X8R8G8B8,
|
||||
static_cast<D3DPOOL>(flags.t_pool), &texture, NULL);
|
||||
}
|
||||
if(texture) texture->Release();
|
||||
device->CreateTexture(iwidth, iheight, 1, flags.t_usage, D3DFMT_X8R8G8B8, (D3DPOOL)flags.t_pool, &texture, NULL);
|
||||
}
|
||||
|
||||
void update_filter() {
|
||||
|
@ -217,14 +222,12 @@ public:
|
|||
void clear() {
|
||||
if(lost && !recover()) return;
|
||||
|
||||
if(caps.stretchrect == false) {
|
||||
texture->GetLevelDesc(0, &d3dsd);
|
||||
texture->GetSurfaceLevel(0, &surface);
|
||||
}
|
||||
texture->GetLevelDesc(0, &d3dsd);
|
||||
texture->GetSurfaceLevel(0, &surface);
|
||||
|
||||
if(surface) {
|
||||
device->ColorFill(surface, 0, D3DCOLOR_XRGB(0x00, 0x00, 0x00));
|
||||
if(caps.stretchrect == false) surface->Release();
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
//clear primary display and all backbuffers
|
||||
|
@ -241,10 +244,8 @@ public:
|
|||
resize(settings.width = width, settings.height = height);
|
||||
}
|
||||
|
||||
if(caps.stretchrect == false) {
|
||||
texture->GetLevelDesc(0, &d3dsd);
|
||||
texture->GetSurfaceLevel(0, &surface);
|
||||
}
|
||||
texture->GetLevelDesc(0, &d3dsd);
|
||||
texture->GetSurfaceLevel(0, &surface);
|
||||
|
||||
surface->LockRect(&d3dlr, 0, flags.lock);
|
||||
pitch = d3dlr.Pitch;
|
||||
|
@ -253,7 +254,7 @@ public:
|
|||
|
||||
void unlock() {
|
||||
surface->UnlockRect();
|
||||
if(caps.stretchrect == false) surface->Release();
|
||||
surface->Release();
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
|
@ -267,24 +268,54 @@ public:
|
|||
//failure to do so causes scaling issues on some video drivers.
|
||||
if(state.width != rd.right || state.height != rd.bottom) {
|
||||
init();
|
||||
set_fragment_shader(shaderSource);
|
||||
return;
|
||||
}
|
||||
|
||||
device->BeginScene();
|
||||
if(caps.shader && effect) {
|
||||
device->BeginScene();
|
||||
set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom);
|
||||
|
||||
if(caps.stretchrect == true) {
|
||||
LPDIRECT3DSURFACE9 temp;
|
||||
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &temp);
|
||||
device->StretchRect(surface, &rs, temp, 0, static_cast<D3DTEXTUREFILTERTYPE>(flags.filter));
|
||||
temp->Release();
|
||||
D3DXVECTOR4 rubyTextureSize;
|
||||
rubyTextureSize.x = iwidth;
|
||||
rubyTextureSize.y = iheight;
|
||||
rubyTextureSize.z = 1.0 / iheight;
|
||||
rubyTextureSize.w = 1.0 / iwidth;
|
||||
effect->SetVector("rubyTextureSize", &rubyTextureSize);
|
||||
|
||||
D3DXVECTOR4 rubyInputSize;
|
||||
rubyInputSize.x = settings.width;
|
||||
rubyInputSize.y = settings.height;
|
||||
rubyInputSize.z = 1.0 / settings.height;
|
||||
rubyInputSize.w = 1.0 / settings.width;
|
||||
effect->SetVector("rubyInputSize", &rubyInputSize);
|
||||
|
||||
D3DXVECTOR4 rubyOutputSize;
|
||||
rubyOutputSize.x = rd.right;
|
||||
rubyOutputSize.y = rd.bottom;
|
||||
rubyOutputSize.z = 1.0 / rd.bottom;
|
||||
rubyOutputSize.w = 1.0 / rd.right;
|
||||
effect->SetVector("rubyOutputSize", &rubyOutputSize);
|
||||
|
||||
UINT passes;
|
||||
effect->Begin(&passes, 0);
|
||||
effect->SetTexture("rubyTexture", texture);
|
||||
device->SetTexture(0, texture);
|
||||
for(unsigned pass = 0; pass < passes; pass++) {
|
||||
effect->BeginPass(pass);
|
||||
device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
effect->EndPass();
|
||||
}
|
||||
effect->End();
|
||||
device->EndScene();
|
||||
} else {
|
||||
device->BeginScene();
|
||||
set_vertex(0, 0, settings.width, settings.height, iwidth, iheight, 0, 0, rd.right, rd.bottom);
|
||||
device->SetTexture(0, texture);
|
||||
device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
||||
device->EndScene();
|
||||
}
|
||||
|
||||
device->EndScene();
|
||||
|
||||
if(settings.synchronize) {
|
||||
while(true) {
|
||||
D3DRASTER_STATUS status;
|
||||
|
@ -296,6 +327,42 @@ public:
|
|||
if(device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) lost = true;
|
||||
}
|
||||
|
||||
void set_fragment_shader(const char *source) {
|
||||
if(!caps.shader) return;
|
||||
|
||||
if(effect) {
|
||||
effect->Release();
|
||||
effect = NULL;
|
||||
}
|
||||
|
||||
if(!source || !*source) {
|
||||
shaderSource = "";
|
||||
return;
|
||||
}
|
||||
|
||||
shaderSource = source;
|
||||
|
||||
HMODULE d3dx;
|
||||
for(unsigned i = 0; i < 256; i++) {
|
||||
char t[256];
|
||||
sprintf(t, "d3dx9_%u.dll", i);
|
||||
d3dx = LoadLibrary(t);
|
||||
if(d3dx) break;
|
||||
}
|
||||
if(!d3dx) d3dx = LoadLibrary("d3dx9.dll");
|
||||
if(!d3dx) return;
|
||||
|
||||
EffectProc effectProc = (EffectProc)GetProcAddress(d3dx, "D3DXCreateEffect");
|
||||
TextureProc textureProc = (TextureProc)GetProcAddress(d3dx, "D3DXCreateTextureFromFileA");
|
||||
|
||||
LPD3DXBUFFER pBufferErrors = NULL;
|
||||
effectProc(device, shaderSource, lstrlen(source), NULL, NULL, NULL, NULL, &effect, &pBufferErrors);
|
||||
|
||||
D3DXHANDLE hTech;
|
||||
effect->FindNextValidTechnique(NULL, &hTech);
|
||||
effect->SetTechnique(hTech);
|
||||
}
|
||||
|
||||
bool init() {
|
||||
term();
|
||||
|
||||
|
@ -330,11 +397,7 @@ public:
|
|||
device->GetDeviceCaps(&d3dcaps);
|
||||
|
||||
caps.dynamic = bool(d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES);
|
||||
caps.stretchrect = (d3dcaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) &&
|
||||
(d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFPOINT) &&
|
||||
(d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFPOINT) &&
|
||||
(d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR) &&
|
||||
(d3dcaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR);
|
||||
caps.shader = d3dcaps.PixelShaderVersion > D3DPS_VERSION(1, 4);
|
||||
|
||||
if(caps.dynamic == true) {
|
||||
flags.t_usage = D3DUSAGE_DYNAMIC;
|
||||
|
@ -356,6 +419,7 @@ public:
|
|||
}
|
||||
|
||||
void release_resources() {
|
||||
if(effect) { effect->Release(); effect = 0; }
|
||||
if(vertex_buffer) { vertex_buffer->Release(); vertex_buffer = 0; }
|
||||
if(surface) { surface->Release(); surface = 0; }
|
||||
if(texture) { texture->Release(); texture = 0; }
|
||||
|
@ -368,6 +432,7 @@ public:
|
|||
}
|
||||
|
||||
pVideoD3D() {
|
||||
effect = 0;
|
||||
vertex_buffer = 0;
|
||||
surface = 0;
|
||||
texture = 0;
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
#include "application.moc"
|
||||
VideoDisplay display;
|
||||
Application application;
|
||||
|
||||
#include "init.cpp"
|
||||
|
||||
VideoDisplay::VideoDisplay() {
|
||||
outputWidth = 0;
|
||||
outputHeight = 0;
|
||||
|
||||
cropLeft = 0;
|
||||
cropTop = 0;
|
||||
cropRight = 0;
|
||||
cropBottom = 0;
|
||||
}
|
||||
|
||||
void Application::initPaths(const char *basename) {
|
||||
char temp[PATH_MAX];
|
||||
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
struct VideoDisplay {
|
||||
unsigned outputWidth;
|
||||
unsigned outputHeight;
|
||||
|
||||
unsigned cropLeft;
|
||||
unsigned cropTop;
|
||||
unsigned cropRight;
|
||||
unsigned cropBottom;
|
||||
|
||||
VideoDisplay();
|
||||
};
|
||||
|
||||
class Application : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -41,4 +53,5 @@ public slots:
|
|||
void run();
|
||||
};
|
||||
|
||||
extern VideoDisplay display;
|
||||
extern Application application;
|
||||
|
|
|
@ -93,8 +93,8 @@ void Application::init() {
|
|||
config().system.crashedOnLastRun = false;
|
||||
config().save(configFilename);
|
||||
|
||||
//no sense showing unusable options ...
|
||||
pixelShaderWindow->setVisible(video.cap(Video::FragmentShader) || video.cap(Video::VertexShader));
|
||||
//hide pixel shader settings if driver does not support them
|
||||
videoSettingsWindow->synchronizePixelShaderSettings();
|
||||
|
||||
utility.resizeMainWindow();
|
||||
utility.updateAvSync();
|
||||
|
|
|
@ -77,9 +77,17 @@ FileBrowser::FileBrowser() {
|
|||
|
||||
string FileBrowser::resolveFilename(const string &path) {
|
||||
if(QDir(path).exists()) {
|
||||
if(striend(path, ".sfc") == false) return "";
|
||||
string filter;
|
||||
if(striend(path, ".sfc")) filter = "*.sfc";
|
||||
if(striend(path, ".bs" )) filter = "*.bs";
|
||||
if(striend(path, ".st" )) filter = "*.st";
|
||||
if(striend(path, ".gb" )) filter = "*.gb";
|
||||
if(striend(path, ".sgb")) filter = "*.sgb";
|
||||
if(striend(path, ".gbc")) filter = "*.gbc";
|
||||
if(filter == "") return "";
|
||||
|
||||
QDir directory(path);
|
||||
directory.setNameFilters(QStringList() << "*.sfc");
|
||||
directory.setNameFilters(QStringList() << filter);
|
||||
QStringList list = directory.entryList(QDir::Files | QDir::NoDotAndDotDot);
|
||||
if(list.count() == 1) return string() << path << "/" << list[0].toUtf8().constData();
|
||||
return "";
|
||||
|
@ -93,31 +101,34 @@ void FileBrowser::onChangeCartridge(const string &path) {
|
|||
if(QDir(path).exists()) filename = resolveFilename(path);
|
||||
else filename = path;
|
||||
|
||||
if(file::exists(filename) && striend(filename, ".sfc")) {
|
||||
Cartridge::Information info;
|
||||
if(cartridge.information(filename, info)) {
|
||||
string info;
|
||||
string image = string() << nall::basename(filename) << ".png";
|
||||
string patch = string() << nall::basename(filename) << ".ups";
|
||||
|
||||
if(file::exists(filename)) {
|
||||
if(striend(filename, ".sfc")) {
|
||||
Cartridge::Information cartinfo;
|
||||
if(cartridge.information(filename, cartinfo)) {
|
||||
info << "<small><table>";
|
||||
info << "<tr><td><b>Title: </b></td><td>" << cartinfo.name << "</td></tr>";
|
||||
info << "<tr><td><b>Region: </b></td><td>" << cartinfo.region << "</td></tr>";
|
||||
info << "<tr><td><b>ROM: </b></td><td>" << cartinfo.romSize * 8 / 1024 / 1024 << "mbit</td></tr>";
|
||||
info << "<tr><td><b>RAM: </b></td><td>";
|
||||
cartinfo.ramSize ? info << cartinfo.ramSize * 8 / 1024 << "kbit</td></tr>" : info << "None</td></tr>";
|
||||
info << "</table></small>";
|
||||
}
|
||||
} else if(striend(filename, ".st")) {
|
||||
unsigned size = file::size(filename);
|
||||
string text;
|
||||
text << "<small><table>";
|
||||
text << "<tr><td><b>Title: </b></td><td>" << info.name << "</td></tr>";
|
||||
text << "<tr><td><b>Region: </b></td><td>" << info.region << "</td></tr>";
|
||||
text << "<tr><td><b>ROM: </b></td><td>" << info.romSize * 8 / 1024 / 1024 << "mbit</td></tr>";
|
||||
text << "<tr><td><b>RAM: </b></td><td>";
|
||||
info.ramSize ? text << info.ramSize * 8 / 1024 << "kbit</td></tr>" : text << "None</td></tr>";
|
||||
text << "</table></small>";
|
||||
previewInfo->setText(text);
|
||||
info << "<small><table>";
|
||||
info << "<tr><td><b>ROM: </b></td><td>" << size * 8 / 1024 / 1024 << "mbit</td></tr>";
|
||||
info << "</table></small>";
|
||||
}
|
||||
|
||||
string image = string() << nall::basename(filename) << ".png";
|
||||
previewImage->setStyleSheet(string() << "background: url(" << image << ") top left no-repeat;");
|
||||
|
||||
string patch = string() << nall::basename(filename) << ".ups";
|
||||
previewApplyPatch->setVisible(file::exists(patch));
|
||||
} else {
|
||||
previewInfo->setText("");
|
||||
previewImage->setStyleSheet("background: transparent;");
|
||||
previewApplyPatch->hide();
|
||||
}
|
||||
|
||||
if(info == "") info = "<small><font color='#808080'>No preview available</font></small>";
|
||||
previewInfo->setText(info);
|
||||
previewImage->setStyleSheet(string() << "background: url(" << image << ") center left no-repeat;");
|
||||
previewApplyPatch->setVisible(file::exists(patch));
|
||||
}
|
||||
|
||||
void FileBrowser::onAcceptCartridge(const string &path) {
|
||||
|
@ -134,31 +145,23 @@ void FileBrowser::onAcceptCartridge(const string &path) {
|
|||
|
||||
if(cartridgeMode == LoadDirect) {
|
||||
config().path.current.filter = filterBox->currentIndex();
|
||||
|
||||
string filter = filterBox->currentText().toUtf8().constData();
|
||||
if(strbegin(filter, "SNES cartridges")) {
|
||||
cartridge.loadNormal(filename);
|
||||
} else if(strbegin(filter, "BS-X cartridges")) {
|
||||
if(config().path.bsx == "") {
|
||||
loaderWindow->loadBsxCartridge("", filename);
|
||||
} else {
|
||||
cartridge.loadBsx(config().path.bsx, filename);
|
||||
}
|
||||
} else if(strbegin(filter, "Sufami Turbo cartridges")) {
|
||||
if(config().path.st == "") {
|
||||
loaderWindow->loadSufamiTurboCartridge("", filename, "");
|
||||
} else {
|
||||
cartridge.loadSufamiTurbo(config().path.st, filename, "");
|
||||
}
|
||||
} else if(strbegin(filter, "Game Boy cartridges")) {
|
||||
if(config().path.sgb == "") {
|
||||
loaderWindow->loadSuperGameBoyCartridge("", filename);
|
||||
} else {
|
||||
cartridge.loadSuperGameBoy(config().path.sgb, filename);
|
||||
}
|
||||
} else {
|
||||
cartridge.loadNormal(filename);
|
||||
}
|
||||
|
||||
if(0);
|
||||
//file extension detection
|
||||
else if(striend(filename, ".sfc")) acceptNormal(filename);
|
||||
else if(striend(filename, ".bs")) acceptBsx(filename);
|
||||
else if(striend(filename, ".st")) acceptSufamiTurbo(filename);
|
||||
else if(striend(filename, ".gb")) acceptSuperGameBoy(filename);
|
||||
else if(striend(filename, ".sgb")) acceptSuperGameBoy(filename);
|
||||
else if(striend(filename, ".gbc")) acceptSuperGameBoy(filename);
|
||||
//filter detection
|
||||
else if(strbegin(filter, "SNES cartridges")) acceptNormal(filename);
|
||||
else if(strbegin(filter, "BS-X cartridges")) acceptBsx(filename);
|
||||
else if(strbegin(filter, "Sufami Turbo cartridges")) acceptSufamiTurbo(filename);
|
||||
else if(strbegin(filter, "Game Boy cartridges")) acceptSuperGameBoy(filename);
|
||||
//fallback behavior
|
||||
else acceptNormal(filename);
|
||||
} else if(cartridgeMode == LoadBase) {
|
||||
loaderWindow->selectBaseCartridge(filename);
|
||||
} else if(cartridgeMode == LoadSlot1) {
|
||||
|
@ -168,3 +171,31 @@ void FileBrowser::onAcceptCartridge(const string &path) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::acceptNormal(const string &filename) {
|
||||
cartridge.loadNormal(filename);
|
||||
}
|
||||
|
||||
void FileBrowser::acceptBsx(const string &filename) {
|
||||
if(config().path.bsx == "") {
|
||||
loaderWindow->loadBsxCartridge("", filename);
|
||||
} else {
|
||||
cartridge.loadBsx(config().path.bsx, filename);
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::acceptSufamiTurbo(const string &filename) {
|
||||
if(config().path.st == "") {
|
||||
loaderWindow->loadSufamiTurboCartridge("", filename, "");
|
||||
} else {
|
||||
cartridge.loadSufamiTurbo(config().path.st, filename, "");
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::acceptSuperGameBoy(const string &filename) {
|
||||
if(config().path.sgb == "") {
|
||||
loaderWindow->loadSuperGameBoyCartridge("", filename);
|
||||
} else {
|
||||
cartridge.loadSuperGameBoy(config().path.sgb, filename);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@ private:
|
|||
string resolveFilename(const string&);
|
||||
void onChangeCartridge(const string&);
|
||||
void onAcceptCartridge(const string&);
|
||||
|
||||
void acceptNormal(const string &filename);
|
||||
void acceptBsx(const string &filename);
|
||||
void acceptSufamiTurbo(const string &filename);
|
||||
void acceptSuperGameBoy(const string &filename);
|
||||
};
|
||||
|
||||
extern FileBrowser *fileBrowser;
|
||||
|
|
|
@ -86,6 +86,12 @@ MainWindow::MainWindow() {
|
|||
|
||||
settings_videoMode->addAction(settings_videoMode_5x = new RadioAction("Scale &5x", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_max_normal = new RadioAction("Scale Max - &Normal", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_max_wide = new RadioAction("Scale Max - &Wide", 0));
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_max_wideZoom = new RadioAction("Scale Max - Wide &Zoom", 0));
|
||||
|
||||
settings_videoMode->addSeparator();
|
||||
|
||||
settings_videoMode->addAction(settings_videoMode_correctAspectRatio = new CheckAction("Correct &Aspect Ratio", 0));
|
||||
|
@ -267,6 +273,9 @@ MainWindow::MainWindow() {
|
|||
connect(settings_videoMode_3x, SIGNAL(triggered()), this, SLOT(setVideoMode3x()));
|
||||
connect(settings_videoMode_4x, SIGNAL(triggered()), this, SLOT(setVideoMode4x()));
|
||||
connect(settings_videoMode_5x, SIGNAL(triggered()), this, SLOT(setVideoMode5x()));
|
||||
connect(settings_videoMode_max_normal, SIGNAL(triggered()), this, SLOT(setVideoModeMaxNormal()));
|
||||
connect(settings_videoMode_max_wide, SIGNAL(triggered()), this, SLOT(setVideoModeMaxWide()));
|
||||
connect(settings_videoMode_max_wideZoom, SIGNAL(triggered()), this, SLOT(setVideoModeMaxWideZoom()));
|
||||
connect(settings_videoMode_correctAspectRatio, SIGNAL(triggered()), this, SLOT(toggleAspectCorrection()));
|
||||
connect(settings_videoMode_ntsc, SIGNAL(triggered()), this, SLOT(setVideoNtsc()));
|
||||
connect(settings_videoMode_pal, SIGNAL(triggered()), this, SLOT(setVideoPal()));
|
||||
|
@ -304,18 +313,18 @@ MainWindow::MainWindow() {
|
|||
|
||||
void MainWindow::syncUi() {
|
||||
system_power->setEnabled(SNES::cartridge.loaded());
|
||||
system_power->setChecked (application.power == true);
|
||||
system_power->setChecked(application.power == true);
|
||||
system_power->setEnabled(SNES::cartridge.loaded());
|
||||
system_reset->setEnabled(SNES::cartridge.loaded() && application.power);
|
||||
|
||||
system_port1_none->setChecked (config().input.port1 == ControllerPort1::None);
|
||||
system_port1_gamepad->setChecked (config().input.port1 == ControllerPort1::Gamepad);
|
||||
system_port1_gamepad->setChecked (config().input.port1 == ControllerPort1::Gamepad);
|
||||
system_port1_asciipad->setChecked (config().input.port1 == ControllerPort1::Asciipad);
|
||||
system_port1_multitap->setChecked (config().input.port1 == ControllerPort1::Multitap);
|
||||
system_port1_mouse->setChecked (config().input.port1 == ControllerPort1::Mouse);
|
||||
|
||||
system_port2_none->setChecked (config().input.port2 == ControllerPort2::None);
|
||||
system_port2_gamepad->setChecked (config().input.port2 == ControllerPort2::Gamepad);
|
||||
system_port2_gamepad->setChecked (config().input.port2 == ControllerPort2::Gamepad);
|
||||
system_port2_asciipad->setChecked (config().input.port2 == ControllerPort2::Asciipad);
|
||||
system_port2_multitap->setChecked (config().input.port2 == ControllerPort2::Multitap);
|
||||
system_port2_mouse->setChecked (config().input.port2 == ControllerPort2::Mouse);
|
||||
|
@ -323,11 +332,18 @@ void MainWindow::syncUi() {
|
|||
system_port2_justifier->setChecked (config().input.port2 == ControllerPort2::Justifier);
|
||||
system_port2_justifiers->setChecked(config().input.port2 == ControllerPort2::Justifiers);
|
||||
|
||||
settings_videoMode_1x->setChecked(config().video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked(config().video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked(config().video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked(config().video.context->multiplier == 4);
|
||||
settings_videoMode_5x->setChecked(config().video.context->multiplier == 5);
|
||||
settings_videoMode_1x->setChecked (config().video.context->multiplier == 1);
|
||||
settings_videoMode_2x->setChecked (config().video.context->multiplier == 2);
|
||||
settings_videoMode_3x->setChecked (config().video.context->multiplier == 3);
|
||||
settings_videoMode_4x->setChecked (config().video.context->multiplier == 4);
|
||||
settings_videoMode_5x->setChecked (config().video.context->multiplier == 5);
|
||||
settings_videoMode_max_normal->setChecked(config().video.context->multiplier == 6);
|
||||
settings_videoMode_max_wide->setChecked (config().video.context->multiplier == 7);
|
||||
settings_videoMode_max_wideZoom->setChecked (config().video.context->multiplier == 8);
|
||||
|
||||
settings_videoMode_max_normal->setVisible(config().video.isFullscreen == true);
|
||||
settings_videoMode_max_wide->setVisible (config().video.isFullscreen == true);
|
||||
settings_videoMode_max_wideZoom->setVisible (config().video.isFullscreen == true);
|
||||
|
||||
settings_videoMode_correctAspectRatio->setChecked(config().video.context->correctAspectRatio);
|
||||
settings_videoMode_ntsc->setChecked(config().video.context->region == 0);
|
||||
|
@ -485,11 +501,14 @@ void MainWindow::quit() {
|
|||
application.terminate = true;
|
||||
}
|
||||
|
||||
void MainWindow::setVideoMode1x() { utility.setScale(1); }
|
||||
void MainWindow::setVideoMode2x() { utility.setScale(2); }
|
||||
void MainWindow::setVideoMode3x() { utility.setScale(3); }
|
||||
void MainWindow::setVideoMode4x() { utility.setScale(4); }
|
||||
void MainWindow::setVideoMode5x() { utility.setScale(5); }
|
||||
void MainWindow::setVideoMode1x() { utility.setScale(1); }
|
||||
void MainWindow::setVideoMode2x() { utility.setScale(2); }
|
||||
void MainWindow::setVideoMode3x() { utility.setScale(3); }
|
||||
void MainWindow::setVideoMode4x() { utility.setScale(4); }
|
||||
void MainWindow::setVideoMode5x() { utility.setScale(5); }
|
||||
void MainWindow::setVideoModeMaxNormal() { utility.setScale(6); }
|
||||
void MainWindow::setVideoModeMaxWide() { utility.setScale(7); }
|
||||
void MainWindow::setVideoModeMaxWideZoom() { utility.setScale(8); }
|
||||
|
||||
void MainWindow::toggleAspectCorrection() { utility.toggleAspectCorrection(); }
|
||||
|
||||
|
|
|
@ -52,6 +52,9 @@ public:
|
|||
RadioAction *settings_videoMode_3x;
|
||||
RadioAction *settings_videoMode_4x;
|
||||
RadioAction *settings_videoMode_5x;
|
||||
RadioAction *settings_videoMode_max_normal;
|
||||
RadioAction *settings_videoMode_max_wide;
|
||||
RadioAction *settings_videoMode_max_wideZoom;
|
||||
CheckAction *settings_videoMode_correctAspectRatio;
|
||||
RadioAction *settings_videoMode_ntsc;
|
||||
RadioAction *settings_videoMode_pal;
|
||||
|
@ -123,6 +126,9 @@ public slots:
|
|||
void setVideoMode3x();
|
||||
void setVideoMode4x();
|
||||
void setVideoMode5x();
|
||||
void setVideoModeMaxNormal();
|
||||
void setVideoModeMaxWide();
|
||||
void setVideoModeMaxWideZoom();
|
||||
void toggleAspectCorrection();
|
||||
void setVideoNtsc();
|
||||
void setVideoPal();
|
||||
|
|
|
@ -88,6 +88,11 @@ Configuration::Configuration() {
|
|||
attach(video.ntscAspectRatio = 54.0 / 47.0, "video.ntscAspectRatio", "NTSC aspect ratio (x / y)");
|
||||
attach(video.palAspectRatio = 32.0 / 23.0, "video.palAspectRatio", "PAL aspect ratio (x / y)");
|
||||
|
||||
attach(video.cropLeft = 0, "video.cropLeft");
|
||||
attach(video.cropTop = 0, "video.cropTop");
|
||||
attach(video.cropRight = 0, "video.cropRight");
|
||||
attach(video.cropBottom = 0, "video.cropBottom");
|
||||
|
||||
attach(video.windowed.correctAspectRatio = true, "video.windowed.correctAspectRatio");
|
||||
attach(video.windowed.multiplier = 2, "video.windowed.multiplier");
|
||||
attach(video.windowed.region = 0, "video.windowed.region");
|
||||
|
|
|
@ -43,6 +43,11 @@ public:
|
|||
bool enableGammaRamp;
|
||||
double ntscAspectRatio, palAspectRatio;
|
||||
|
||||
unsigned cropLeft;
|
||||
unsigned cropTop;
|
||||
unsigned cropRight;
|
||||
unsigned cropBottom;
|
||||
|
||||
struct Context {
|
||||
bool correctAspectRatio;
|
||||
unsigned multiplier, region;
|
||||
|
|
|
@ -112,4 +112,37 @@ struct Scale5x : HotkeyInput {
|
|||
}
|
||||
} scale5x;
|
||||
|
||||
struct ScaleMaxNormal : HotkeyInput {
|
||||
void pressed() {
|
||||
if(config().video.isFullscreen) utility.setScale(6);
|
||||
}
|
||||
|
||||
ScaleMaxNormal() : HotkeyInput("Scale Max - Normal", "input.userInterface.videoSettings.scaleMaxNormal") {
|
||||
name = "Shift+KB0::Num6";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scaleMaxNormal;
|
||||
|
||||
struct ScaleMaxFill : HotkeyInput {
|
||||
void pressed() {
|
||||
if(config().video.isFullscreen) utility.setScale(7);
|
||||
}
|
||||
|
||||
ScaleMaxFill() : HotkeyInput("Scale Max - Fill", "input.userInterface.videoSettings.scaleMaxFill") {
|
||||
name = "Shift+KB0::Num7";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scaleMaxFill;
|
||||
|
||||
struct ScaleMaxSmart : HotkeyInput {
|
||||
void pressed() {
|
||||
if(config().video.isFullscreen) utility.setScale(8);
|
||||
}
|
||||
|
||||
ScaleMaxSmart() : HotkeyInput("Scale Max - Smart", "input.userInterface.videoSettings.scaleMaxSmart") {
|
||||
name = "Shift+KB0::Num8";
|
||||
userInterfaceVideoSettings.attach(this);
|
||||
}
|
||||
} scaleMaxSmart;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
Interface interface;
|
||||
|
||||
void Interface::video_refresh(uint16_t *data, unsigned pitch, unsigned *line, unsigned width, unsigned height) {
|
||||
//scale display.crop* values from percentage-based (0-100%) to exact pixel sizes (width, height)
|
||||
unsigned cropLeft = (double)display.cropLeft / 100.0 * width;
|
||||
unsigned cropTop = (double)display.cropTop / 100.0 * height;
|
||||
unsigned cropRight = (double)display.cropRight / 100.0 * width;
|
||||
unsigned cropBottom = (double)display.cropBottom / 100.0 * height;
|
||||
|
||||
width -= (cropLeft + cropRight);
|
||||
height -= (cropTop + cropBottom);
|
||||
|
||||
uint32_t *output;
|
||||
unsigned outwidth, outheight, outpitch;
|
||||
filter.size(outwidth, outheight, width, height);
|
||||
|
||||
if(video.lock(output, outpitch, outwidth, outheight) == true) {
|
||||
filter.render(output, outpitch, data, pitch, line, width, height);
|
||||
data += cropTop * (pitch >> 1) + cropLeft;
|
||||
filter.render(output, outpitch, data, pitch, line + cropTop, width, height);
|
||||
video.unlock();
|
||||
video.refresh();
|
||||
if(saveScreenshot == true) captureScreenshot(output, outpitch, outwidth, outheight);
|
||||
|
|
|
@ -193,21 +193,21 @@ void Filter::render(
|
|||
outpitch >>= 2;
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
if(width == 512 && line[y] == 256) {
|
||||
for(unsigned x = 0; x < 256; x++) {
|
||||
uint16_t p = *input++;
|
||||
*output++ = colortable[p];
|
||||
*output++ = colortable[p];
|
||||
const uint16_t *in = input + y * pitch;
|
||||
uint32_t *out = output + y * outpitch;
|
||||
|
||||
if(width > 256 && line[y] <= 256) {
|
||||
for(unsigned x = 0; x < line[y]; x++) {
|
||||
uint16_t p = *in++;
|
||||
*out++ = colortable[p];
|
||||
*out++ = colortable[p];
|
||||
}
|
||||
input += 256;
|
||||
} else {
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint16_t p = *input++;
|
||||
*output++ = colortable[p];
|
||||
uint16_t p = *in++;
|
||||
*out++ = colortable[p];
|
||||
}
|
||||
}
|
||||
input += pitch - width;
|
||||
output += outpitch - width;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,91 +0,0 @@
|
|||
#include "pixelshader.moc"
|
||||
PixelShaderWindow *pixelShaderWindow;
|
||||
|
||||
PixelShaderWindow::PixelShaderWindow() {
|
||||
layout = new QVBoxLayout;
|
||||
layout->setMargin(0);
|
||||
layout->setSpacing(Style::WidgetSpacing);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
gridLayout = new QGridLayout;
|
||||
gridLayout->setVerticalSpacing(0);
|
||||
layout->addLayout(gridLayout);
|
||||
|
||||
fragmentLabel = new QLabel("Fragment shader:");
|
||||
gridLayout->addWidget(fragmentLabel, 0, 0, 1, 3);
|
||||
|
||||
fragmentPath = new QLineEdit;
|
||||
gridLayout->addWidget(fragmentPath, 1, 0);
|
||||
|
||||
fragmentSelect = new QPushButton("Select ...");
|
||||
gridLayout->addWidget(fragmentSelect, 1, 1);
|
||||
|
||||
fragmentDefault = new QPushButton("Default");
|
||||
gridLayout->addWidget(fragmentDefault, 1, 2);
|
||||
|
||||
vertexLabel = new QLabel("Vertex shader:");
|
||||
gridLayout->addWidget(vertexLabel, 2, 0, 1, 3);
|
||||
|
||||
vertexPath = new QLineEdit;
|
||||
gridLayout->addWidget(vertexPath, 3, 0);
|
||||
|
||||
vertexSelect = new QPushButton("Select ...");
|
||||
gridLayout->addWidget(vertexSelect, 3, 1);
|
||||
|
||||
vertexDefault = new QPushButton("Default");
|
||||
gridLayout->addWidget(vertexDefault, 3, 2);
|
||||
|
||||
synchronize();
|
||||
|
||||
connect(fragmentSelect, SIGNAL(released()), this, SLOT(selectFragmentShader()));
|
||||
connect(vertexSelect, SIGNAL(released()), this, SLOT(selectVertexShader()));
|
||||
connect(fragmentDefault, SIGNAL(released()), this, SLOT(defaultFragmentShader()));
|
||||
connect(vertexDefault, SIGNAL(released()), this, SLOT(defaultVertexShader()));
|
||||
}
|
||||
|
||||
void PixelShaderWindow::synchronize() {
|
||||
fragmentPath->setText(config().path.fragmentShader);
|
||||
vertexPath->setText(config().path.vertexShader);
|
||||
}
|
||||
|
||||
void PixelShaderWindow::selectFragmentShader() {
|
||||
fileBrowser->onChange = (void*)0;
|
||||
fileBrowser->onActivate = bind(&PixelShaderWindow::assignFragmentShader, this);
|
||||
fileBrowser->onAccept = bind(&PixelShaderWindow::assignFragmentShader, this);
|
||||
fileBrowser->setWindowTitle("Select Fragment Shader");
|
||||
fileBrowser->setPath(config().path.current.shader);
|
||||
fileBrowser->setNameFilters("All files (*)");
|
||||
fileBrowser->showLoad();
|
||||
}
|
||||
|
||||
void PixelShaderWindow::selectVertexShader() {
|
||||
fileBrowser->onChange = (void*)0;
|
||||
fileBrowser->onActivate = bind(&PixelShaderWindow::assignVertexShader, this);
|
||||
fileBrowser->onAccept = bind(&PixelShaderWindow::assignVertexShader, this);
|
||||
fileBrowser->setWindowTitle("Select Vertex Shader");
|
||||
fileBrowser->setPath(config().path.current.shader);
|
||||
fileBrowser->setNameFilters("All files (*)");
|
||||
fileBrowser->showLoad();
|
||||
}
|
||||
|
||||
void PixelShaderWindow::defaultFragmentShader() { assignFragmentShader(""); }
|
||||
void PixelShaderWindow::defaultVertexShader() { assignVertexShader(""); }
|
||||
|
||||
void PixelShaderWindow::assignFragmentShader(const string &filename) {
|
||||
if(filename == "" || QDir(filename).exists() == false) {
|
||||
config().path.fragmentShader = filename;
|
||||
if(filename != "") config().path.current.shader = dir(filename);
|
||||
synchronize();
|
||||
utility.updatePixelShader();
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderWindow::assignVertexShader(const string &filename) {
|
||||
if(filename == "" || QDir(filename).exists() == false) {
|
||||
config().path.vertexShader = filename;
|
||||
if(filename != "") config().path.current.shader = dir(filename);
|
||||
synchronize();
|
||||
utility.updatePixelShader();
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
class PixelShaderWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QVBoxLayout *layout;
|
||||
QGridLayout *gridLayout;
|
||||
QLabel *fragmentLabel;
|
||||
QLineEdit *fragmentPath;
|
||||
QPushButton *fragmentSelect;
|
||||
QPushButton *fragmentDefault;
|
||||
QLabel *vertexLabel;
|
||||
QLineEdit *vertexPath;
|
||||
QPushButton *vertexSelect;
|
||||
QPushButton *vertexDefault;
|
||||
|
||||
void synchronize();
|
||||
PixelShaderWindow();
|
||||
|
||||
public slots:
|
||||
void selectFragmentShader();
|
||||
void selectVertexShader();
|
||||
void defaultFragmentShader();
|
||||
void defaultVertexShader();
|
||||
|
||||
void assignFragmentShader(const string&);
|
||||
void assignVertexShader(const string&);
|
||||
};
|
||||
|
||||
extern PixelShaderWindow *pixelShaderWindow;
|
|
@ -1,6 +1,5 @@
|
|||
#include "../ui-base.hpp"
|
||||
|
||||
#include "pixelshader.cpp"
|
||||
#include "video.cpp"
|
||||
#include "audio.cpp"
|
||||
#include "input.cpp"
|
||||
|
@ -28,11 +27,36 @@ SettingsWindow::SettingsWindow() {
|
|||
pathSettingsWindow = new PathSettingsWindow;
|
||||
advancedSettingsWindow = new AdvancedSettingsWindow;
|
||||
|
||||
videoArea = new QScrollArea;
|
||||
videoArea->setWidget(videoSettingsWindow);
|
||||
videoArea->setFrameStyle(0);
|
||||
videoArea->setWidgetResizable(true);
|
||||
|
||||
audioArea = new QScrollArea;
|
||||
audioArea->setWidget(audioSettingsWindow);
|
||||
audioArea->setFrameStyle(0);
|
||||
audioArea->setWidgetResizable(true);
|
||||
|
||||
inputArea = new QScrollArea;
|
||||
inputArea->setWidget(inputSettingsWindow);
|
||||
inputArea->setFrameStyle(0);
|
||||
inputArea->setWidgetResizable(true);
|
||||
|
||||
pathArea = new QScrollArea;
|
||||
pathArea->setWidget(pathSettingsWindow);
|
||||
pathArea->setFrameStyle(0);
|
||||
pathArea->setWidgetResizable(true);
|
||||
|
||||
advancedArea = new QScrollArea;
|
||||
advancedArea->setWidget(advancedSettingsWindow);
|
||||
advancedArea->setFrameStyle(0);
|
||||
advancedArea->setWidgetResizable(true);
|
||||
|
||||
tab = new QTabWidget;
|
||||
tab->addTab(videoSettingsWindow, QIcon(":/16x16/video-display.png"), "Video");
|
||||
tab->addTab(audioSettingsWindow, QIcon(":/16x16/audio-volume-high.png"), "Audio");
|
||||
tab->addTab(inputSettingsWindow, QIcon(":/16x16/input-gaming.png"), "Input");
|
||||
tab->addTab(pathSettingsWindow, QIcon(":/16x16/folder.png"), "Paths");
|
||||
tab->addTab(advancedSettingsWindow, QIcon(":/16x16/preferences-system.png"), "Advanced");
|
||||
tab->addTab(videoArea, QIcon(":/16x16/video-display.png"), "Video");
|
||||
tab->addTab(audioArea, QIcon(":/16x16/audio-volume-high.png"), "Audio");
|
||||
tab->addTab(inputArea, QIcon(":/16x16/input-gaming.png"), "Input");
|
||||
tab->addTab(pathArea, QIcon(":/16x16/folder.png"), "Paths");
|
||||
tab->addTab(advancedArea, QIcon(":/16x16/preferences-system.png"), "Advanced");
|
||||
layout->addWidget(tab);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,11 @@ class SettingsWindow : public Window {
|
|||
public:
|
||||
QVBoxLayout *layout;
|
||||
QTabWidget *tab;
|
||||
QScrollArea *videoArea;
|
||||
QScrollArea *audioArea;
|
||||
QScrollArea *inputArea;
|
||||
QScrollArea *pathArea;
|
||||
QScrollArea *advancedArea;
|
||||
|
||||
SettingsWindow();
|
||||
|
||||
|
|
|
@ -8,58 +8,61 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
|||
layout->setAlignment(Qt::AlignTop);
|
||||
setLayout(layout);
|
||||
|
||||
sliders = new QGridLayout;
|
||||
layout->addLayout(sliders);
|
||||
colorLabel = new QLabel("<b>Color Adjustment</b>");
|
||||
layout->addWidget(colorLabel);
|
||||
|
||||
colorLayout = new QGridLayout;
|
||||
layout->addLayout(colorLayout);
|
||||
|
||||
contrastLabel = new QLabel("Contrast adjust:");
|
||||
sliders->addWidget(contrastLabel, 0, 0);
|
||||
colorLayout->addWidget(contrastLabel, 0, 0);
|
||||
|
||||
contrastValue = new QLabel;
|
||||
contrastValue->setAlignment(Qt::AlignHCenter);
|
||||
contrastValue->setMinimumWidth(contrastValue->fontMetrics().width("+100%"));
|
||||
sliders->addWidget(contrastValue, 0, 1);
|
||||
colorLayout->addWidget(contrastValue, 0, 1);
|
||||
|
||||
contrast = new QSlider(Qt::Horizontal);
|
||||
contrast->setMinimum(-95);
|
||||
contrast->setMaximum(+95);
|
||||
sliders->addWidget(contrast, 0, 2);
|
||||
contrastSlider = new QSlider(Qt::Horizontal);
|
||||
contrastSlider->setMinimum(-95);
|
||||
contrastSlider->setMaximum(+95);
|
||||
colorLayout->addWidget(contrastSlider, 0, 2);
|
||||
|
||||
brightnessLabel = new QLabel("Brightness adjust:");
|
||||
sliders->addWidget(brightnessLabel, 1, 0);
|
||||
colorLayout->addWidget(brightnessLabel, 1, 0);
|
||||
|
||||
brightnessValue = new QLabel;
|
||||
brightnessValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(brightnessValue, 1, 1);
|
||||
colorLayout->addWidget(brightnessValue, 1, 1);
|
||||
|
||||
brightness = new QSlider(Qt::Horizontal);
|
||||
brightness->setMinimum(-95);
|
||||
brightness->setMaximum(+95);
|
||||
sliders->addWidget(brightness, 1, 2);
|
||||
brightnessSlider = new QSlider(Qt::Horizontal);
|
||||
brightnessSlider->setMinimum(-95);
|
||||
brightnessSlider->setMaximum(+95);
|
||||
colorLayout->addWidget(brightnessSlider, 1, 2);
|
||||
|
||||
gammaLabel = new QLabel("Gamma adjust:");
|
||||
sliders->addWidget(gammaLabel, 2, 0);
|
||||
colorLayout->addWidget(gammaLabel, 2, 0);
|
||||
|
||||
gammaValue = new QLabel;
|
||||
gammaValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(gammaValue, 2, 1);
|
||||
colorLayout->addWidget(gammaValue, 2, 1);
|
||||
|
||||
gamma = new QSlider(Qt::Horizontal);
|
||||
gamma->setMinimum(-95);
|
||||
gamma->setMaximum(+95);
|
||||
sliders->addWidget(gamma, 2, 2);
|
||||
gammaSlider = new QSlider(Qt::Horizontal);
|
||||
gammaSlider->setMinimum(-95);
|
||||
gammaSlider->setMaximum(+95);
|
||||
colorLayout->addWidget(gammaSlider, 2, 2);
|
||||
|
||||
scanlineLabel = new QLabel("Scanline adjust:");
|
||||
sliders->addWidget(scanlineLabel, 3, 0);
|
||||
colorLayout->addWidget(scanlineLabel, 3, 0);
|
||||
|
||||
scanlineValue = new QLabel;
|
||||
scanlineValue->setAlignment(Qt::AlignHCenter);
|
||||
sliders->addWidget(scanlineValue, 3, 1);
|
||||
colorLayout->addWidget(scanlineValue, 3, 1);
|
||||
|
||||
scanline = new QSlider(Qt::Horizontal);
|
||||
scanline->setMinimum(0);
|
||||
scanline->setMaximum(20);
|
||||
scanline->setPageStep(4);
|
||||
sliders->addWidget(scanline, 3, 2);
|
||||
scanlineSlider = new QSlider(Qt::Horizontal);
|
||||
scanlineSlider->setMinimum(0);
|
||||
scanlineSlider->setMaximum(20);
|
||||
scanlineSlider->setPageStep(4);
|
||||
colorLayout->addWidget(scanlineSlider, 3, 2);
|
||||
|
||||
options = new QHBoxLayout;
|
||||
layout->addLayout(options);
|
||||
|
@ -68,38 +71,167 @@ VideoSettingsWindow::VideoSettingsWindow() {
|
|||
enableGammaRamp->setToolTip("Lower monitor gamma to more accurately match a CRT television");
|
||||
options->addWidget(enableGammaRamp);
|
||||
|
||||
pixelShaderWindow = new PixelShaderWindow;
|
||||
layout->addWidget(pixelShaderWindow);
|
||||
cropLabel = new QLabel("<b>Overscan Compensation</b>");
|
||||
layout->addWidget(cropLabel);
|
||||
|
||||
connect(contrast, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int)));
|
||||
connect(brightness, SIGNAL(valueChanged(int)), this, SLOT(brightnessAdjust(int)));
|
||||
connect(gamma, SIGNAL(valueChanged(int)), this, SLOT(gammaAdjust(int)));
|
||||
connect(scanline, SIGNAL(valueChanged(int)), this, SLOT(scanlineAdjust(int)));
|
||||
cropLayout = new QGridLayout;
|
||||
layout->addLayout(cropLayout);
|
||||
|
||||
cropLeftLabel = new QLabel("Left:");
|
||||
cropLayout->addWidget(cropLeftLabel, 0, 0);
|
||||
|
||||
cropLeftValue = new QLabel;
|
||||
cropLeftValue->setAlignment(Qt::AlignHCenter);
|
||||
cropLeftValue->setMinimumWidth(cropLeftValue->fontMetrics().width("+100%"));
|
||||
cropLayout->addWidget(cropLeftValue, 0, 1);
|
||||
|
||||
cropLeftSlider = new QSlider(Qt::Horizontal);
|
||||
cropLeftSlider->setMinimum(0);
|
||||
cropLeftSlider->setMaximum(20);
|
||||
cropLayout->addWidget(cropLeftSlider, 0, 2);
|
||||
|
||||
cropTopLabel = new QLabel("Top:");
|
||||
cropLayout->addWidget(cropTopLabel, 1, 0);
|
||||
|
||||
cropTopValue = new QLabel;
|
||||
cropTopValue->setAlignment(Qt::AlignHCenter);
|
||||
cropLayout->addWidget(cropTopValue, 1, 1);
|
||||
|
||||
cropTopSlider = new QSlider(Qt::Horizontal);
|
||||
cropTopSlider->setMinimum(0);
|
||||
cropTopSlider->setMaximum(20);
|
||||
cropLayout->addWidget(cropTopSlider, 1, 2);
|
||||
|
||||
cropRightLabel = new QLabel("Right:");
|
||||
cropLayout->addWidget(cropRightLabel, 2, 0);
|
||||
|
||||
cropRightValue = new QLabel;
|
||||
cropRightValue->setAlignment(Qt::AlignHCenter);
|
||||
cropLayout->addWidget(cropRightValue, 2, 1);
|
||||
|
||||
cropRightSlider = new QSlider(Qt::Horizontal);
|
||||
cropRightSlider->setMinimum(0);
|
||||
cropRightSlider->setMaximum(20);
|
||||
cropLayout->addWidget(cropRightSlider, 2, 2);
|
||||
|
||||
cropBottomLabel = new QLabel("Bottom:");
|
||||
cropLayout->addWidget(cropBottomLabel, 3, 0);
|
||||
|
||||
cropBottomValue = new QLabel;
|
||||
cropBottomValue->setAlignment(Qt::AlignHCenter);
|
||||
cropLayout->addWidget(cropBottomValue, 3, 1);
|
||||
|
||||
cropBottomSlider = new QSlider(Qt::Horizontal);
|
||||
cropBottomSlider->setMinimum(0);
|
||||
cropBottomSlider->setMaximum(20);
|
||||
cropLayout->addWidget(cropBottomSlider, 3, 2);
|
||||
|
||||
pixelShaderLabel = new QLabel("<b>Pixel Shader</b>");
|
||||
layout->addWidget(pixelShaderLabel);
|
||||
|
||||
pixelShaderLayout = new QGridLayout;
|
||||
layout->addLayout(pixelShaderLayout);
|
||||
|
||||
fragmentShaderLabel = new QLabel("Fragment:");
|
||||
pixelShaderLayout->addWidget(fragmentShaderLabel, 0, 0);
|
||||
|
||||
fragmentShaderValue = new QLineEdit;
|
||||
pixelShaderLayout->addWidget(fragmentShaderValue, 0, 1);
|
||||
|
||||
fragmentShaderSelect = new QPushButton("Select ...");
|
||||
pixelShaderLayout->addWidget(fragmentShaderSelect, 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(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int)));
|
||||
connect(brightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(brightnessAdjust(int)));
|
||||
connect(gammaSlider, SIGNAL(valueChanged(int)), this, SLOT(gammaAdjust(int)));
|
||||
connect(scanlineSlider, SIGNAL(valueChanged(int)), this, SLOT(scanlineAdjust(int)));
|
||||
connect(enableGammaRamp, SIGNAL(stateChanged(int)), this, SLOT(gammaRampToggle(int)));
|
||||
connect(cropLeftSlider, SIGNAL(valueChanged(int)), this, SLOT(cropLeftAdjust(int)));
|
||||
connect(cropTopSlider, SIGNAL(valueChanged(int)), this, SLOT(cropTopAdjust(int)));
|
||||
connect(cropRightSlider, SIGNAL(valueChanged(int)), this, SLOT(cropRightAdjust(int)));
|
||||
connect(cropBottomSlider, SIGNAL(valueChanged(int)), this, SLOT(cropBottomAdjust(int)));
|
||||
connect(fragmentShaderSelect, SIGNAL(released()), this, SLOT(selectFragmentShader()));
|
||||
connect(fragmentShaderDefault, SIGNAL(released()), this, SLOT(defaultFragmentShader()));
|
||||
connect(vertexShaderSelect, SIGNAL(released()), this, SLOT(selectVertexShader()));
|
||||
connect(vertexShaderDefault, SIGNAL(released()), this, SLOT(defaultVertexShader()));
|
||||
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::synchronizePixelShaderSettings() {
|
||||
if(!video.cap(Video::FragmentShader) && !video.cap(Video::VertexShader)) {
|
||||
pixelShaderLabel->hide();
|
||||
}
|
||||
|
||||
if(!video.cap(Video::FragmentShader)) {
|
||||
fragmentShaderLabel->hide();
|
||||
fragmentShaderValue->hide();
|
||||
fragmentShaderSelect->hide();
|
||||
fragmentShaderDefault->hide();
|
||||
}
|
||||
|
||||
if(!video.cap(Video::VertexShader)) {
|
||||
vertexShaderLabel->hide();
|
||||
vertexShaderValue->hide();
|
||||
vertexShaderSelect->hide();
|
||||
vertexShaderDefault->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::syncUi() {
|
||||
int n;
|
||||
|
||||
n = config().video.contrastAdjust;
|
||||
contrastValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
contrast->setSliderPosition(n);
|
||||
contrastSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.brightnessAdjust;
|
||||
brightnessValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
brightness->setSliderPosition(n);
|
||||
brightnessSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.gammaAdjust;
|
||||
gammaValue->setText(string() << (n > 0 ? "+" : "") << n << "%");
|
||||
gamma->setSliderPosition(n);
|
||||
gammaSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.scanlineAdjust;
|
||||
scanlineValue->setText(string() << n << "%");
|
||||
scanline->setSliderPosition(n / 5);
|
||||
scanlineSlider->setSliderPosition(n / 5);
|
||||
|
||||
enableGammaRamp->setChecked(config().video.enableGammaRamp);
|
||||
|
||||
n = config().video.cropLeft;
|
||||
cropLeftValue->setText(string() << n << "%");
|
||||
cropLeftSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.cropTop;
|
||||
cropTopValue->setText(string() << n << "%");
|
||||
cropTopSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.cropRight;
|
||||
cropRightValue->setText(string() << n << "%");
|
||||
cropRightSlider->setSliderPosition(n);
|
||||
|
||||
n = config().video.cropBottom;
|
||||
cropBottomValue->setText(string() << n << "%");
|
||||
cropBottomSlider->setSliderPosition(n);
|
||||
|
||||
fragmentShaderValue->setText(config().path.fragmentShader);
|
||||
vertexShaderValue->setText(config().path.vertexShader);
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::contrastAdjust(int value) {
|
||||
|
@ -131,3 +263,68 @@ void VideoSettingsWindow::gammaRampToggle(int state) {
|
|||
syncUi();
|
||||
utility.updateColorFilter();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::cropLeftAdjust(int state) {
|
||||
config().video.cropLeft = state;
|
||||
if(config().video.context->multiplier != 8) display.cropLeft = state;
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::cropTopAdjust(int state) {
|
||||
config().video.cropTop = state;
|
||||
if(config().video.context->multiplier != 8) display.cropTop = state;
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::cropRightAdjust(int state) {
|
||||
config().video.cropRight = state;
|
||||
if(config().video.context->multiplier != 8) display.cropRight = state;
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::cropBottomAdjust(int state) {
|
||||
config().video.cropBottom = state;
|
||||
if(config().video.context->multiplier != 8) display.cropBottom = state;
|
||||
syncUi();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::selectFragmentShader() {
|
||||
fileBrowser->onChange = (void*)0;
|
||||
fileBrowser->onActivate = bind(&VideoSettingsWindow::assignFragmentShader, this);
|
||||
fileBrowser->onAccept = bind(&VideoSettingsWindow::assignFragmentShader, this);
|
||||
fileBrowser->setWindowTitle("Select Fragment Shader");
|
||||
fileBrowser->setPath(config().path.current.shader);
|
||||
fileBrowser->setNameFilters("All files (*)");
|
||||
fileBrowser->showLoad();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::selectVertexShader() {
|
||||
fileBrowser->onChange = (void*)0;
|
||||
fileBrowser->onActivate = bind(&VideoSettingsWindow::assignVertexShader, this);
|
||||
fileBrowser->onAccept = bind(&VideoSettingsWindow::assignVertexShader, this);
|
||||
fileBrowser->setWindowTitle("Select Vertex Shader");
|
||||
fileBrowser->setPath(config().path.current.shader);
|
||||
fileBrowser->setNameFilters("All files (*)");
|
||||
fileBrowser->showLoad();
|
||||
}
|
||||
|
||||
void VideoSettingsWindow::defaultFragmentShader() { assignFragmentShader(""); }
|
||||
void VideoSettingsWindow::defaultVertexShader() { assignVertexShader(""); }
|
||||
|
||||
void VideoSettingsWindow::assignFragmentShader(const string &filename) {
|
||||
if(filename == "" || QDir(filename).exists() == false) {
|
||||
config().path.fragmentShader = 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);
|
||||
syncUi();
|
||||
utility.updatePixelShader();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,31 +3,69 @@ class VideoSettingsWindow : public QWidget {
|
|||
|
||||
public:
|
||||
QVBoxLayout *layout;
|
||||
QGridLayout *sliders;
|
||||
QLabel *colorLabel;
|
||||
QGridLayout *colorLayout;
|
||||
QLabel *contrastLabel;
|
||||
QLabel *contrastValue;
|
||||
QSlider *contrast;
|
||||
QSlider *contrastSlider;
|
||||
QLabel *brightnessLabel;
|
||||
QLabel *brightnessValue;
|
||||
QSlider *brightness;
|
||||
QSlider *brightnessSlider;
|
||||
QLabel *gammaLabel;
|
||||
QLabel *gammaValue;
|
||||
QSlider *gamma;
|
||||
QSlider *gammaSlider;
|
||||
QLabel *scanlineLabel;
|
||||
QLabel *scanlineValue;
|
||||
QSlider *scanline;
|
||||
QSlider *scanlineSlider;
|
||||
QHBoxLayout *options;
|
||||
QCheckBox *enableGammaRamp;
|
||||
QLabel *cropLabel;
|
||||
QGridLayout *cropLayout;
|
||||
QLabel *cropLeftLabel;
|
||||
QLabel *cropLeftValue;
|
||||
QSlider *cropLeftSlider;
|
||||
QLabel *cropTopLabel;
|
||||
QLabel *cropTopValue;
|
||||
QSlider *cropTopSlider;
|
||||
QLabel *cropRightLabel;
|
||||
QLabel *cropRightValue;
|
||||
QSlider *cropRightSlider;
|
||||
QLabel *cropBottomLabel;
|
||||
QLabel *cropBottomValue;
|
||||
QSlider *cropBottomSlider;
|
||||
QLabel *pixelShaderLabel;
|
||||
QGridLayout *pixelShaderLayout;
|
||||
QLabel *fragmentShaderLabel;
|
||||
QLineEdit *fragmentShaderValue;
|
||||
QPushButton *fragmentShaderSelect;
|
||||
QPushButton *fragmentShaderDefault;
|
||||
QLabel *vertexShaderLabel;
|
||||
QLineEdit *vertexShaderValue;
|
||||
QPushButton *vertexShaderSelect;
|
||||
QPushButton *vertexShaderDefault;
|
||||
|
||||
void synchronizePixelShaderSettings();
|
||||
void syncUi();
|
||||
VideoSettingsWindow();
|
||||
|
||||
public slots:
|
||||
private slots:
|
||||
void contrastAdjust(int);
|
||||
void brightnessAdjust(int);
|
||||
void gammaAdjust(int);
|
||||
void scanlineAdjust(int);
|
||||
void gammaRampToggle(int);
|
||||
void cropLeftAdjust(int);
|
||||
void cropTopAdjust(int);
|
||||
void cropRightAdjust(int);
|
||||
void cropBottomAdjust(int);
|
||||
void selectFragmentShader();
|
||||
void selectVertexShader();
|
||||
void defaultFragmentShader();
|
||||
void defaultVertexShader();
|
||||
|
||||
private:
|
||||
void assignFragmentShader(const string &filename);
|
||||
void assignVertexShader(const string &filename);
|
||||
};
|
||||
|
||||
extern VideoSettingsWindow *videoSettingsWindow;
|
||||
|
|
|
@ -23,9 +23,24 @@ ToolsWindow::ToolsWindow() {
|
|||
cheatFinderWindow = new CheatFinderWindow;
|
||||
stateManagerWindow = new StateManagerWindow;
|
||||
|
||||
cheatEditorArea = new QScrollArea;
|
||||
cheatEditorArea->setWidget(cheatEditorWindow);
|
||||
cheatEditorArea->setFrameStyle(0);
|
||||
cheatEditorArea->setWidgetResizable(true);
|
||||
|
||||
cheatFinderArea = new QScrollArea;
|
||||
cheatFinderArea->setWidget(cheatFinderWindow);
|
||||
cheatFinderArea->setFrameStyle(0);
|
||||
cheatFinderArea->setWidgetResizable(true);
|
||||
|
||||
stateManagerArea = new QScrollArea;
|
||||
stateManagerArea->setWidget(stateManagerWindow);
|
||||
stateManagerArea->setFrameStyle(0);
|
||||
stateManagerArea->setWidgetResizable(true);
|
||||
|
||||
tab = new QTabWidget;
|
||||
tab->addTab(cheatEditorWindow, QIcon(":/16x16/accessories-text-editor.png"), "Cheat Editor");
|
||||
tab->addTab(cheatFinderWindow, QIcon(":/16x16/system-search.png"), "Cheat Finder");
|
||||
tab->addTab(stateManagerWindow, QIcon(":/16x16/system-file-manager.png"), "State Manager");
|
||||
tab->addTab(cheatEditorArea, QIcon(":/16x16/accessories-text-editor.png"), "Cheat Editor");
|
||||
tab->addTab(cheatFinderArea, QIcon(":/16x16/system-search.png"), "Cheat Finder");
|
||||
tab->addTab(stateManagerArea, QIcon(":/16x16/system-file-manager.png"), "State Manager");
|
||||
layout->addWidget(tab);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ class ToolsWindow : public Window {
|
|||
public:
|
||||
QVBoxLayout *layout;
|
||||
QTabWidget *tab;
|
||||
QScrollArea *cheatEditorArea;
|
||||
QScrollArea *cheatFinderArea;
|
||||
QScrollArea *stateManagerArea;
|
||||
|
||||
ToolsWindow();
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ using namespace ruby;
|
|||
#include "movie/movie.hpp"
|
||||
|
||||
#include "settings/settings.moc.hpp"
|
||||
#include "settings/pixelshader.moc.hpp"
|
||||
#include "settings/video.moc.hpp"
|
||||
#include "settings/audio.moc.hpp"
|
||||
#include "settings/input.moc.hpp"
|
||||
|
|
|
@ -37,10 +37,25 @@ void Utility::constrainSize(unsigned &x, unsigned &y, unsigned max) {
|
|||
}
|
||||
|
||||
void Utility::resizeMainWindow() {
|
||||
//process all pending events to ensure window size is correct (after fullscreen state change, etc)
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
|
||||
unsigned screenWidth, screenHeight;
|
||||
if(config().video.isFullscreen == false) {
|
||||
screenWidth = QApplication::desktop()->availableGeometry(mainWindow).width();
|
||||
screenHeight = QApplication::desktop()->availableGeometry(mainWindow).height();
|
||||
} else {
|
||||
screenWidth = mainWindow->canvasContainer->size().width();
|
||||
screenHeight = mainWindow->canvasContainer->size().height();
|
||||
}
|
||||
|
||||
unsigned region = config().video.context->region;
|
||||
unsigned multiplier = config().video.context->multiplier;
|
||||
unsigned width = 256 * multiplier;
|
||||
unsigned height = (region == 0 ? 224 : 239) * multiplier;
|
||||
unsigned &width = display.outputWidth;
|
||||
unsigned &height = display.outputHeight;
|
||||
width = 256 * multiplier;
|
||||
height = (region == 0 ? 224 : 239) * multiplier;
|
||||
|
||||
if(config().video.context->correctAspectRatio) {
|
||||
if(region == 0) {
|
||||
|
@ -50,42 +65,53 @@ void Utility::resizeMainWindow() {
|
|||
}
|
||||
}
|
||||
|
||||
//at 5x scale, it is possible to correct the aspect ratio while maintaining
|
||||
//an even number of pixels for every column and every row; very important for
|
||||
//point / nearest-neighbor scaling ...
|
||||
//
|
||||
//NTSC: 1471x1120 -> 1536x1120 (6x5 scale)
|
||||
//PAL : 1781x1195 -> 1792x1195 (7x5 scale)
|
||||
if(multiplier == 5 && config().video.context->correctAspectRatio) {
|
||||
width = 256 * (region == 0 ? 6 : 7);
|
||||
height = (region == 0 ? 224 : 239) * 5;
|
||||
}
|
||||
display.cropLeft = config().video.cropLeft;
|
||||
display.cropTop = config().video.cropTop;
|
||||
display.cropRight = config().video.cropRight;
|
||||
display.cropBottom = config().video.cropBottom;
|
||||
|
||||
//ensure window size will not be larger than viewable desktop area
|
||||
constrainSize(height, width, screenHeight);
|
||||
constrainSize(width, height, screenWidth);
|
||||
|
||||
if(config().video.isFullscreen == false) {
|
||||
//get effective desktop work area region (ignore Windows taskbar, OS X dock, etc.)
|
||||
QRect deskRect = QApplication::desktop()->availableGeometry(mainWindow);
|
||||
|
||||
//ensure window size will not be larger than viewable desktop area
|
||||
constrainSize(height, width, deskRect.height()); //- frameHeight);
|
||||
constrainSize(width, height, deskRect.width()); //- frameWidth );
|
||||
|
||||
mainWindow->canvas->setFixedSize(width, height);
|
||||
mainWindow->show();
|
||||
} else {
|
||||
for(unsigned i = 0; i < 2; i++) {
|
||||
unsigned iWidth = width, iHeight = height;
|
||||
|
||||
constrainSize(iHeight, iWidth, mainWindow->canvasContainer->size().height());
|
||||
constrainSize(iWidth, iHeight, mainWindow->canvasContainer->size().width());
|
||||
|
||||
//center canvas onscreen; ensure it is not larger than viewable area
|
||||
mainWindow->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
mainWindow->canvas->setFixedSize(iWidth, iHeight);
|
||||
mainWindow->canvas->setMinimumSize(0, 0);
|
||||
|
||||
usleep(2000);
|
||||
QApplication::processEvents();
|
||||
if(multiplier == 6) {
|
||||
//Scale Max - Normal
|
||||
width = (double)width * (double)screenHeight / (double)height;
|
||||
height = screenHeight;
|
||||
}
|
||||
|
||||
if(multiplier == 7) {
|
||||
//Scale Max - Wide
|
||||
width = screenWidth;
|
||||
height = screenHeight;
|
||||
}
|
||||
|
||||
if(multiplier == 8) {
|
||||
//Scale Max - Wide Zoom
|
||||
//1. scale width and height proportionally until width of screen is completely filled
|
||||
//2. determine how much height goes out of screen by
|
||||
//3. cut half of the above value out of the visible input display region
|
||||
//this results in a 50% compromise between correct aspect ratio and fill mode;
|
||||
//while cropping out only 50% as much height as a fully proportional zoom would
|
||||
width = (double)width * (double)screenHeight / (double)height;
|
||||
height = screenHeight;
|
||||
unsigned widthDifference = screenWidth - width;
|
||||
unsigned adjustedHeight = (double)height * (double)(width + widthDifference) / (double)(width);
|
||||
unsigned heightDifference = adjustedHeight - height;
|
||||
width = screenWidth;
|
||||
display.cropLeft = 0;
|
||||
display.cropTop = 100.0 / (double)height * (heightDifference / 4);
|
||||
display.cropRight = 0;
|
||||
display.cropBottom = 100.0 / (double)height * (heightDifference / 4);
|
||||
}
|
||||
|
||||
mainWindow->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
mainWindow->canvas->setFixedSize(width, height);
|
||||
mainWindow->canvas->setMinimumSize(0, 0);
|
||||
}
|
||||
|
||||
//workaround for Qt/Xlib bug:
|
||||
|
|
BIN
supergameboy.dll
BIN
supergameboy.dll
Binary file not shown.
|
@ -1,6 +1,8 @@
|
|||
#ifndef NALL_PLATFORM_HPP
|
||||
#define NALL_PLATFORM_HPP
|
||||
|
||||
#include <nall/utf8.hpp>
|
||||
|
||||
//=========================
|
||||
//standard platform headers
|
||||
//=========================
|
||||
|
@ -50,7 +52,7 @@
|
|||
#define getcwd _getcwd
|
||||
#define ftruncate _chsize
|
||||
#define putenv _putenv
|
||||
#define mkdir(n, m) mkdir(n)
|
||||
#define mkdir(n, m) _wmkdir(nall::utf16_t(n))
|
||||
#define rmdir _rmdir
|
||||
#define vsnprintf _vsnprintf
|
||||
#define usleep(n) Sleep(n / 1000)
|
||||
|
|
|
@ -21,7 +21,7 @@ ifeq ($(platform),x)
|
|||
qtinc := `pkg-config --cflags $(qtlibs)`
|
||||
qtlib := `pkg-config --libs $(qtlibs)`
|
||||
else ifeq ($(platform),osx)
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers
|
||||
qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers)
|
||||
|
||||
qtlib := -L/Library/Frameworks
|
||||
qtlib += $(foreach lib,$(qtlibs),-framework $(lib))
|
||||
|
|
|
@ -342,6 +342,7 @@ inline FileDialog::FileDialog() {
|
|||
fileSystemModel->setNameFilterDisables(false);
|
||||
|
||||
fileView = new FileView;
|
||||
fileView->setMinimumWidth(320);
|
||||
fileView->setModel(fileSystemModel);
|
||||
fileView->setIconSize(QSize(16, 16));
|
||||
browseLayout->addWidget(fileView);
|
||||
|
|
Loading…
Reference in New Issue