mirror of
https://github.com/libretro/RetroArch
synced 2025-03-16 07:21:03 +00:00
Start on modular CPU filters. Abandon the old CPU filter stuff.
This commit is contained in:
parent
ec367d333d
commit
96b978d55a
1
driver.c
1
driver.c
@ -243,6 +243,7 @@ void init_video_input(void)
|
||||
.force_aspect = g_settings.video.force_aspect,
|
||||
.smooth = g_settings.video.smooth,
|
||||
.input_scale = scale,
|
||||
.rgb32 = g_extern.filter.active
|
||||
};
|
||||
|
||||
const input_driver_t *tmp = driver.input;
|
||||
|
3
driver.h
3
driver.h
@ -59,6 +59,7 @@ typedef struct video_info
|
||||
bool force_aspect;
|
||||
bool smooth;
|
||||
int input_scale; // HQ2X => 2, HQ4X => 4, None => 1
|
||||
bool rgb32; // Use 32-bit RGBA rather than native XBGR1555.
|
||||
} video_info_t;
|
||||
|
||||
typedef struct audio_driver
|
||||
@ -106,7 +107,7 @@ typedef struct video_driver
|
||||
{
|
||||
void* (*init)(video_info_t *video, const input_driver_t **input, void **input_data);
|
||||
// Should the video driver act as an input driver as well? :) The video init might preinitialize an input driver to override the settings in case the video driver relies on input driver for event handling, e.g.
|
||||
bool (*frame)(void* data, const uint16_t* frame, unsigned width, unsigned height, unsigned pitch, const char *msg); // msg is for showing a message on the screen along with the video frame.
|
||||
bool (*frame)(void* data, const void* frame, unsigned width, unsigned height, unsigned pitch, const char *msg); // msg is for showing a message on the screen along with the video frame.
|
||||
void (*set_nonblock_state)(void* data, bool toggle); // Should we care about syncing to vblank? Fast forwarding.
|
||||
// Is the window still active?
|
||||
bool (*alive)(void *data);
|
||||
|
@ -69,7 +69,7 @@ struct settings
|
||||
float aspect_ratio;
|
||||
char cg_shader_path[256];
|
||||
char bsnes_shader_path[256];
|
||||
unsigned filter;
|
||||
char filter_path[256];
|
||||
enum ssnes_shader_type shader_type;
|
||||
|
||||
bool render_to_texture;
|
||||
|
@ -1,45 +0,0 @@
|
||||
#include "bleed.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void bleed_filter(uint16_t *data, int width, int height)
|
||||
{
|
||||
uint16_t tmp[4];
|
||||
int ptr = 0;
|
||||
uint16_t r[4];
|
||||
uint16_t g[4];
|
||||
uint16_t b[4];
|
||||
uint16_t bleed_r;
|
||||
uint16_t bleed_g;
|
||||
uint16_t bleed_b;
|
||||
float rand_map[4];
|
||||
|
||||
for (int h = 0; h < height; h++ )
|
||||
{
|
||||
memcpy(tmp, data, sizeof(tmp));
|
||||
ptr = 3;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
rand_map[i] = (rand() % 20)/1000.0; // 0.02 * 4 = 0.08
|
||||
}
|
||||
|
||||
for (int i = 3; i < width; i++, ptr++)
|
||||
{
|
||||
tmp[ptr & 0x3] = data[i];
|
||||
for (int y = 0; y < 4; y++)
|
||||
{
|
||||
r[y] = (tmp[(ptr + y) & 0x3] >> 10) & 0x1F;
|
||||
g[y] = (tmp[(ptr + y) & 0x3] >> 5) & 0x1F;
|
||||
b[y] = (tmp[(ptr + y) & 0x3] >> 0) & 0x1F;
|
||||
}
|
||||
|
||||
bleed_r = r[0] * (0.05 + rand_map[0] ) + r[1] * (0.10 + rand_map[1] ) + r[2] * (0.20 + rand_map[2]) + r[3] * (0.57 + rand_map[3] ); // 0.92
|
||||
bleed_g = g[0] * (0.03 + rand_map[2]/3) + g[1] * (0.10 + rand_map[0]/3) + g[2] * (0.20 + rand_map[3]/3) + g[3] * (0.63 + rand_map[1]/3); // 0.96
|
||||
bleed_b = b[0] * (0.05 + rand_map[3] ) + b[1] * (0.10 + rand_map[2] ) + b[2] * (0.20 + rand_map[1]) + b[3] * (0.57 + rand_map[0] ); // 0.92
|
||||
|
||||
data[i] = (bleed_r << 10) | (bleed_g << 5) | (bleed_b);
|
||||
}
|
||||
data += width;
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
#include <stdint.h>
|
||||
|
||||
void bleed_filter(uint16_t *data, int width, int height);
|
@ -1,94 +0,0 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2007 guest(r) - guest.r@gmail.com
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
The 2xSaL shader processes a gfx. surface and redraws it 2x finer.
|
||||
|
||||
A linear post-resize can fit the image to any resolution.
|
||||
|
||||
Note: set scaler to normal2x.
|
||||
|
||||
*/
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
struct deltas
|
||||
{
|
||||
float2 UL, UR, DL, DR;
|
||||
};
|
||||
|
||||
|
||||
output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s_p : TEXUNIT0)
|
||||
{
|
||||
float2 texsize = IN.texture_size;
|
||||
float dx = pow(texsize.x, -1.0) * 0.25;
|
||||
float dy = pow(texsize.y, -1.0) * 0.25;
|
||||
float3 dt = float3(1.0, 1.0, 1.0);
|
||||
|
||||
deltas VAR = {
|
||||
tex + float2(-dx, -dy),
|
||||
tex + float2(dx, -dy),
|
||||
tex + float2(-dx, dy),
|
||||
tex + float2(dx, dy)
|
||||
};
|
||||
|
||||
float3 c00 = tex2D(s_p, VAR.UL).xyz;
|
||||
float3 c20 = tex2D(s_p, VAR.UR).xyz;
|
||||
float3 c02 = tex2D(s_p, VAR.DL).xyz;
|
||||
float3 c22 = tex2D(s_p, VAR.DR).xyz;
|
||||
|
||||
float m1=dot(abs(c00-c22),dt)+0.001;
|
||||
float m2=dot(abs(c02-c20),dt)+0.001;
|
||||
|
||||
output OUT;
|
||||
OUT.color = float4((m1*(c02+c20)+m2*(c22+c00))/(2.0*(m1+m2)),1.0);
|
||||
return OUT;
|
||||
}
|
||||
|
@ -1,95 +0,0 @@
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
float Luminance = 0.09f;
|
||||
static const float fMiddleGray = 0.18f;
|
||||
static const float fWhiteCutoff = 0.8f;
|
||||
|
||||
#define NUM 13
|
||||
|
||||
float2 PixelOffsets[NUM] =
|
||||
{
|
||||
{ -0.006, -0.006 },
|
||||
{ -0.005, -0.005 },
|
||||
{ -0.004, -0.004 },
|
||||
{ -0.003, -0.003 },
|
||||
{ -0.002, -0.002 },
|
||||
{ -0.001, -0.001 },
|
||||
{ 0.000, 0.000 },
|
||||
{ 0.001, 0.001 },
|
||||
{ 0.002, 0.002 },
|
||||
{ 0.003, 0.003 },
|
||||
{ 0.004, 0.004 },
|
||||
{ 0.005, 0.005 },
|
||||
{ 0.006, 0.006 },
|
||||
};
|
||||
|
||||
static const float BlurWeights[NUM] =
|
||||
{
|
||||
0.002216,
|
||||
0.008764,
|
||||
0.026995,
|
||||
0.064759,
|
||||
0.120985,
|
||||
0.176033,
|
||||
0.199471,
|
||||
0.176033,
|
||||
0.120985,
|
||||
0.064759,
|
||||
0.026995,
|
||||
0.008764,
|
||||
0.002216,
|
||||
};
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
|
||||
output main_fragment( float2 Tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0 )
|
||||
{
|
||||
float2 BloomSettings;
|
||||
BloomSettings.x = 1;
|
||||
BloomSettings.y = 0.3;
|
||||
|
||||
float3 pixel;
|
||||
float3 Color = 0;
|
||||
|
||||
for(int i = 0; i < NUM; i++)
|
||||
{
|
||||
pixel = tex2D(s0, Tex + PixelOffsets[i] * 5.0f)+BloomSettings.y;
|
||||
|
||||
pixel *= fMiddleGray / (Luminance + 0.001f);
|
||||
pixel *= (1.0f + (pixel / (fWhiteCutoff * fWhiteCutoff)));
|
||||
pixel -= 5.0f;
|
||||
|
||||
pixel = max(pixel,0.0f);
|
||||
pixel /= (10.0f + pixel);
|
||||
|
||||
Color += pixel * BlurWeights[i];
|
||||
}
|
||||
|
||||
Color *= BloomSettings.x;
|
||||
|
||||
output OUT;
|
||||
OUT.color = float4(Color,1.0) + tex2D(s0,Tex);
|
||||
return OUT;
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
const float2 samples[12]
|
||||
= {
|
||||
-0.326212, -0.405805,
|
||||
-0.840144, -0.073580,
|
||||
-0.695914, 0.457137,
|
||||
-0.203345, 0.620716,
|
||||
0.962340, -0.194983,
|
||||
0.473434, -0.480026,
|
||||
0.519456, 0.767022,
|
||||
0.185461, -0.893124,
|
||||
0.507431, 0.064425,
|
||||
0.896420, 0.412458,
|
||||
-0.321940, -0.932615,
|
||||
-0.791559, -0.597705
|
||||
};
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 col : COLOR;
|
||||
};
|
||||
|
||||
output main_fragment(in float2 Tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0 )
|
||||
{
|
||||
float4 color = tex2D( s0, Tex.xy);
|
||||
float BlurFactor = 0.0025; //set between 0.001 and 0.05
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
color += tex2D(s0, Tex + BlurFactor * samples[i]);
|
||||
}
|
||||
|
||||
output OUT;
|
||||
OUT.col = color / 13;
|
||||
return OUT;
|
||||
}
|
||||
|
100
hqflt/cg/crt.cg
100
hqflt/cg/crt.cg
@ -1,100 +0,0 @@
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
#define TEX2D(c) tex2D(decal,(c))
|
||||
#define PI 3.141592653589
|
||||
#define phase 0.0
|
||||
#define gamma 2.5
|
||||
#define distortion 0.04
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
float2 barrelDistortion(float2 coord)
|
||||
{
|
||||
float2 cc = coord - 0.5;
|
||||
float dist = dot(cc, cc);
|
||||
return coord + cc * (dist + distortion * dist * dist) * distortion;
|
||||
}
|
||||
|
||||
output main_fragment(float2 texCoord : TEXCOORD0, uniform sampler2D decal : TEXUNIT0, uniform input IN)
|
||||
{
|
||||
output OUT;
|
||||
|
||||
float2 rubyInputSize = IN.video_size;
|
||||
float2 rubyOutputSize = IN.output_size;
|
||||
float2 rubyTextureSize = IN.texture_size;
|
||||
|
||||
float2 xy = barrelDistortion(texCoord.xy);
|
||||
float2 one = 1.0/rubyTextureSize;
|
||||
xy = xy + float2(0.0 , -0.5 * (phase + (1-phase) * rubyInputSize.y/rubyOutputSize.y) * one.y);
|
||||
float4 texels[8];
|
||||
texels[0] = TEX2D(xy + float2(-one.x,0.0));
|
||||
texels[1] = TEX2D(xy);
|
||||
texels[2] = TEX2D(xy + float2(one.x, 0.0));
|
||||
texels[3] = TEX2D(xy + float2(2 * one.x, 0.0));
|
||||
texels[4] = TEX2D(xy + float2(-one.x,one.y));
|
||||
texels[5] = TEX2D(xy + float2(0.0, one.y));
|
||||
texels[6] = TEX2D(xy + one);
|
||||
texels[7] = TEX2D(xy + float2(2 * one.x, one.y));
|
||||
|
||||
|
||||
float2 uv_ratio = frac(xy*rubyTextureSize);
|
||||
|
||||
float4 col, col2;
|
||||
|
||||
float4 coeffs = float4(1.0 + uv_ratio.x, uv_ratio.x, 1.0 - uv_ratio.x, 2.0 - uv_ratio.x);
|
||||
coeffs = (sin(PI * coeffs) * sin(PI * coeffs / 2.0)) / (coeffs * coeffs);
|
||||
coeffs = coeffs / (coeffs.x+coeffs.y+coeffs.z+coeffs.w);
|
||||
|
||||
col = clamp(coeffs.x * texels[0] + coeffs.y * texels[1] + coeffs.z * texels[2] + coeffs.w * texels[3], 0.0, 1.0);
|
||||
col2 = clamp(coeffs.x * texels[4] + coeffs.y * texels[5] + coeffs.z * texels[6] + coeffs.w * texels[7], 0.0, 1.0);
|
||||
col = pow(col, gamma);
|
||||
col2 = pow(col2, gamma);
|
||||
|
||||
float4 wid = 2 + 2 * pow(col, 4.0);
|
||||
float4 weights = uv_ratio.y/0.3;
|
||||
weights = 0.51*exp(-pow(weights*sqrt(2/wid),wid))/0.3/(0.6+0.2*wid);
|
||||
wid = 2 + 4 * pow(col2,4.0);
|
||||
float4 weights2 = (1.0-uv_ratio.y)/0.3;
|
||||
weights2 = 0.51*exp(-pow(weights2*sqrt(2/wid),wid))/0.3/(0.6+0.2*wid);
|
||||
|
||||
float4 mcol = 1.0;
|
||||
if ( fmod(xy.x*rubyOutputSize.x,2.0) < 1.0)
|
||||
mcol.g = 0.7;
|
||||
else
|
||||
mcol.rb = 0.7;
|
||||
|
||||
OUT.color = pow(mcol*(col * weights + col2 * weights2), 1.0/2.2);
|
||||
//OUT.color = 1.0;
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
@ -1,94 +0,0 @@
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
output main_fragment(float2 texCoord : TEXCOORD0, uniform sampler2D decal : TEXUNIT0, uniform input IN)
|
||||
{
|
||||
float x = 0.5 * (1.0 / IN.texture_size.x);
|
||||
float y = 0.5 * (1.0 / IN.texture_size.y);
|
||||
float2 dg1 = float2( x, y);
|
||||
float2 dg2 = float2(-x, y);
|
||||
float2 dx = float2(x, 0.0);
|
||||
float2 dy = float2(0.0, y);
|
||||
|
||||
float4 TexCoord[5];
|
||||
TexCoord[0] = float4(texCoord, 0.0, 0.0);
|
||||
TexCoord[1].xy = TexCoord[0].xy - dg1;
|
||||
TexCoord[1].zw = TexCoord[0].xy - dy;
|
||||
TexCoord[2].xy = TexCoord[0].xy - dg2;
|
||||
TexCoord[2].zw = TexCoord[0].xy + dx;
|
||||
TexCoord[3].xy = TexCoord[0].xy + dg1;
|
||||
TexCoord[3].zw = TexCoord[0].xy + dy;
|
||||
TexCoord[4].xy = TexCoord[0].xy + dg2;
|
||||
TexCoord[4].zw = TexCoord[0].xy - dx;
|
||||
|
||||
float3 c00 = tex2D(decal, TexCoord[1].xy).xyz;
|
||||
float3 c10 = tex2D(decal, TexCoord[1].zw).xyz;
|
||||
float3 c20 = tex2D(decal, TexCoord[2].xy).xyz;
|
||||
float3 c01 = tex2D(decal, TexCoord[4].zw).xyz;
|
||||
float3 c11 = tex2D(decal, TexCoord[0].xy).xyz;
|
||||
float3 c21 = tex2D(decal, TexCoord[2].zw).xyz;
|
||||
float3 c02 = tex2D(decal, TexCoord[4].xy).xyz;
|
||||
float3 c12 = tex2D(decal, TexCoord[3].zw).xyz;
|
||||
float3 c22 = tex2D(decal, TexCoord[3].xy).xyz;
|
||||
float3 dt = float3(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);
|
||||
|
||||
output OUT;
|
||||
OUT.color = float4(w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11, 1.0);
|
||||
return OUT;
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Author: Themaister
|
||||
License: Public domain
|
||||
*/
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
struct deltas
|
||||
{
|
||||
float2 UL, UR, DL, DR;
|
||||
};
|
||||
|
||||
float3 quad_inter(float3 x0, float3 x1, float3 x2, float x)
|
||||
{
|
||||
float3 poly[3];
|
||||
poly[2] = 0.5*x0 - x1 + 0.5*x2;
|
||||
poly[1] = -1.5*x0 + 2.0*x1 - 0.5*x2;
|
||||
poly[0] = x0;
|
||||
return poly[2] * x * x + poly[1] * x + poly[0];
|
||||
}
|
||||
|
||||
output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s0 : TEXUNIT0)
|
||||
{
|
||||
float2 texsize = IN.texture_size;
|
||||
float sharpness = 2.0;
|
||||
float dx = float(pow(sharpness * texsize.x, -1.0));
|
||||
float dy = float(pow(sharpness * texsize.y, -1.0));
|
||||
|
||||
float3 c00 = tex2D(s0, tex + float2(-dx, -dy)).xyz;
|
||||
float3 c01 = tex2D(s0, tex + float2(-dx, 0)).xyz;
|
||||
float3 c02 = tex2D(s0, tex + float2(-dx, dy)).xyz;
|
||||
float3 c10 = tex2D(s0, tex + float2(0, -dy)).xyz;
|
||||
float3 c11 = tex2D(s0, tex + float2(0, 0)).xyz;
|
||||
float3 c12 = tex2D(s0, tex + float2(0, dy)).xyz;
|
||||
float3 c20 = tex2D(s0, tex + float2(dx, -dy)).xyz;
|
||||
float3 c21 = tex2D(s0, tex + float2(dx, 0)).xyz;
|
||||
float3 c22 = tex2D(s0, tex + float2(dx, dy)).xyz;
|
||||
|
||||
float frac_amt_x = frac(tex.x * texsize.x);
|
||||
float frac_amt_y = frac(tex.y * texsize.y);
|
||||
float3 loval = quad_inter(c00, c10, c20, frac_amt_x + 0.5);
|
||||
float3 midval = quad_inter(c01, c11, c21, frac_amt_x + 0.5);
|
||||
float3 hival = quad_inter(c02, c12, c22, frac_amt_x + 0.5);
|
||||
float3 res = quad_inter(loval, midval, hival, frac_amt_y + 0.5);
|
||||
|
||||
output OUT;
|
||||
|
||||
// Bilinear!
|
||||
// float3 first = lerp(c00, c20, frac(tex.x * texsize.x + 0.5));
|
||||
// float3 second = lerp(c02, c22, frac(tex.x * texsize.x + 0.5));
|
||||
// float3 res = lerp(first, second, frac(tex.y * texsize.y + 0.5));
|
||||
// OUT.color = float4(res, 1.0);
|
||||
|
||||
|
||||
OUT.color = float4(res, 1.0);
|
||||
return OUT;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
output main_fragment(float2 texCoord : TEXCOORD0, uniform sampler2D decal : TEXUNIT0, uniform input IN)
|
||||
{
|
||||
output OUT;
|
||||
|
||||
float winHeight = IN.output_size.y;
|
||||
float4 tex_color = tex2D(decal, texCoord);
|
||||
|
||||
OUT.color = (1.0 - 0.60 * floor(fmod(texCoord.y * winHeight, 2.0))) * tex_color;
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
output main_fragment( in float2 Tex : TEXCOORD0, uniform sampler2D s0 : TEXUNIT0 )
|
||||
{
|
||||
float4 Color = tex2D( s0, Tex.xy );
|
||||
float Sharpenfactor = 30; //Make this between 10 and 50;
|
||||
|
||||
Color -= tex2D( s0, Tex.xy+0.0001)*Sharpenfactor;
|
||||
Color += tex2D( s0, Tex.xy-0.0001)*Sharpenfactor;
|
||||
|
||||
Color.a = 1.0;
|
||||
output OUT;
|
||||
OUT.color = Color;
|
||||
return OUT;
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
Author: Themaister
|
||||
License: Public domain
|
||||
*/
|
||||
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
|
||||
output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s0 : TEXUNIT0)
|
||||
{
|
||||
float2 texsize = IN.texture_size;
|
||||
const float scale_factor = 1.0;
|
||||
float2 delta = 0.5 / (texsize * scale_factor);
|
||||
float dx = delta.x;
|
||||
float dy = delta.y;
|
||||
|
||||
float3 c00 = tex2D(s0, tex + float2(-dx, -dy)).xyz;
|
||||
float3 c01 = tex2D(s0, tex + float2(-dx, 0)).xyz;
|
||||
float3 c02 = tex2D(s0, tex + float2(-dx, dy)).xyz;
|
||||
float3 c10 = tex2D(s0, tex + float2(0, -dy)).xyz;
|
||||
float3 c11 = tex2D(s0, tex + float2(0, 0)).xyz;
|
||||
float3 c12 = tex2D(s0, tex + float2(0, dy)).xyz;
|
||||
float3 c20 = tex2D(s0, tex + float2(dx, -dy)).xyz;
|
||||
float3 c21 = tex2D(s0, tex + float2(dx, 0)).xyz;
|
||||
float3 c22 = tex2D(s0, tex + float2(dx, dy)).xyz;
|
||||
|
||||
output OUT;
|
||||
|
||||
float3 first = lerp(c00, c20, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
float3 second = lerp(c02, c22, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
|
||||
float3 mid_horiz = lerp(c01, c21, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
float3 mid_vert = lerp(c10, c12, frac(scale_factor * tex.y * texsize.y + 0.5));
|
||||
|
||||
float3 res = lerp(first, second, frac(scale_factor * tex.y * texsize.y + 0.5));
|
||||
OUT.color = float4(0.28 * (res + mid_horiz + mid_vert) + 4.7 * abs(res - lerp(mid_horiz, mid_vert, 0.5)), 1.0);
|
||||
|
||||
return OUT;
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
/*
|
||||
Author: Themaister
|
||||
License: Public domain
|
||||
*/
|
||||
|
||||
/* Default Vertex shader */
|
||||
void main_vertex
|
||||
(
|
||||
float4 position : POSITION,
|
||||
float4 color : COLOR,
|
||||
float2 texCoord : TEXCOORD0,
|
||||
|
||||
uniform float4x4 modelViewProj,
|
||||
|
||||
out float4 oPosition : POSITION,
|
||||
out float4 oColor : COLOR,
|
||||
out float2 otexCoord : TEXCOORD
|
||||
)
|
||||
{
|
||||
oPosition = mul(modelViewProj, position);
|
||||
oColor = color;
|
||||
otexCoord = texCoord;
|
||||
}
|
||||
|
||||
struct output
|
||||
{
|
||||
float4 color : COLOR;
|
||||
};
|
||||
|
||||
struct input
|
||||
{
|
||||
float2 video_size;
|
||||
float2 texture_size;
|
||||
float2 output_size;
|
||||
};
|
||||
|
||||
float4 compress(float4 in_color, float threshold, float ratio)
|
||||
{
|
||||
float4 diff = in_color - float4(threshold);
|
||||
diff = clamp(diff, 0.0, 100.0);
|
||||
return in_color - (diff * (1.0 - 1.0/ratio));
|
||||
}
|
||||
|
||||
output main_fragment (float2 tex : TEXCOORD0, uniform input IN, uniform sampler2D s0 : TEXUNIT0)
|
||||
{
|
||||
float2 texsize = IN.texture_size;
|
||||
const float scale_factor = 1.0;
|
||||
float2 delta = 0.5 / (texsize * scale_factor);
|
||||
float dx = delta.x;
|
||||
float dy = delta.y;
|
||||
|
||||
float3 c00 = tex2D(s0, tex + float2(-dx, -dy)).xyz;
|
||||
float3 c01 = tex2D(s0, tex + float2(-dx, 0)).xyz;
|
||||
float3 c02 = tex2D(s0, tex + float2(-dx, dy)).xyz;
|
||||
float3 c10 = tex2D(s0, tex + float2(0, -dy)).xyz;
|
||||
float3 c11 = tex2D(s0, tex + float2(0, 0)).xyz;
|
||||
float3 c12 = tex2D(s0, tex + float2(0, dy)).xyz;
|
||||
float3 c20 = tex2D(s0, tex + float2(dx, -dy)).xyz;
|
||||
float3 c21 = tex2D(s0, tex + float2(dx, 0)).xyz;
|
||||
float3 c22 = tex2D(s0, tex + float2(dx, dy)).xyz;
|
||||
|
||||
output OUT;
|
||||
|
||||
float3 first = lerp(c00, c20, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
float3 second = lerp(c02, c22, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
|
||||
float3 mid_horiz = lerp(c01, c21, frac(scale_factor * tex.x * texsize.x + 0.5));
|
||||
float3 mid_vert = lerp(c10, c12, frac(scale_factor * tex.y * texsize.y + 0.5));
|
||||
|
||||
float3 res = lerp(first, second, frac(scale_factor * tex.y * texsize.y + 0.5));
|
||||
float4 final = float4(0.26 * (res + mid_horiz + mid_vert) + 3.5 * abs(res - lerp(mid_horiz, mid_vert, 0.5)), 1.0);
|
||||
OUT.color = compress(final, 0.8, 5.0);
|
||||
|
||||
return OUT;
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
|
||||
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
|
||||
*
|
||||
* Some code herein may be based on code found in BSNES.
|
||||
*
|
||||
* SSNES is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with SSNES.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __FILTERS_H
|
||||
#define __FILTERS_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER
|
||||
|
||||
#include "pastlib.h"
|
||||
#include "grayscale.h"
|
||||
#include "bleed.h"
|
||||
#include "ntsc.h"
|
||||
|
||||
#define FILTER_NONE 0
|
||||
#define FILTER_HQ2X 1
|
||||
#define FILTER_HQ4X 2
|
||||
#define FILTER_GRAYSCALE 3
|
||||
#define FILTER_BLEED 4
|
||||
#define FILTER_NTSC 5
|
||||
#define FILTER_HQ2X_STR "hq2x"
|
||||
#define FILTER_HQ4X_STR "hq4x"
|
||||
#define FILTER_GRAYSCALE_STR "grayscale"
|
||||
#define FILTER_BLEED_STR "bleed"
|
||||
#define FILTER_NTSC_STR "ntsc"
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,21 +0,0 @@
|
||||
/* Very simple grayscale filter.
|
||||
* Author: Hans-Kristian Arntzen
|
||||
* License: Public domain
|
||||
*/
|
||||
|
||||
#include "grayscale.h"
|
||||
|
||||
// Input format 0RRRRRGGGGGBBBBB. Colors themselves could be switched around.
|
||||
void grayscale_filter(uint16_t *data, int width, int height)
|
||||
{
|
||||
for (int i = 0; i < width * height; i++ )
|
||||
{
|
||||
int r, g, b, color;
|
||||
r = (data[i] >> 10) & 0x1F;
|
||||
g = (data[i] >> 5) & 0x1F;
|
||||
b = (data[i] >> 0) & 0x1F;
|
||||
|
||||
color = (int)(r * 0.3 + g * 0.59 + b * 0.11);
|
||||
data[i] = (color << 10) | (color << 5) | color;
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
/* Very simple grayscale filter.
|
||||
* Author: Hans-Kristian Arntzen
|
||||
* License: Public domain
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
void grayscale_filter(uint16_t *data, int width, int height);
|
555
hqflt/hq.c
555
hqflt/hq.c
@ -1,555 +0,0 @@
|
||||
/* This source code is Copyright (C) 2006-2009 by WolfWings. */
|
||||
/* It is, however, released under the ISC license. */
|
||||
/* en.wikipedia.org/wiki/ISC_Licence */
|
||||
/* --------------------------------------------------------- */
|
||||
/* It is a formula-level rederiviation of the HQ2x technique */
|
||||
/* and is, thus, not a derivative work of the original code, */
|
||||
/* only the original equations behind the code. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pastlib.h"
|
||||
|
||||
static const uint8_t blends_2x[14*4] = {
|
||||
/* 5 2 4 1 */
|
||||
|
||||
8, 4, 4, 0,
|
||||
8, 4, 0, 4,
|
||||
8, 0, 4, 4,
|
||||
16, 0, 0, 0,
|
||||
12, 4, 0, 0,
|
||||
12, 0, 4, 0,
|
||||
12, 0, 0, 4,
|
||||
|
||||
4, 6, 6, 0, /* Interp9 */
|
||||
12, 2, 2, 0, /* Interp7 */
|
||||
14, 1, 1, 0, /* Interp10*/
|
||||
10, 4, 2, 0, /* Interp6 */
|
||||
10, 2, 4, 0, /* Interp6 */
|
||||
4, 6, 6, 0, /* Added for secondary blending used in HQ4x */
|
||||
8, 4, 4, 0, /* Added for secondary blending used in HQ4x */
|
||||
};
|
||||
|
||||
static const uint8_t blends_4x[14*16] = {
|
||||
/* 5 2 4 1 5 2 4 1 5 2 4 1 5 2 4 1 */
|
||||
|
||||
8, 4, 4, 0, 10, 4, 2, 0, 10, 2, 4, 0, 12, 2, 2, 0, /* Needs to be split. B */
|
||||
10, 0, 0, 6, 10, 4, 0, 2, 12, 0, 0, 4, 14, 0, 0, 2,
|
||||
10, 0, 0, 6, 10, 0, 4, 2, 12, 0, 0, 4, 14, 0, 0, 2,
|
||||
16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, /* Solid colors */
|
||||
10, 6, 0, 0, 10, 6, 0, 0, 14, 2, 0, 0, 14, 2, 0, 0,
|
||||
10, 0, 6, 0, 14, 0, 2, 0, 10, 0, 6, 0, 14, 0, 2, 0,
|
||||
10, 0, 0, 6, 12, 0, 0, 4, 12, 0, 0, 4, 14, 0, 0, 2,
|
||||
0, 8, 8, 0, 4, 8, 4, 0, 0, 6,10, 0, 12, 2, 2, 0, /* Needs to be split. A */
|
||||
8, 4, 4, 0, 12, 4, 0, 0, 12, 0, 4, 0, 16, 0, 0, 0,
|
||||
8, 4, 4, 0, 16, 0, 0, 0, 16, 0, 0, 0, 16, 0, 0, 0,
|
||||
12, 4, 0, 0, 4,12, 0, 0, 10, 0, 4, 0, 14, 0, 2, 0,
|
||||
12, 0, 4, 0, 10, 4, 0, 0, 4, 0,12, 0, 14, 2, 0, 0,
|
||||
0, 8, 8, 0, 0,10, 6, 0, 4, 4, 8, 0, 12, 2, 2, 0, /* Needs to be split. A */
|
||||
0, 8, 8, 0, 8, 8, 0, 0, 8, 0, 8, 0, 16, 0, 0, 0, /* Needs to be split. B */
|
||||
};
|
||||
|
||||
static const uint8_t tree_hq[0x800] = {
|
||||
/* 6 6 6 6 6 6 6 6
|
||||
* 2 2 2 2 2 2 2 2
|
||||
* 4 4 4 4 4 4 4 4
|
||||
* 8 8 8 8 8 8 8 8
|
||||
*/
|
||||
0, 0, 2, 2, 1, 1,13,13, 0, 0, 2, 2, 1, 1,13, 8, /* */
|
||||
0, 0, 2, 2, 1, 1,12, 6, 0, 0, 2, 2, 1, 1, 8, 8, /* 3 */
|
||||
0, 0, 5,10, 4, 4,13,13, 0, 0, 5, 5,11, 4,13,13, /* 1 */
|
||||
0, 0, 5,10, 4, 4,12,13, 0, 0, 5, 5,11, 4,13,13, /* 31 */
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 6, 8, /* 7 */
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6, /* 3 7 */
|
||||
0, 0, 5,10, 4, 4, 7,13, 0, 0, 5, 5,11, 4,13,13, /* 17 */
|
||||
0, 0, 5,10, 4, 4, 9, 9, 0, 0, 5,10,11,11, 9, 9, /* 317 */
|
||||
0, 0, 2, 2, 1, 1,13, 8, 0, 0, 2, 2, 1, 1, 8, 8, /* 9 */
|
||||
0, 0, 2, 2, 1, 1,12, 8, 0, 0, 2, 2, 1, 1, 8, 6, /* 3 9 */
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13, /* 1 9 */
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5, 4, 4,12,13, /* 31 9 */
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 8, 6, /* 79 */
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6, /* 3 79 */
|
||||
0, 0, 5, 5, 4, 4, 7, 7, 0, 0, 5, 5, 4, 4,13,13, /* 179 */
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5, 4, 4, 9, 9, /* 3179 */
|
||||
/* DIFF26 */
|
||||
0, 0, 2, 2, 1, 1,13,13, 0, 0, 2, 2, 1, 1,13, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 6, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5,11, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5,11, 4,13,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 6, 8,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 7,13, 0, 0, 5, 5,11, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5,11,11, 9, 9,
|
||||
0, 0, 2, 2, 1, 1,13, 8, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5, 4, 4,12,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 7, 7, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5, 4, 4, 9, 9,
|
||||
/* DIFF24 */
|
||||
0, 0, 2, 2, 1, 1, 6, 3, 0, 0, 2, 2, 1, 1, 3, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5,10,11,11, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
/* DIFF26 DIFF24 */
|
||||
0, 0, 2, 2, 1, 1, 6, 3, 0, 0, 2, 2, 1, 1, 3, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5,11, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5,11,11, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
/* DIFF84 */
|
||||
0, 0, 2, 2, 1, 1,13,13, 0, 0, 2, 2, 1, 1,13, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 6, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 5,10, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5,10, 4, 4,12,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 6, 8,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5,10, 4, 4, 7,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5,10, 4, 4, 9, 9, 0, 0, 5,10, 4, 4, 9, 9,
|
||||
0, 0, 2, 2, 1, 1,13, 8, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5, 4, 4,12,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 7, 7, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5, 4, 4, 9, 9,
|
||||
/* DIFF26 DIFF84 */
|
||||
0, 0, 2, 2, 1, 1,13,13, 0, 0, 2, 2, 1, 1,13, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 6, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 6, 8,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 7,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5, 4, 4, 9, 9,
|
||||
0, 0, 2, 2, 1, 1,13, 8, 0, 0, 2, 2, 1, 1, 8, 8,
|
||||
0, 0, 2, 2, 1, 1,12, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 5, 5, 4, 4,13,13, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4,12,13, 0, 0, 5, 5, 4, 4,12,13,
|
||||
0, 0, 2, 2, 1, 1, 7, 8, 0, 0, 2, 2, 1, 1, 8, 6,
|
||||
0, 0, 2, 2, 1, 1, 8, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 7, 7, 0, 0, 5, 5, 4, 4,13,13,
|
||||
0, 0, 5, 5, 4, 4, 9, 9, 0, 0, 5, 5, 4, 4, 9, 9,
|
||||
/* DIFF24 DIFF84 */
|
||||
0, 0, 2, 2, 1, 1, 6, 3, 0, 0, 2, 2, 1, 1, 3, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5,10, 4, 4, 3, 3, 0, 0, 5,10, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
/* DIFF26 DIFF24 DIFF84 */
|
||||
0, 0, 2, 2, 1, 1, 6, 3, 0, 0, 2, 2, 1, 1, 3, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 2, 2, 1, 1, 6, 6, 0, 0, 2, 2, 1, 1, 6, 6,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3,
|
||||
0, 0, 5, 5, 4, 4, 3, 3, 0, 0, 5, 5, 4, 4, 3, 3};
|
||||
|
||||
#define RB(y,u,v) (((y)&0x3FF)<<22)|(((u)&0x3FF)<<11)|((v)&0x3FF)
|
||||
#define GO(y,v) ((((y)+64)&0x3FF)<<22)|(16<<11)|(((v)+16)&0x3FF)
|
||||
static const uint32_t DiffTable[128] = {
|
||||
RB(-85, 160, 80), RB(-83, 155, 77), RB(-80, 150, 75), RB(-77, 145, 72),
|
||||
RB(-75, 140, 70), RB(-72, 135, 67), RB(-69, 130, 65), RB(-67, 125, 62),
|
||||
RB(-64, 120, 60), RB(-61, 115, 57), RB(-59, 110, 55), RB(-56, 105, 52),
|
||||
RB(-53, 100, 50), RB(-51, 95, 47), RB(-48, 90, 45), RB(-45, 85, 42),
|
||||
RB(-43, 80, 40), RB(-40, 75, 37), RB(-37, 70, 35), RB(-35, 65, 32),
|
||||
RB(-32, 60, 30), RB(-29, 55, 27), RB(-27, 50, 25), RB(-24, 45, 22),
|
||||
RB(-21, 40, 20), RB(-19, 35, 17), RB(-16, 30, 15), RB(-13, 25, 12),
|
||||
RB(-11, 20, 10), RB( -8, 15, 7), RB( -5, 10, 5), RB( -3, 5, 2),
|
||||
RB( 0, 0, 0), RB( 2, -5, -2), RB( 5, -10, -5), RB( 7, -15, -7),
|
||||
RB( 10, -20, -10), RB( 13, -25, -12), RB( 15, -30, -15), RB( 18, -35, -17),
|
||||
RB( 21, -40, -20), RB( 23, -45, -22), RB( 26, -50, -25), RB( 29, -55, -27),
|
||||
RB( 31, -60, -30), RB( 34, -65, -32), RB( 37, -70, -35), RB( 39, -75, -37),
|
||||
RB( 42, -80, -40), RB( 45, -85, -42), RB( 47, -90, -45), RB( 50, -95, -47),
|
||||
RB( 53,-100, -50), RB( 55,-105, -52), RB( 58,-110, -55), RB( 61,-115, -57),
|
||||
RB( 63,-120, -60), RB( 66,-125, -62), RB( 69,-130, -65), RB( 71,-135, -67),
|
||||
RB( 74,-140, -70), RB( 77,-145, -72), RB( 79,-150, -75), RB( 82,-155, -77),
|
||||
GO(-84, -160), GO(-81, -155), GO(-78, -150), GO(-76, -145),
|
||||
GO(-73, -140), GO(-70, -135), GO(-68, -130), GO(-65, -125),
|
||||
GO(-63, -120), GO(-60, -115), GO(-57, -110), GO(-55, -105),
|
||||
GO(-52, -100), GO(-49, -95), GO(-47, -90), GO(-44, -85),
|
||||
GO(-42, -80), GO(-39, -75), GO(-36, -70), GO(-34, -65),
|
||||
GO(-31, -60), GO(-28, -55), GO(-26, -50), GO(-23, -45),
|
||||
GO(-21, -40), GO(-18, -35), GO(-15, -30), GO(-13, -25),
|
||||
GO(-10, -20), GO( -7, -15), GO( -5, -10), GO( -2, -5),
|
||||
GO( 0, 0), GO( 2, 4), GO( 5, 9), GO( 7, 14),
|
||||
GO( 10, 19), GO( 13, 24), GO( 15, 29), GO( 18, 34),
|
||||
GO( 21, 39), GO( 23, 44), GO( 26, 49), GO( 28, 54),
|
||||
GO( 31, 59), GO( 34, 64), GO( 36, 69), GO( 39, 74),
|
||||
GO( 42, 79), GO( 44, 84), GO( 47, 89), GO( 49, 94),
|
||||
GO( 52, 99), GO( 55, 104), GO( 57, 109), GO( 60, 114),
|
||||
GO( 63, 119), GO( 65, 124), GO( 68, 129), GO( 70, 134),
|
||||
GO( 73, 139), GO( 76, 144), GO( 78, 149), GO( 81, 154)};
|
||||
|
||||
inline static int ExpandedDiff (uint32_t c0, uint32_t c1) {
|
||||
uint32_t r, g;
|
||||
g = c0;
|
||||
g += 0x4008020;
|
||||
g -= c1;
|
||||
r = DiffTable[(int)((unsigned char)g) + 0];
|
||||
r ^= (0x3FF << 11);
|
||||
g >>= 10;
|
||||
r += DiffTable[(int)((unsigned char)g) + 0];
|
||||
g >>= 11;
|
||||
r += DiffTable[(int)((unsigned char)g) + 64];
|
||||
r &= 0xE01F03E0;
|
||||
return r;
|
||||
}
|
||||
|
||||
#define DIFF56 0x001
|
||||
#define DIFF52 0x002
|
||||
#define DIFF54 0x004
|
||||
#define DIFF58 0x008
|
||||
#define DIFF53 0x010
|
||||
#define DIFF51 0x020
|
||||
#define DIFF57 0x040
|
||||
#define DIFF59 0x080
|
||||
#define DIFF26 0x100
|
||||
#define DIFF24 0x200
|
||||
#define DIFF84 0x400
|
||||
#define DIFF86 0x800
|
||||
|
||||
/* lastLineDiffs is previous line's 52, 53, 26, all >> 1 */
|
||||
|
||||
static uint8_t lastLineDiffs[__PAST_LIBRARY_WIDTH];
|
||||
|
||||
#define RotatePattern(x) ((((x) & 0x777) << 1) | (((x) & 0x888) >> 3))
|
||||
|
||||
void ProcessHQ2x(const pixel * restrict in, pixel * restrict out) {
|
||||
signed int y, x;
|
||||
unsigned int pattern, newpattern;
|
||||
uint32_t pixels[9];
|
||||
int prevline, nextline;
|
||||
|
||||
memset(lastLineDiffs, 0, sizeof(lastLineDiffs));
|
||||
prevline = 1;
|
||||
nextline = 1 + __PAST_LIBRARY_WIDTH;
|
||||
y = __PAST_LIBRARY_HEIGHT - 1;
|
||||
|
||||
do {
|
||||
pixels[1-1] =
|
||||
pixels[2-1] = RGBUnpack(in[prevline-1]); /* Pixel 2 */
|
||||
pixels[3-1] = RGBUnpack(in[prevline ]); /* Pixel 3 */
|
||||
|
||||
pixels[4-1] =
|
||||
pixels[5-1] = RGBUnpack(in[ 0]); /* Pixel 5 */
|
||||
pixels[6-1] = RGBUnpack(in[ 1]); /* Pixel 6 */
|
||||
|
||||
pixels[7-1] =
|
||||
pixels[8-1] = RGBUnpack(in[nextline-1]); /* Pixel 8 */
|
||||
pixels[9-1] = RGBUnpack(in[nextline ]); /* Pixel 9 */
|
||||
|
||||
pattern = 0;
|
||||
|
||||
x = __PAST_LIBRARY_WIDTH - 1;
|
||||
do {
|
||||
newpattern = 0;
|
||||
if (pattern & DIFF26) newpattern |= DIFF51;
|
||||
if (pattern & DIFF56) newpattern |= DIFF54;
|
||||
if (pattern & DIFF86) newpattern |= DIFF57;
|
||||
if (pattern & DIFF53) newpattern |= DIFF24;
|
||||
if (pattern & DIFF59) newpattern |= DIFF84;
|
||||
|
||||
if (lastLineDiffs[x] & (DIFF52 >> 1)) newpattern |= DIFF58;
|
||||
if (lastLineDiffs[x] & (DIFF26 >> 1)) newpattern |= DIFF59;
|
||||
if (lastLineDiffs[x] & (DIFF53 >> 1)) newpattern |= DIFF86;
|
||||
|
||||
pattern = newpattern;
|
||||
|
||||
if (ExpandedDiff(pixels[5-1], pixels[2-1])) pattern |= DIFF52;
|
||||
if (ExpandedDiff(pixels[5-1], pixels[3-1])) pattern |= DIFF53;
|
||||
if (ExpandedDiff(pixels[5-1], pixels[6-1])) pattern |= DIFF56;
|
||||
if (ExpandedDiff(pixels[2-1], pixels[6-1])) pattern |= DIFF26;
|
||||
lastLineDiffs[x] = pattern >> 1;
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[ 0] =
|
||||
RGBPack(((pixels[5-1] * blends_2x[(newpattern * 4) + 0]) +
|
||||
(pixels[2-1] * blends_2x[(newpattern * 4) + 1]) +
|
||||
(pixels[4-1] * blends_2x[(newpattern * 4) + 2]) +
|
||||
(pixels[1-1] * blends_2x[(newpattern * 4) + 3])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[ 1] =
|
||||
RGBPack(((pixels[5-1] * blends_2x[(newpattern * 4) + 0]) +
|
||||
(pixels[6-1] * blends_2x[(newpattern * 4) + 1]) +
|
||||
(pixels[2-1] * blends_2x[(newpattern * 4) + 2]) +
|
||||
(pixels[3-1] * blends_2x[(newpattern * 4) + 3])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[(__PAST_LIBRARY_WIDTH*2)+1] =
|
||||
RGBPack(((pixels[5-1] * blends_2x[(newpattern * 4) + 0]) +
|
||||
(pixels[8-1] * blends_2x[(newpattern * 4) + 1]) +
|
||||
(pixels[6-1] * blends_2x[(newpattern * 4) + 2]) +
|
||||
(pixels[9-1] * blends_2x[(newpattern * 4) + 3])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[(__PAST_LIBRARY_WIDTH*2) ] =
|
||||
RGBPack(((pixels[5-1] * blends_2x[(newpattern * 4) + 0]) +
|
||||
(pixels[4-1] * blends_2x[(newpattern * 4) + 1]) +
|
||||
(pixels[8-1] * blends_2x[(newpattern * 4) + 2]) +
|
||||
(pixels[7-1] * blends_2x[(newpattern * 4) + 3])) / 16);
|
||||
|
||||
out += 2;
|
||||
in++;
|
||||
x--;
|
||||
|
||||
if (x == 0) {
|
||||
pixels[1-1] = pixels[2-1];
|
||||
pixels[2-1] = pixels[3-1];
|
||||
pixels[4-1] = pixels[5-1];
|
||||
pixels[5-1] = pixels[6-1];
|
||||
pixels[7-1] = pixels[8-1];
|
||||
pixels[8-1] = pixels[9-1];
|
||||
continue;
|
||||
}
|
||||
|
||||
pixels[1-1] = pixels[2-1];
|
||||
pixels[2-1] = pixels[3-1];
|
||||
pixels[3-1] = RGBUnpack(in[prevline]); /* Pixel 3 */
|
||||
pixels[4-1] = pixels[5-1];
|
||||
pixels[5-1] = pixels[6-1];
|
||||
pixels[6-1] = RGBUnpack(in[1 ]); /* Pixel 6 */
|
||||
pixels[7-1] = pixels[8-1];
|
||||
pixels[8-1] = pixels[9-1];
|
||||
pixels[9-1] = RGBUnpack(in[nextline]); /* Pixel 9 */
|
||||
} while (x >= 0);
|
||||
|
||||
prevline = 1 - __PAST_LIBRARY_WIDTH;
|
||||
out += (__PAST_LIBRARY_WIDTH * 2);
|
||||
|
||||
y--;
|
||||
if (y > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nextline = 0;
|
||||
} while (y >= 0);
|
||||
}
|
||||
|
||||
void ProcessHQ4x(const pixel * restrict in, pixel * restrict out) {
|
||||
signed int y, x;
|
||||
unsigned int pattern, newpattern;
|
||||
uint32_t pixels[9];
|
||||
int prevline, nextline;
|
||||
|
||||
memset(lastLineDiffs, 0, sizeof(lastLineDiffs));
|
||||
prevline = 1;
|
||||
nextline = 1 + __PAST_LIBRARY_WIDTH;
|
||||
y = __PAST_LIBRARY_HEIGHT - 1;
|
||||
|
||||
do {
|
||||
pixels[1-1] =
|
||||
pixels[2-1] = RGBUnpack(in[prevline-1]); /* Pixel 2 */
|
||||
pixels[3-1] = RGBUnpack(in[prevline ]); /* Pixel 3 */
|
||||
|
||||
pixels[4-1] =
|
||||
pixels[5-1] = RGBUnpack(in[ 0]); /* Pixel 5 */
|
||||
pixels[6-1] = RGBUnpack(in[ 1]); /* Pixel 6 */
|
||||
|
||||
pixels[7-1] =
|
||||
pixels[8-1] = RGBUnpack(in[nextline-1]); /* Pixel 8 */
|
||||
pixels[9-1] = RGBUnpack(in[nextline ]); /* Pixel 9 */
|
||||
|
||||
pattern = 0;
|
||||
|
||||
x = __PAST_LIBRARY_WIDTH - 1;
|
||||
do {
|
||||
newpattern = 0;
|
||||
if (pattern & DIFF26) newpattern |= DIFF51;
|
||||
if (pattern & DIFF56) newpattern |= DIFF54;
|
||||
if (pattern & DIFF86) newpattern |= DIFF57;
|
||||
if (pattern & DIFF53) newpattern |= DIFF24;
|
||||
if (pattern & DIFF59) newpattern |= DIFF84;
|
||||
|
||||
if (lastLineDiffs[x] & (DIFF52 >> 1)) newpattern |= DIFF58;
|
||||
if (lastLineDiffs[x] & (DIFF26 >> 1)) newpattern |= DIFF59;
|
||||
if (lastLineDiffs[x] & (DIFF53 >> 1)) newpattern |= DIFF86;
|
||||
|
||||
pattern = newpattern;
|
||||
|
||||
if (ExpandedDiff(pixels[5-1], pixels[2-1])) pattern |= DIFF52;
|
||||
if (ExpandedDiff(pixels[5-1], pixels[3-1])) pattern |= DIFF53;
|
||||
if (ExpandedDiff(pixels[5-1], pixels[6-1])) pattern |= DIFF56;
|
||||
if (ExpandedDiff(pixels[2-1], pixels[6-1])) pattern |= DIFF26;
|
||||
lastLineDiffs[x] = pattern >> 1;
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[ 0] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x0]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 1 + 0x0]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 2 + 0x0]) +
|
||||
(pixels[1-1] * blends_4x[(newpattern * 16) + 3 + 0x0])) / 16);
|
||||
out[ 1] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x4]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 1 + 0x4]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 2 + 0x4]) +
|
||||
(pixels[1-1] * blends_4x[(newpattern * 16) + 3 + 0x4])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x4) ] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x8]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 1 + 0x8]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 2 + 0x8]) +
|
||||
(pixels[1-1] * blends_4x[(newpattern * 16) + 3 + 0x8])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x4)+1] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0xC]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 1 + 0xC]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 2 + 0xC]) +
|
||||
(pixels[1-1] * blends_4x[(newpattern * 16) + 3 + 0xC])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[ 3] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x0]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 1 + 0x0]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 2 + 0x0]) +
|
||||
(pixels[3-1] * blends_4x[(newpattern * 16) + 3 + 0x0])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x4)+3] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x4]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 1 + 0x4]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 2 + 0x4]) +
|
||||
(pixels[3-1] * blends_4x[(newpattern * 16) + 3 + 0x4])) / 16);
|
||||
out[ 2] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x8]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 1 + 0x8]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 2 + 0x8]) +
|
||||
(pixels[3-1] * blends_4x[(newpattern * 16) + 3 + 0x8])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x4)+2] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0xC]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 1 + 0xC]) +
|
||||
(pixels[2-1] * blends_4x[(newpattern * 16) + 2 + 0xC]) +
|
||||
(pixels[3-1] * blends_4x[(newpattern * 16) + 3 + 0xC])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[(__PAST_LIBRARY_WIDTH*0xC)+3] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x0]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 1 + 0x0]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 2 + 0x0]) +
|
||||
(pixels[9-1] * blends_4x[(newpattern * 16) + 3 + 0x0])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0xC)+2] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x4]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 1 + 0x4]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 2 + 0x4]) +
|
||||
(pixels[9-1] * blends_4x[(newpattern * 16) + 3 + 0x4])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x8)+3] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x8]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 1 + 0x8]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 2 + 0x8]) +
|
||||
(pixels[9-1] * blends_4x[(newpattern * 16) + 3 + 0x8])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x8)+2] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0xC]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 1 + 0xC]) +
|
||||
(pixels[6-1] * blends_4x[(newpattern * 16) + 2 + 0xC]) +
|
||||
(pixels[9-1] * blends_4x[(newpattern * 16) + 3 + 0xC])) / 16);
|
||||
|
||||
newpattern = tree_hq[pattern & 0x7FF];
|
||||
pattern = RotatePattern(pattern);
|
||||
out[(__PAST_LIBRARY_WIDTH*0xC) ] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x0]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 1 + 0x0]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 2 + 0x0]) +
|
||||
(pixels[7-1] * blends_4x[(newpattern * 16) + 3 + 0x0])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x8) ] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x4]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 1 + 0x4]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 2 + 0x4]) +
|
||||
(pixels[7-1] * blends_4x[(newpattern * 16) + 3 + 0x4])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0xC)+1] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0x8]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 1 + 0x8]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 2 + 0x8]) +
|
||||
(pixels[7-1] * blends_4x[(newpattern * 16) + 3 + 0x8])) / 16);
|
||||
out[(__PAST_LIBRARY_WIDTH*0x8)+1] =
|
||||
RGBPack(((pixels[5-1] * blends_4x[(newpattern * 16) + 0 + 0xC]) +
|
||||
(pixels[4-1] * blends_4x[(newpattern * 16) + 1 + 0xC]) +
|
||||
(pixels[8-1] * blends_4x[(newpattern * 16) + 2 + 0xC]) +
|
||||
(pixels[7-1] * blends_4x[(newpattern * 16) + 3 + 0xC])) / 16);
|
||||
|
||||
out += 4;
|
||||
in++;
|
||||
x--;
|
||||
|
||||
if (x == 0) {
|
||||
pixels[1-1] = pixels[2-1];
|
||||
pixels[2-1] = pixels[3-1];
|
||||
pixels[4-1] = pixels[5-1];
|
||||
pixels[5-1] = pixels[6-1];
|
||||
pixels[7-1] = pixels[8-1];
|
||||
pixels[8-1] = pixels[9-1];
|
||||
continue;
|
||||
}
|
||||
|
||||
pixels[1-1] = pixels[2-1];
|
||||
pixels[2-1] = pixels[3-1];
|
||||
pixels[3-1] = RGBUnpack(in[prevline]); /* Pixel 3 */
|
||||
pixels[4-1] = pixels[5-1];
|
||||
pixels[5-1] = pixels[6-1];
|
||||
pixels[6-1] = RGBUnpack(in[1 ]); /* Pixel 6 */
|
||||
pixels[7-1] = pixels[8-1];
|
||||
pixels[8-1] = pixels[9-1];
|
||||
pixels[9-1] = RGBUnpack(in[nextline]); /* Pixel 9 */
|
||||
} while (x >= 0);
|
||||
|
||||
prevline = 1 - __PAST_LIBRARY_WIDTH;
|
||||
out += (__PAST_LIBRARY_WIDTH * 0xC);
|
||||
|
||||
y--;
|
||||
if (y > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nextline = 0;
|
||||
} while (y >= 0);
|
||||
}
|
19
hqflt/ntsc.c
19
hqflt/ntsc.c
@ -1,19 +0,0 @@
|
||||
#include "ntsc.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void ntsc_filter(uint16_t * restrict out, const uint16_t * restrict in, int width, int height)
|
||||
{
|
||||
static int phase = 0;
|
||||
static snes_ntsc_t ntsc;
|
||||
static bool inited = false;
|
||||
|
||||
if (inited == false)
|
||||
{
|
||||
snes_ntsc_init(&ntsc, &snes_ntsc_composite);
|
||||
inited = true;
|
||||
}
|
||||
|
||||
snes_ntsc_blit(&ntsc, in, width, phase, width, height, out, SNES_NTSC_OUT_WIDTH(width) * sizeof(uint16_t));
|
||||
phase ^= 1;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
|
||||
#ifndef _NTSC_FILTER_H
|
||||
#define _NTSC_FILTER_H
|
||||
#include <stdint.h>
|
||||
#include "snes_ntsc/snes_ntsc.h"
|
||||
|
||||
void ntsc_filter(uint16_t * restrict out, const uint16_t * restrict in, int width, int height);
|
||||
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
/* This source code is Copyright (C) 2006-2009 by WolfWings. */
|
||||
/* It is, however, released under the ISC license. */
|
||||
/* en.wikipedia.org/wiki/ISC_Licence */
|
||||
/* --------------------------------------------------------- */
|
||||
/* It is a formula-level rederiviation of the HQ2x technique */
|
||||
/* and is, thus, not a derivative work of the original code, */
|
||||
/* only the original equations behind the code. */
|
||||
|
||||
#ifndef __PAST_LIBRARY_H
|
||||
#define __PAST_LIBRARY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __PAST_LIBRARY_WIDTH
|
||||
#define __PAST_LIBRARY_WIDTH 256
|
||||
#endif
|
||||
|
||||
#ifndef __PAST_LIBRARY_HEIGHT
|
||||
#define __PAST_LIBRARY_HEIGHT 224
|
||||
#endif
|
||||
|
||||
typedef uint16_t pixel;
|
||||
|
||||
/* These two functions are what need to be modified to interface other
|
||||
* pixel formats with the library. They need to return values inside a
|
||||
* format like this: (Red/Blue can be reversed.)
|
||||
*
|
||||
* 0000-00GG-GGG0-0000-0RRR-RR00-000B-BBBB
|
||||
*
|
||||
* This is VERY fast to create from 15-bit (NOT 16-bit) RGB/BGR, as
|
||||
* below.
|
||||
*
|
||||
* If you can't return data in this format, you'll have to rebuild the
|
||||
* ExpandedDiff function and DiffTable array to compensate, and possibly
|
||||
* change the blending functions in the Process* functions to handle any
|
||||
* guard-bits and masking.
|
||||
*/
|
||||
|
||||
static inline uint32_t RGBUnpack(pixel i) {
|
||||
uint32_t o = i;
|
||||
o = (o * 0x10001);
|
||||
o = o & 0x03E07C1F;
|
||||
return o;
|
||||
}
|
||||
static inline pixel RGBPack(uint32_t x) {
|
||||
x &= 0x03E07C1F;
|
||||
x |= (x >> 16);
|
||||
return x;
|
||||
}
|
||||
|
||||
void ProcessHQ2x(const pixel * restrict inbuffer, pixel * restrict outbuffer);
|
||||
void ProcessHQ4x(const pixel * restrict inbuffer, pixel * restrict outbuffer);
|
||||
|
||||
#endif /* __PAST_LIBRARY_H */
|
@ -1,251 +0,0 @@
|
||||
/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
|
||||
#include "snes_ntsc.h"
|
||||
|
||||
/* Copyright (C) 2006-2007 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 };
|
||||
snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 };
|
||||
|
||||
#define alignment_count 3
|
||||
#define burst_count 3
|
||||
#define rescale_in 8
|
||||
#define rescale_out 7
|
||||
|
||||
#define artifacts_mid 1.0f
|
||||
#define fringing_mid 1.0f
|
||||
#define std_decoder_hue 0
|
||||
|
||||
#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */
|
||||
#define gamma_size 32
|
||||
|
||||
#include "snes_ntsc_impl.h"
|
||||
|
||||
/* 3 input pixels -> 8 composite samples */
|
||||
pixel_info_t const snes_ntsc_pixels [alignment_count] = {
|
||||
{ PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } },
|
||||
{ PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } },
|
||||
{ PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } },
|
||||
};
|
||||
|
||||
static void merge_kernel_fields( snes_ntsc_rgb_t* io )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_size; n; --n )
|
||||
{
|
||||
snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias;
|
||||
snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias;
|
||||
snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias;
|
||||
/* merge colors without losing precision */
|
||||
io [burst_size * 0] =
|
||||
((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 1] =
|
||||
((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
io [burst_size * 2] =
|
||||
((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias;
|
||||
++io;
|
||||
}
|
||||
}
|
||||
|
||||
static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out )
|
||||
{
|
||||
int n;
|
||||
for ( n = burst_count; n; --n )
|
||||
{
|
||||
unsigned i;
|
||||
for ( i = 0; i < rgb_kernel_size / 2; i++ )
|
||||
{
|
||||
snes_ntsc_rgb_t error = color -
|
||||
out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] -
|
||||
out [i + 7] - out [i + 5 +14] - out [i + 3 +28];
|
||||
DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 );
|
||||
}
|
||||
out += alignment_count * rgb_kernel_size;
|
||||
}
|
||||
}
|
||||
|
||||
void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
int merge_fields;
|
||||
int entry;
|
||||
init_t impl;
|
||||
if ( !setup )
|
||||
setup = &snes_ntsc_composite;
|
||||
init( &impl, setup );
|
||||
|
||||
merge_fields = setup->merge_fields;
|
||||
if ( setup->artifacts <= -1 && setup->fringing <= -1 )
|
||||
merge_fields = 1;
|
||||
|
||||
for ( entry = 0; entry < snes_ntsc_palette_size; entry++ )
|
||||
{
|
||||
/* Reduce number of significant bits of source color. Clearing the
|
||||
low bits of R and B were least notictable. Modifying green was too
|
||||
noticeable. */
|
||||
int ir = entry >> 8 & 0x1E;
|
||||
int ig = entry >> 4 & 0x1F;
|
||||
int ib = entry << 1 & 0x1E;
|
||||
|
||||
#if SNES_NTSC_BSNES_COLORTBL
|
||||
if ( setup->bsnes_colortbl )
|
||||
{
|
||||
int bgr15 = (ib << 10) | (ig << 5) | ir;
|
||||
unsigned long rgb16 = setup->bsnes_colortbl [bgr15];
|
||||
ir = rgb16 >> 11 & 0x1E;
|
||||
ig = rgb16 >> 6 & 0x1F;
|
||||
ib = rgb16 & 0x1E;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
float rr = impl.to_float [ir];
|
||||
float gg = impl.to_float [ig];
|
||||
float bb = impl.to_float [ib];
|
||||
|
||||
float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i );
|
||||
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g );
|
||||
snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b );
|
||||
|
||||
snes_ntsc_rgb_t* out = ntsc->table [entry];
|
||||
gen_kernel( &impl, y, i, q, out );
|
||||
if ( merge_fields )
|
||||
merge_kernel_fields( out );
|
||||
correct_errors( rgb, out );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SNES_NTSC_NO_BLITTERS
|
||||
|
||||
void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 1) / snes_ntsc_in_chunk;
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
SNES_NTSC_IN_T const* line_in = input;
|
||||
SNES_NTSC_BEGIN_ROW( ntsc, burst_phase,
|
||||
snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) );
|
||||
snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
++line_in;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* order of input and output pixels must not be altered */
|
||||
SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
line_in += 3;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
/* finish final pixels */
|
||||
SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
|
||||
SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width,
|
||||
int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch )
|
||||
{
|
||||
int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2);
|
||||
for ( ; in_height; --in_height )
|
||||
{
|
||||
SNES_NTSC_IN_T const* line_in = input;
|
||||
SNES_NTSC_HIRES_ROW( ntsc, burst_phase,
|
||||
snes_ntsc_black, snes_ntsc_black, snes_ntsc_black,
|
||||
SNES_NTSC_ADJ_IN( line_in [0] ),
|
||||
SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out;
|
||||
int n;
|
||||
line_in += 2;
|
||||
|
||||
for ( n = chunk_count; n; --n )
|
||||
{
|
||||
/* twice as many input pixels per chunk */
|
||||
SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) );
|
||||
SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) );
|
||||
SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) );
|
||||
SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) );
|
||||
SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) );
|
||||
SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) );
|
||||
SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
line_in += 6;
|
||||
line_out += 7;
|
||||
}
|
||||
|
||||
SNES_NTSC_COLOR_IN( 0, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 1, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 2, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 3, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 4, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
SNES_NTSC_COLOR_IN( 5, snes_ntsc_black );
|
||||
SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH );
|
||||
SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH );
|
||||
|
||||
burst_phase = (burst_phase + 1) % snes_ntsc_burst_count;
|
||||
input += in_row_width;
|
||||
rgb_out = (char*) rgb_out + out_pitch;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -1,236 +0,0 @@
|
||||
/* SNES NTSC video filter */
|
||||
|
||||
/* snes_ntsc 0.2.2 */
|
||||
#ifndef SNES_NTSC_H
|
||||
#define SNES_NTSC_H
|
||||
|
||||
#include "snes_ntsc_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown
|
||||
in parenthesis and should remain fairly stable in future versions. */
|
||||
typedef struct snes_ntsc_setup_t
|
||||
{
|
||||
/* Basic parameters */
|
||||
double hue; /* -1 = -180 degrees +1 = +180 degrees */
|
||||
double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */
|
||||
double contrast; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double brightness; /* -1 = dark (0.5) +1 = light (1.5) */
|
||||
double sharpness; /* edge contrast enhancement/blurring */
|
||||
|
||||
/* Advanced parameters */
|
||||
double gamma; /* -1 = dark (1.5) +1 = light (0.5) */
|
||||
double resolution; /* image resolution */
|
||||
double artifacts; /* artifacts caused by color changes */
|
||||
double fringing; /* color artifacts caused by brightness changes */
|
||||
double bleed; /* color bleed (color resolution reduction) */
|
||||
int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */
|
||||
float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */
|
||||
|
||||
unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */
|
||||
} snes_ntsc_setup_t;
|
||||
|
||||
/* Video format presets */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */
|
||||
extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */
|
||||
|
||||
/* Initializes and adjusts parameters. Can be called multiple times on the same
|
||||
snes_ntsc_t object. Can pass NULL for either parameter. */
|
||||
typedef struct snes_ntsc_t snes_ntsc_t;
|
||||
void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup );
|
||||
|
||||
/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT
|
||||
and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB.
|
||||
In_row_width is the number of pixels to get to the next input row. Out_pitch
|
||||
is the number of *bytes* to get to the next output row. */
|
||||
void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
|
||||
long in_row_width, int burst_phase, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input,
|
||||
long in_row_width, int burst_phase, int in_width, int in_height,
|
||||
void* rgb_out, long out_pitch );
|
||||
|
||||
/* Number of output pixels written by low-res blitter for given input width. Width
|
||||
might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded
|
||||
value. Guaranteed not to round 256 down at all. */
|
||||
#define SNES_NTSC_OUT_WIDTH( in_width ) \
|
||||
((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk)
|
||||
|
||||
/* Number of low-res input pixels that will fit within given output width. Might be
|
||||
rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded
|
||||
value. */
|
||||
#define SNES_NTSC_IN_WIDTH( out_width ) \
|
||||
(((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1)
|
||||
|
||||
|
||||
/* Interface for user-defined custom blitters */
|
||||
|
||||
enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */
|
||||
enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */
|
||||
enum { snes_ntsc_black = 0 }; /* palette index for black */
|
||||
enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */
|
||||
|
||||
/* Begins outputting row and starts three pixels. First pixel will be cut off a bit.
|
||||
Use snes_ntsc_black for unused pixels. Declares variables, so must be before first
|
||||
statement in a block (unless you're using C++). */
|
||||
#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \
|
||||
char const* ktable = \
|
||||
(char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
|
||||
SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable )
|
||||
|
||||
/* Begins input pixel */
|
||||
#define SNES_NTSC_COLOR_IN( index, color ) \
|
||||
SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable )
|
||||
|
||||
/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0:
|
||||
24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB)
|
||||
16: RRRRRGGG GGGBBBBB (5-6-5 RGB)
|
||||
15: RRRRRGG GGGBBBBB (5-5-5 RGB)
|
||||
14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format)
|
||||
0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */
|
||||
#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \
|
||||
SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 )
|
||||
|
||||
/* Hires equivalents */
|
||||
#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \
|
||||
char const* ktable = \
|
||||
(char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\
|
||||
unsigned const snes_ntsc_pixel1_ = (pixel1);\
|
||||
snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\
|
||||
unsigned const snes_ntsc_pixel2_ = (pixel2);\
|
||||
snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\
|
||||
unsigned const snes_ntsc_pixel3_ = (pixel3);\
|
||||
snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\
|
||||
unsigned const snes_ntsc_pixel4_ = (pixel4);\
|
||||
snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\
|
||||
unsigned const snes_ntsc_pixel5_ = (pixel5);\
|
||||
snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\
|
||||
snes_ntsc_rgb_t const* kernel0 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx0;\
|
||||
snes_ntsc_rgb_t const* kernelx1 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx2 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx3 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx4 = kernel1;\
|
||||
snes_ntsc_rgb_t const* kernelx5 = kernel1
|
||||
|
||||
#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\
|
||||
snes_ntsc_rgb_t raw_ =\
|
||||
kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\
|
||||
kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\
|
||||
kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\
|
||||
kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\
|
||||
SNES_NTSC_CLAMP_( raw_, 0 );\
|
||||
SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\
|
||||
}
|
||||
|
||||
|
||||
/* private */
|
||||
enum { snes_ntsc_entry_size = 128 };
|
||||
enum { snes_ntsc_palette_size = 0x2000 };
|
||||
typedef unsigned long snes_ntsc_rgb_t;
|
||||
struct snes_ntsc_t {
|
||||
snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size];
|
||||
};
|
||||
enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count };
|
||||
|
||||
#define SNES_NTSC_RGB16( ktable, n ) \
|
||||
(snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \
|
||||
(snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
|
||||
|
||||
#define SNES_NTSC_BGR15( ktable, n ) \
|
||||
(snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \
|
||||
(snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t)))
|
||||
|
||||
/* common 3->7 ntsc macros */
|
||||
#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \
|
||||
unsigned const snes_ntsc_pixel0_ = (pixel0);\
|
||||
snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\
|
||||
unsigned const snes_ntsc_pixel1_ = (pixel1);\
|
||||
snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\
|
||||
unsigned const snes_ntsc_pixel2_ = (pixel2);\
|
||||
snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\
|
||||
snes_ntsc_rgb_t const* kernelx0;\
|
||||
snes_ntsc_rgb_t const* kernelx1 = kernel0;\
|
||||
snes_ntsc_rgb_t const* kernelx2 = kernel0
|
||||
|
||||
#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\
|
||||
snes_ntsc_rgb_t raw_ =\
|
||||
kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\
|
||||
kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\
|
||||
SNES_NTSC_CLAMP_( raw_, shift );\
|
||||
SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\
|
||||
}
|
||||
|
||||
/* common ntsc macros */
|
||||
#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1))
|
||||
#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2)
|
||||
#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101)
|
||||
#define SNES_NTSC_CLAMP_( io, shift ) {\
|
||||
snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\
|
||||
snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\
|
||||
io |= clamp;\
|
||||
clamp -= sub;\
|
||||
io &= clamp;\
|
||||
}
|
||||
|
||||
#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\
|
||||
unsigned color_;\
|
||||
kernelx##index = kernel##index;\
|
||||
kernel##index = (color_ = (color), ENTRY( table, color_ ));\
|
||||
}
|
||||
|
||||
/* x is always zero except in snes_ntsc library */
|
||||
/* original routine */
|
||||
#if 0
|
||||
#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
if ( bits == 16 )\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 24 || bits == 32 )\
|
||||
rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\
|
||||
if ( bits == 15 )\
|
||||
rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
|
||||
if ( bits == 14 )\
|
||||
rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\
|
||||
if ( bits == 0 )\
|
||||
rgb_out = raw_ << x;\
|
||||
}
|
||||
#endif
|
||||
|
||||
#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
|
||||
}
|
||||
|
||||
// Custom SSNES routine for 15 bit.
|
||||
|
||||
/* custom bsnes routine -- hooks into bsnes colortable */
|
||||
#if 0
|
||||
#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\
|
||||
if ( bits == 16 ) {\
|
||||
rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\
|
||||
rgb_out = ((rgb_out&0xf800)>>11)|((rgb_out&0x07c0)>>1)|((rgb_out&0x001f)<<10);\
|
||||
rgb_out = colortable[rgb_out];\
|
||||
} else if ( bits == 24 || bits == 32 ) {\
|
||||
rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\
|
||||
rgb_out = ((rgb_out&0xf80000)>>19)|((rgb_out&0x00f800)>>6)|((rgb_out&0x0000f8)<<7);\
|
||||
rgb_out = colortable[rgb_out];\
|
||||
} else if ( bits == 15 ) {\
|
||||
rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\
|
||||
rgb_out = ((rgb_out&0x7c00)>>10)|((rgb_out&0x03e0))|((rgb_out&0x001f)<<10);\
|
||||
rgb_out = colortable[rgb_out];\
|
||||
} else {\
|
||||
rgb_out = raw_ << x;\
|
||||
}\
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -1,27 +0,0 @@
|
||||
/* Configure library by modifying this file */
|
||||
|
||||
#ifndef SNES_NTSC_CONFIG_H
|
||||
#define SNES_NTSC_CONFIG_H
|
||||
|
||||
/* Format of source pixels */
|
||||
/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 */
|
||||
#define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15
|
||||
|
||||
/* The following affect the built-in blitter only; a custom blitter can
|
||||
handle things however it wants. */
|
||||
|
||||
/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */
|
||||
#define SNES_NTSC_OUT_DEPTH 15
|
||||
|
||||
/* Type of input pixel values */
|
||||
#define SNES_NTSC_IN_T unsigned short
|
||||
|
||||
/* Each raw pixel input value is passed through this. You might want to mask
|
||||
the pixel index if you use the high bits as flags, etc. */
|
||||
#define SNES_NTSC_ADJ_IN( in ) (((in >> 10) & 0x1F) | (in & 0x3E0) | ((in << 10) & 0x7C00))
|
||||
|
||||
|
||||
/* For each pixel, this is the basic operation:
|
||||
output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */
|
||||
|
||||
#endif
|
@ -1,439 +0,0 @@
|
||||
/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */
|
||||
|
||||
/* Common implementation of NTSC filters */
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
/* Copyright (C) 2006 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#define DISABLE_CORRECTION 0
|
||||
|
||||
#undef PI
|
||||
#define PI 3.14159265358979323846f
|
||||
|
||||
#ifndef LUMA_CUTOFF
|
||||
#define LUMA_CUTOFF 0.20
|
||||
#endif
|
||||
#ifndef gamma_size
|
||||
#define gamma_size 1
|
||||
#endif
|
||||
#ifndef rgb_bits
|
||||
#define rgb_bits 8
|
||||
#endif
|
||||
#ifndef artifacts_max
|
||||
#define artifacts_max (artifacts_mid * 1.5f)
|
||||
#endif
|
||||
#ifndef fringing_max
|
||||
#define fringing_max (fringing_mid * 2)
|
||||
#endif
|
||||
#ifndef STD_HUE_CONDITION
|
||||
#define STD_HUE_CONDITION( setup ) 1
|
||||
#endif
|
||||
|
||||
#define ext_decoder_hue (std_decoder_hue + 15)
|
||||
#define rgb_unit (1 << rgb_bits)
|
||||
#define rgb_offset (rgb_unit * 2 + 0.5f)
|
||||
|
||||
enum { burst_size = snes_ntsc_entry_size / burst_count };
|
||||
enum { kernel_half = 16 };
|
||||
enum { kernel_size = kernel_half * 2 + 1 };
|
||||
|
||||
typedef struct init_t
|
||||
{
|
||||
float to_rgb [burst_count * 6];
|
||||
float to_float [gamma_size];
|
||||
float contrast;
|
||||
float brightness;
|
||||
float artifacts;
|
||||
float fringing;
|
||||
float kernel [rescale_out * kernel_size * 2];
|
||||
} init_t;
|
||||
|
||||
#define ROTATE_IQ( i, q, sin_b, cos_b ) {\
|
||||
float t;\
|
||||
t = i * cos_b - q * sin_b;\
|
||||
q = i * sin_b + q * cos_b;\
|
||||
i = t;\
|
||||
}
|
||||
|
||||
static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
#if rescale_out > 1
|
||||
float kernels [kernel_size * 2];
|
||||
#else
|
||||
float* const kernels = impl->kernel;
|
||||
#endif
|
||||
|
||||
/* generate luma (y) filter using sinc kernel */
|
||||
{
|
||||
/* sinc with rolloff (dsf) */
|
||||
float const rolloff = 1 + (float) setup->sharpness * (float) 0.032;
|
||||
float const maxh = 32;
|
||||
float const pow_a_n = (float) pow( rolloff, maxh );
|
||||
float sum;
|
||||
int i;
|
||||
/* quadratic mapping to reduce negative (blurring) range */
|
||||
float to_angle = (float) setup->resolution + 1;
|
||||
to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1);
|
||||
|
||||
kernels [kernel_size * 3 / 2] = maxh; /* default center value */
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = i - kernel_half;
|
||||
float angle = x * to_angle;
|
||||
/* instability occurs at center point with rolloff very close to 1.0 */
|
||||
if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 )
|
||||
{
|
||||
float rolloff_cos_a = rolloff * (float) cos( angle );
|
||||
float num = 1 - rolloff_cos_a -
|
||||
pow_a_n * (float) cos( maxh * angle ) +
|
||||
pow_a_n * rolloff * (float) cos( (maxh - 1) * angle );
|
||||
float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff;
|
||||
float dsf = num / den;
|
||||
kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply blackman window and find sum */
|
||||
sum = 0;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
float x = PI * 2 / (kernel_half * 2) * i;
|
||||
float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 );
|
||||
sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman);
|
||||
}
|
||||
|
||||
/* normalize kernel */
|
||||
sum = 1.0f / sum;
|
||||
for ( i = 0; i < kernel_half * 2 + 1; i++ )
|
||||
{
|
||||
int x = kernel_size * 3 / 2 - kernel_half + i;
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
|
||||
/* generate chroma (iq) filter using gaussian kernel */
|
||||
{
|
||||
float const cutoff_factor = -0.03125f;
|
||||
float cutoff = (float) setup->bleed;
|
||||
int i;
|
||||
|
||||
if ( cutoff < 0 )
|
||||
{
|
||||
/* keep extreme value accessible only near upper end of scale (1.0) */
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= cutoff;
|
||||
cutoff *= -30.0f / 0.65f;
|
||||
}
|
||||
cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff;
|
||||
|
||||
for ( i = -kernel_half; i <= kernel_half; i++ )
|
||||
kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff );
|
||||
|
||||
/* normalize even and odd phases separately */
|
||||
for ( i = 0; i < 2; i++ )
|
||||
{
|
||||
float sum = 0;
|
||||
int x;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
sum += kernels [x];
|
||||
|
||||
sum = 1.0f / sum;
|
||||
for ( x = i; x < kernel_size; x += 2 )
|
||||
{
|
||||
kernels [x] *= sum;
|
||||
assert( kernels [x] == kernels [x] ); /* catch numerical instability */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
printf( "luma:\n" );
|
||||
for ( i = kernel_size; i < kernel_size * 2; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
printf( "chroma:\n" );
|
||||
for ( i = 0; i < kernel_size; i++ )
|
||||
printf( "%f\n", kernels [i] );
|
||||
*/
|
||||
|
||||
/* generate linear rescale kernels */
|
||||
#if rescale_out > 1
|
||||
{
|
||||
float weight = 1.0f;
|
||||
float* out = impl->kernel;
|
||||
int n = rescale_out;
|
||||
do
|
||||
{
|
||||
float remain = 0;
|
||||
int i;
|
||||
weight -= 1.0f / rescale_in;
|
||||
for ( i = 0; i < kernel_size * 2; i++ )
|
||||
{
|
||||
float cur = kernels [i];
|
||||
float m = cur * weight;
|
||||
*out++ = m + remain;
|
||||
remain = cur - m;
|
||||
}
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static float const default_decoder [6] =
|
||||
{ 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f };
|
||||
|
||||
static void init( init_t* impl, snes_ntsc_setup_t const* setup )
|
||||
{
|
||||
impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset;
|
||||
impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit;
|
||||
#ifdef default_palette_contrast
|
||||
if ( !setup->palette )
|
||||
impl->contrast *= default_palette_contrast;
|
||||
#endif
|
||||
|
||||
impl->artifacts = (float) setup->artifacts;
|
||||
if ( impl->artifacts > 0 )
|
||||
impl->artifacts *= artifacts_max - artifacts_mid;
|
||||
impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid;
|
||||
|
||||
impl->fringing = (float) setup->fringing;
|
||||
if ( impl->fringing > 0 )
|
||||
impl->fringing *= fringing_max - fringing_mid;
|
||||
impl->fringing = impl->fringing * fringing_mid + fringing_mid;
|
||||
|
||||
init_filters( impl, setup );
|
||||
|
||||
/* generate gamma table */
|
||||
if ( gamma_size > 1 )
|
||||
{
|
||||
float const to_float = 1.0f / (gamma_size - (gamma_size > 1));
|
||||
float const gamma = 1.1333f - (float) setup->gamma * 0.5f;
|
||||
/* match common PC's 2.2 gamma to TV's 2.65 gamma */
|
||||
int i;
|
||||
for ( i = 0; i < gamma_size; i++ )
|
||||
impl->to_float [i] =
|
||||
(float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness;
|
||||
}
|
||||
|
||||
/* setup decoder matricies */
|
||||
{
|
||||
float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue;
|
||||
float sat = (float) setup->saturation + 1;
|
||||
float const* decoder = setup->decoder_matrix;
|
||||
if ( !decoder )
|
||||
{
|
||||
decoder = default_decoder;
|
||||
if ( STD_HUE_CONDITION( setup ) )
|
||||
hue += PI / 180 * (std_decoder_hue - ext_decoder_hue);
|
||||
}
|
||||
|
||||
{
|
||||
float s = (float) sin( hue ) * sat;
|
||||
float c = (float) cos( hue ) * sat;
|
||||
float* out = impl->to_rgb;
|
||||
int n;
|
||||
|
||||
n = burst_count;
|
||||
do
|
||||
{
|
||||
float const* in = decoder;
|
||||
int n = 3;
|
||||
do
|
||||
{
|
||||
float i = *in++;
|
||||
float q = *in++;
|
||||
*out++ = i * c - q * s;
|
||||
*out++ = i * s + q * c;
|
||||
}
|
||||
while ( --n );
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */
|
||||
}
|
||||
while ( --n );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* kernel generation */
|
||||
|
||||
#define RGB_TO_YIQ( r, g, b, y, i ) (\
|
||||
(y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\
|
||||
(i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\
|
||||
((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\
|
||||
)
|
||||
|
||||
#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\
|
||||
r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\
|
||||
g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\
|
||||
(type) (y + to_rgb [4] * i + to_rgb [5] * q)\
|
||||
)
|
||||
|
||||
#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1)
|
||||
|
||||
enum { rgb_kernel_size = burst_size / alignment_count };
|
||||
enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder };
|
||||
|
||||
typedef struct pixel_info_t
|
||||
{
|
||||
int offset;
|
||||
float negate;
|
||||
float kernel [4];
|
||||
} pixel_info_t;
|
||||
|
||||
#if rescale_in > 1
|
||||
#define PIXEL_OFFSET_( ntsc, scaled ) \
|
||||
(kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \
|
||||
(kernel_size * 2 * scaled))
|
||||
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\
|
||||
(((scaled) + rescale_out * 10) % rescale_out) ),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#else
|
||||
#define PIXEL_OFFSET( ntsc, scaled ) \
|
||||
(kernel_size / 2 + (ntsc) - (scaled)),\
|
||||
(1.0f - (((ntsc) + 100) & 2))
|
||||
#endif
|
||||
|
||||
extern pixel_info_t const snes_ntsc_pixels [alignment_count];
|
||||
|
||||
/* Generate pixel at all burst phases and column alignments */
|
||||
static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out )
|
||||
{
|
||||
/* generate for each scanline burst phase */
|
||||
float const* to_rgb = impl->to_rgb;
|
||||
int burst_remain = burst_count;
|
||||
y -= rgb_offset;
|
||||
do
|
||||
{
|
||||
/* Encode yiq into *two* composite signals (to allow control over artifacting).
|
||||
Convolve these with kernels which: filter respective components, apply
|
||||
sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack
|
||||
into integer. Based on algorithm by NewRisingSun. */
|
||||
pixel_info_t const* pixel = snes_ntsc_pixels;
|
||||
int alignment_remain = alignment_count;
|
||||
do
|
||||
{
|
||||
/* negate is -1 when composite starts at odd multiple of 2 */
|
||||
float const yy = y * impl->fringing * pixel->negate;
|
||||
float const ic0 = (i + yy) * pixel->kernel [0];
|
||||
float const qc1 = (q + yy) * pixel->kernel [1];
|
||||
float const ic2 = (i - yy) * pixel->kernel [2];
|
||||
float const qc3 = (q - yy) * pixel->kernel [3];
|
||||
|
||||
float const factor = impl->artifacts * pixel->negate;
|
||||
float const ii = i * factor;
|
||||
float const yc0 = (y + ii) * pixel->kernel [0];
|
||||
float const yc2 = (y - ii) * pixel->kernel [2];
|
||||
|
||||
float const qq = q * factor;
|
||||
float const yc1 = (y + qq) * pixel->kernel [1];
|
||||
float const yc3 = (y - qq) * pixel->kernel [3];
|
||||
|
||||
float const* k = &impl->kernel [pixel->offset];
|
||||
int n;
|
||||
++pixel;
|
||||
for ( n = rgb_kernel_size; n; --n )
|
||||
{
|
||||
float i = k[0]*ic0 + k[2]*ic2;
|
||||
float q = k[1]*qc1 + k[3]*qc3;
|
||||
float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 +
|
||||
k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset;
|
||||
if ( rescale_out <= 1 )
|
||||
k--;
|
||||
else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] )
|
||||
k += kernel_size * 2 - 1;
|
||||
else
|
||||
k -= kernel_size * 2 * (rescale_out - 1) + 2;
|
||||
{
|
||||
int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g );
|
||||
*out++ = PACK_RGB( r, g, b ) - rgb_bias;
|
||||
}
|
||||
}
|
||||
}
|
||||
while ( alignment_count > 1 && --alignment_remain );
|
||||
|
||||
if ( burst_count <= 1 )
|
||||
break;
|
||||
|
||||
to_rgb += 6;
|
||||
|
||||
ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */
|
||||
}
|
||||
while ( --burst_remain );
|
||||
}
|
||||
|
||||
static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out );
|
||||
|
||||
#if DISABLE_CORRECTION
|
||||
#define CORRECT_ERROR( a ) { out [i] += rgb_bias; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; }
|
||||
#else
|
||||
#define CORRECT_ERROR( a ) { out [a] += error; }
|
||||
#define DISTRIBUTE_ERROR( a, b, c ) {\
|
||||
snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\
|
||||
fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\
|
||||
fourth -= rgb_bias >> 2;\
|
||||
out [a] += fourth;\
|
||||
out [b] += fourth;\
|
||||
out [c] += fourth;\
|
||||
out [i] += error - (fourth * 3);\
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RGB_PALETTE_OUT( rgb, out_ )\
|
||||
{\
|
||||
unsigned char* out = (out_);\
|
||||
snes_ntsc_rgb_t clamped = (rgb);\
|
||||
SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\
|
||||
out [0] = (unsigned char) (clamped >> 21);\
|
||||
out [1] = (unsigned char) (clamped >> 11);\
|
||||
out [2] = (unsigned char) (clamped >> 1);\
|
||||
}
|
||||
|
||||
/* blitter related */
|
||||
|
||||
#ifndef restrict
|
||||
#if defined (__GNUC__)
|
||||
#define restrict __restrict__
|
||||
#elif defined (_MSC_VER) && _MSC_VER > 1300
|
||||
#define restrict __restrict
|
||||
#else
|
||||
/* no support for restricted pointers */
|
||||
#define restrict
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#if SNES_NTSC_OUT_DEPTH <= 16
|
||||
#if USHRT_MAX == 0xFFFF
|
||||
typedef unsigned short snes_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 16-bit int type"
|
||||
#endif
|
||||
|
||||
#else
|
||||
#if UINT_MAX == 0xFFFFFFFF
|
||||
typedef unsigned int snes_ntsc_out_t;
|
||||
#elif ULONG_MAX == 0xFFFFFFFF
|
||||
typedef unsigned long snes_ntsc_out_t;
|
||||
#else
|
||||
#error "Need 32-bit int type"
|
||||
#endif
|
||||
|
||||
#endif
|
34
settings.c
34
settings.c
@ -104,9 +104,6 @@ static void set_defaults(void)
|
||||
g_settings.video.smooth = video_smooth;
|
||||
g_settings.video.force_aspect = force_aspect;
|
||||
g_settings.video.aspect_ratio = SNES_ASPECT_RATIO;
|
||||
#ifdef HAVE_FILTER
|
||||
g_settings.video.filter = FILTER_NONE;
|
||||
#endif
|
||||
g_settings.video.shader_type = SSNES_SHADER_AUTO;
|
||||
|
||||
#ifdef HAVE_FREETYPE
|
||||
@ -301,36 +298,7 @@ static void parse_config_file(void)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_FILTER
|
||||
if (config_get_string(conf, "video_filter", &tmp_str))
|
||||
{
|
||||
unsigned filter = 0;
|
||||
if (strcasecmp(FILTER_HQ2X_STR, tmp_str) == 0)
|
||||
filter = FILTER_HQ2X;
|
||||
else if (strcasecmp(FILTER_HQ4X_STR, tmp_str) == 0)
|
||||
filter = FILTER_HQ4X;
|
||||
else if (strcasecmp(FILTER_GRAYSCALE_STR, tmp_str) == 0)
|
||||
filter = FILTER_GRAYSCALE;
|
||||
else if (strcasecmp(FILTER_BLEED_STR, tmp_str) == 0)
|
||||
filter = FILTER_BLEED;
|
||||
else if (strcasecmp(FILTER_NTSC_STR, tmp_str) == 0)
|
||||
filter = FILTER_NTSC;
|
||||
else
|
||||
{
|
||||
SSNES_ERR(
|
||||
"Invalid filter... Valid filters are:\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n"
|
||||
"\t%s\n",
|
||||
FILTER_HQ2X_STR, FILTER_HQ4X_STR, FILTER_GRAYSCALE_STR,
|
||||
FILTER_BLEED_STR, FILTER_NTSC_STR);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(tmp_str);
|
||||
g_settings.video.filter = filter;
|
||||
}
|
||||
CONFIG_GET_STRING(video.filter_path, "video_filter");
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_XML)
|
||||
|
64
ssnes.c
64
ssnes.c
@ -25,7 +25,7 @@
|
||||
#include <time.h>
|
||||
#include "driver.h"
|
||||
#include "file.h"
|
||||
#include "hqflt/filters.h"
|
||||
#include "filters.h"
|
||||
#include "general.h"
|
||||
#include "dynamic.h"
|
||||
#include "record/ffemu.h"
|
||||
@ -77,23 +77,6 @@ static void set_fast_forward_button(bool new_button_state)
|
||||
old_button_state = new_button_state;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FILTER
|
||||
static inline void process_frame (uint16_t * restrict out, const uint16_t * restrict in, unsigned width, unsigned height)
|
||||
{
|
||||
int pitch = 1024;
|
||||
if (height == 448 || height == 478)
|
||||
pitch = 512;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
const uint16_t *src = in + y * pitch;
|
||||
uint16_t *dst = out + y * width;
|
||||
|
||||
memcpy(dst, src, width * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// libsnes: 0.065
|
||||
// Format received is 16-bit 0RRRRRGGGGGBBBBB
|
||||
static void video_frame(const uint16_t *data, unsigned width, unsigned height)
|
||||
@ -117,44 +100,17 @@ static void video_frame(const uint16_t *data, unsigned width, unsigned height)
|
||||
const char *msg = msg_queue_pull(g_extern.msg_queue);
|
||||
|
||||
#ifdef HAVE_FILTER
|
||||
uint16_t output_filter[width * height * 4 * 4];
|
||||
uint16_t output[width * height];
|
||||
|
||||
if (g_settings.video.filter != FILTER_NONE)
|
||||
process_frame(output, data, width, height);
|
||||
|
||||
|
||||
switch (g_settings.video.filter)
|
||||
unsigned owidth = width;
|
||||
unsigned oheight = height;
|
||||
video_filter_size(&owidth, &oheight);
|
||||
if (g_extern.filter.active)
|
||||
{
|
||||
case FILTER_HQ2X:
|
||||
ProcessHQ2x(output, output_filter);
|
||||
if (!driver.video->frame(driver.video_data, output_filter, width << 1, height << 1, width << 2, msg))
|
||||
g_extern.video_active = false;
|
||||
break;
|
||||
case FILTER_HQ4X:
|
||||
ProcessHQ4x(output, output_filter);
|
||||
if (!driver.video->frame(driver.video_data, output_filter, width << 2, height << 2, width << 3, msg))
|
||||
g_extern.video_active = false;
|
||||
break;
|
||||
case FILTER_GRAYSCALE:
|
||||
grayscale_filter(output, width, height);
|
||||
if (!driver.video->frame(driver.video_data, output, width, height, width << 1, msg))
|
||||
g_extern.video_active = false;
|
||||
break;
|
||||
case FILTER_BLEED:
|
||||
bleed_filter(output, width, height);
|
||||
if (!driver.video->frame(driver.video_data, output, width, height, width << 1, msg))
|
||||
g_extern.video_active = false;
|
||||
break;
|
||||
case FILTER_NTSC:
|
||||
ntsc_filter(output_filter, output, width, height);
|
||||
if (!driver.video->frame(driver.video_data, output_filter, SNES_NTSC_OUT_WIDTH(width), height, SNES_NTSC_OUT_WIDTH(width) << 1, msg))
|
||||
g_extern.video_active = false;
|
||||
break;
|
||||
default:
|
||||
if (!driver.video->frame(driver.video_data, data, width, height, (height == 448 || height == 478) ? 1024 : 2048, msg))
|
||||
g_extern.video_active = false;
|
||||
video_filter_render(g_extern.filter.buffer, g_extern.filter.pitch >> 2, data, (height == 448 || height == 478) ? 512 : 1024, width, height);
|
||||
if (!driver.video->frame(driver.video_data, g_extern.filter.buffer, owidth, oheight, g_extern.filter.pitch, msg))
|
||||
g_extern.video_active = false;
|
||||
}
|
||||
else if (!driver.video->frame(driver.video_data, data, width, height, (height == 448 || height == 478) ? 1024 : 2048, msg))
|
||||
g_extern.video_active = false;
|
||||
#else
|
||||
if (!driver.video->frame(driver.video_data, data, width, height, (height == 448 || height == 478) ? 1024 : 2048, msg))
|
||||
g_extern.video_active = false;
|
||||
|
@ -52,8 +52,8 @@
|
||||
# Defines if bilinear filtering is used during second pass (needs render-to-texture).
|
||||
# video_second_pass_smooth = true
|
||||
|
||||
# CPU-based filter. Valid ones are: hq2x, hq4x, grayscale, bleed, ntsc.
|
||||
# video_filter = ntsc
|
||||
# CPU-based filter. Path to a bSNES CPU filter (*.filter)
|
||||
# video_filter =
|
||||
|
||||
# Path to a TTF font used for rendering messages. This path must be defined to enable fonts.
|
||||
# Do note that the _full_ path of the font is necessary!
|
||||
|
Loading…
x
Reference in New Issue
Block a user