diff --git a/Data/TableData/LogicalBodyTypes/Filters.xml b/Data/TableData/LogicalBodyTypes/Filters.xml
index 089f37d15..81fc0e1aa 100644
--- a/Data/TableData/LogicalBodyTypes/Filters.xml
+++ b/Data/TableData/LogicalBodyTypes/Filters.xml
@@ -10,7 +10,7 @@
GUN_PISTOL
- 711, 732
+ 711, 732, 1352
@@ -32,13 +32,13 @@
GUN_PISTOL
GUN_M_PISTOL
- 711, 732
+ 711, 732, 1352
GUN_PISTOL
- 711, 732
+ 711, 732, 1352
@@ -2307,12 +2307,12 @@
- 711
+ 711, 1352
- 711
+ 711, 1352
diff --git a/Shaders/cubic/catmull-rom-bilinear.glsl b/Shaders/interpolation/catmull-rom-bilinear.glsl
similarity index 97%
rename from Shaders/cubic/catmull-rom-bilinear.glsl
rename to Shaders/interpolation/catmull-rom-bilinear.glsl
index cfe00bff0..03d5b77ae 100644
--- a/Shaders/cubic/catmull-rom-bilinear.glsl
+++ b/Shaders/interpolation/catmull-rom-bilinear.glsl
@@ -1,137 +1,137 @@
-/*
- The following code is licensed under the MIT license: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
- Ported from code: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
- Samples a texture with Catmull-Rom filtering, using 9 texture fetches instead of 16.
- See http://vec3.ca/bicubic-filtering-in-fewer-taps/ for more details
- ATENTION: This code only work using LINEAR filter sampling set on Retroarch!
- Modified to use 5 texture fetches
-*/
-
-#if defined(VERTEX)
-
-#if __VERSION__ >= 130
-#define COMPAT_VARYING out
-#define COMPAT_ATTRIBUTE in
-#define COMPAT_TEXTURE texture
-#else
-#define COMPAT_VARYING varying
-#define COMPAT_ATTRIBUTE attribute
-#define COMPAT_TEXTURE texture2D
-#endif
-
-#ifdef GL_ES
-#define COMPAT_PRECISION mediump
-precision COMPAT_PRECISION float;
-#else
-#define COMPAT_PRECISION
-#endif
-
-COMPAT_ATTRIBUTE vec4 VertexCoord;
-COMPAT_ATTRIBUTE vec4 COLOR;
-COMPAT_ATTRIBUTE vec4 TexCoord;
-COMPAT_VARYING vec4 COL0;
-COMPAT_VARYING vec4 TEX0;
-
-uniform mat4 MVPMatrix;
-uniform COMPAT_PRECISION int FrameDirection;
-uniform COMPAT_PRECISION int FrameCount;
-uniform COMPAT_PRECISION vec2 OutputSize;
-uniform COMPAT_PRECISION vec2 TextureSize;
-uniform COMPAT_PRECISION vec2 InputSize;
-
-void main()
-{
- gl_Position = MVPMatrix * VertexCoord;
- COL0 = COLOR;
- TEX0.xy = TexCoord.xy;
-}
-
-#elif defined(FRAGMENT)
-
-#if __VERSION__ >= 130
-#define COMPAT_VARYING in
-#define COMPAT_TEXTURE texture
-out mediump vec4 FragColor;
-#else
-#define COMPAT_VARYING varying
-#define FragColor gl_FragColor
-#define COMPAT_TEXTURE texture2D
-#endif
-
-#ifdef GL_ES
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-#define COMPAT_PRECISION mediump
-#else
-#define COMPAT_PRECISION
-#endif
-
-uniform COMPAT_PRECISION int FrameDirection;
-uniform COMPAT_PRECISION int FrameCount;
-uniform COMPAT_PRECISION vec2 OutputSize;
-uniform COMPAT_PRECISION vec2 TextureSize;
-uniform COMPAT_PRECISION vec2 InputSize;
-uniform sampler2D Texture;
-COMPAT_VARYING vec4 TEX0;
-
-// compatibility #defines
-#define Source Texture
-#define vTexCoord TEX0.xy
-
-#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
-#define outsize vec4(OutputSize, 1.0 / OutputSize)
-
-void main()
-{
- // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
- // down the sample location to get the exact center of our "starting" texel. The starting texel will be at
- // location [1, 1] in the grid, where [0, 0] is the top left corner.
- vec2 samplePos = vTexCoord * SourceSize.xy;
- vec2 texPos1 = floor(samplePos - 0.5) + 0.5;
-
- // Compute the fractional offset from our starting texel to our original sample location, which we'll
- // feed into the Catmull-Rom spline function to get our filter weights.
- vec2 f = samplePos - texPos1;
-
- // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier.
- // These equations are pre-expanded based on our knowledge of where the texels will be located,
- // which lets us avoid having to evaluate a piece-wise function.
- vec2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f));
- vec2 w1 = 1.0 + f * f * (-2.5 + 1.5 * f);
- vec2 w2 = f * (0.5 + f * (2.0 - 1.5 * f));
- vec2 w3 = f * f * (-0.5 + 0.5 * f);
-
- // Work out weighting factors and sampling offsets that will let us use bilinear filtering to
- // simultaneously evaluate the middle 2 samples from the 4x4 grid.
- vec2 w12 = w1 + w2;
- vec2 offset12 = w2 / (w1 + w2);
-
- // Compute the final UV coordinates we'll use for sampling the texture
- vec2 texPos0 = texPos1 - 1.;
- vec2 texPos3 = texPos1 + 2.;
- vec2 texPos12 = texPos1 + offset12;
-
- texPos0 *= SourceSize.zw;
- texPos3 *= SourceSize.zw;
- texPos12 *= SourceSize.zw;
-
- float wtm = w12.x * w0.y;
- float wml = w0.x * w12.y;
- float wmm = w12.x * w12.y;
- float wmr = w3.x * w12.y;
- float wbm = w12.x * w3.y;
-
- vec3 result = vec3(0.0f);
-
- result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos0.y)).rgb * wtm;
- result += COMPAT_TEXTURE(Source, vec2(texPos0.x, texPos12.y)).rgb * wml;
- result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos12.y)).rgb * wmm;
- result += COMPAT_TEXTURE(Source, vec2(texPos3.x, texPos12.y)).rgb * wmr;
- result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos3.y)).rgb * wbm;
-
- FragColor = vec4(result * (1./(wtm+wml+wmm+wmr+wbm)), 1.0);
-}
-#endif
+/*
+ The following code is licensed under the MIT license: https://gist.github.com/TheRealMJP/bc503b0b87b643d3505d41eab8b332ae
+ Ported from code: https://gist.github.com/TheRealMJP/c83b8c0f46b63f3a88a5986f4fa982b1
+ Samples a texture with Catmull-Rom filtering, using 9 texture fetches instead of 16.
+ See http://vec3.ca/bicubic-filtering-in-fewer-taps/ for more details
+ ATENTION: This code only work using LINEAR filter sampling set on Retroarch!
+ Modified to use 5 texture fetches
+*/
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING out
+#define COMPAT_ATTRIBUTE in
+#define COMPAT_TEXTURE texture
+#else
+#define COMPAT_VARYING varying
+#define COMPAT_ATTRIBUTE attribute
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+precision COMPAT_PRECISION float;
+#else
+#define COMPAT_PRECISION
+#endif
+
+COMPAT_ATTRIBUTE vec4 VertexCoord;
+COMPAT_ATTRIBUTE vec4 COLOR;
+COMPAT_ATTRIBUTE vec4 TexCoord;
+COMPAT_VARYING vec4 COL0;
+COMPAT_VARYING vec4 TEX0;
+
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ COL0 = COLOR;
+ TEX0.xy = TexCoord.xy;
+}
+
+#elif defined(FRAGMENT)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING in
+#define COMPAT_TEXTURE texture
+out mediump vec4 FragColor;
+#else
+#define COMPAT_VARYING varying
+#define FragColor gl_FragColor
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D Texture;
+COMPAT_VARYING vec4 TEX0;
+
+// compatibility #defines
+#define Source Texture
+#define vTexCoord TEX0.xy
+
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define outsize vec4(OutputSize, 1.0 / OutputSize)
+
+void main()
+{
+ // We're going to sample a a 4x4 grid of texels surrounding the target UV coordinate. We'll do this by rounding
+ // down the sample location to get the exact center of our "starting" texel. The starting texel will be at
+ // location [1, 1] in the grid, where [0, 0] is the top left corner.
+ vec2 samplePos = vTexCoord * SourceSize.xy;
+ vec2 texPos1 = floor(samplePos - 0.5) + 0.5;
+
+ // Compute the fractional offset from our starting texel to our original sample location, which we'll
+ // feed into the Catmull-Rom spline function to get our filter weights.
+ vec2 f = samplePos - texPos1;
+
+ // Compute the Catmull-Rom weights using the fractional offset that we calculated earlier.
+ // These equations are pre-expanded based on our knowledge of where the texels will be located,
+ // which lets us avoid having to evaluate a piece-wise function.
+ vec2 w0 = f * (-0.5 + f * (1.0 - 0.5 * f));
+ vec2 w1 = 1.0 + f * f * (-2.5 + 1.5 * f);
+ vec2 w2 = f * (0.5 + f * (2.0 - 1.5 * f));
+ vec2 w3 = f * f * (-0.5 + 0.5 * f);
+
+ // Work out weighting factors and sampling offsets that will let us use bilinear filtering to
+ // simultaneously evaluate the middle 2 samples from the 4x4 grid.
+ vec2 w12 = w1 + w2;
+ vec2 offset12 = w2 / (w1 + w2);
+
+ // Compute the final UV coordinates we'll use for sampling the texture
+ vec2 texPos0 = texPos1 - 1.;
+ vec2 texPos3 = texPos1 + 2.;
+ vec2 texPos12 = texPos1 + offset12;
+
+ texPos0 *= SourceSize.zw;
+ texPos3 *= SourceSize.zw;
+ texPos12 *= SourceSize.zw;
+
+ float wtm = w12.x * w0.y;
+ float wml = w0.x * w12.y;
+ float wmm = w12.x * w12.y;
+ float wmr = w3.x * w12.y;
+ float wbm = w12.x * w3.y;
+
+ vec3 result = vec3(0.0f);
+
+ result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos0.y)).rgb * wtm;
+ result += COMPAT_TEXTURE(Source, vec2(texPos0.x, texPos12.y)).rgb * wml;
+ result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos12.y)).rgb * wmm;
+ result += COMPAT_TEXTURE(Source, vec2(texPos3.x, texPos12.y)).rgb * wmr;
+ result += COMPAT_TEXTURE(Source, vec2(texPos12.x, texPos3.y)).rgb * wbm;
+
+ FragColor = vec4(result * (1./(wtm+wml+wmm+wmr+wbm)), 1.0);
+}
+#endif
diff --git a/Shaders/interpolation/fsr.glsl b/Shaders/interpolation/fsr.glsl
new file mode 100644
index 000000000..17e574bc9
--- /dev/null
+++ b/Shaders/interpolation/fsr.glsl
@@ -0,0 +1,324 @@
+/*
+ FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING
+ Ported from https://www.shadertoy.com/view/stXSWB, MIT license
+*/
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING out
+#define COMPAT_ATTRIBUTE in
+#define COMPAT_TEXTURE texture
+#else
+#define COMPAT_VARYING varying
+#define COMPAT_ATTRIBUTE attribute
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+COMPAT_ATTRIBUTE vec4 VertexCoord;
+COMPAT_ATTRIBUTE vec4 COLOR;
+COMPAT_ATTRIBUTE vec4 TexCoord;
+COMPAT_VARYING vec4 COL0;
+COMPAT_VARYING vec4 TEX0;
+
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ COL0 = COLOR;
+ TEX0.xy = TexCoord.xy;
+}
+
+#elif defined(FRAGMENT)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING in
+#define COMPAT_TEXTURE texture
+out vec4 FragColor;
+#else
+#define COMPAT_VARYING varying
+#define FragColor gl_FragColor
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D Texture;
+COMPAT_VARYING vec4 TEX0;
+
+// compatibility #defines
+#define Source Texture
+#define vTexCoord TEX0.xy
+
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define outsize vec4(OutputSize, 1.0 / OutputSize)
+
+vec3 FsrEasuCF(vec2 p) {
+ return COMPAT_TEXTURE(Source,p).rgb;
+}
+
+/**** EASU ****/
+void FsrEasuCon(
+ out vec4 con0,
+ out vec4 con1,
+ out vec4 con2,
+ out vec4 con3,
+ // This the rendered image resolution being upscaled
+ vec2 inputViewportInPixels,
+ // This is the resolution of the resource containing the input image (useful for dynamic resolution)
+ vec2 inputSizeInPixels,
+ // This is the display resolution which the input image gets upscaled to
+ vec2 outputSizeInPixels
+)
+{
+ // Output integer position to a pixel position in viewport.
+ con0 = vec4(
+ inputViewportInPixels.x/outputSizeInPixels.x,
+ inputViewportInPixels.y/outputSizeInPixels.y,
+ .5*inputViewportInPixels.x/outputSizeInPixels.x-.5,
+ .5*inputViewportInPixels.y/outputSizeInPixels.y-.5
+ );
+ // Viewport pixel position to normalized image space.
+ // This is used to get upper-left of 'F' tap.
+ con1 = vec4(1,1,1,-1)/inputSizeInPixels.xyxy;
+ // Centers of gather4, first offset from upper-left of 'F'.
+ // +---+---+
+ // | | |
+ // +--(0)--+
+ // | b | c |
+ // +---F---+---+---+
+ // | e | f | g | h |
+ // +--(1)--+--(2)--+
+ // | i | j | k | l |
+ // +---+---+---+---+
+ // | n | o |
+ // +--(3)--+
+ // | | |
+ // +---+---+
+ // These are from (0) instead of 'F'.
+ con2 = vec4(-1,2,1,2)/inputSizeInPixels.xyxy;
+ con3 = vec4(0,4,0,0)/inputSizeInPixels.xyxy;
+}
+
+// Filtering for a given tap for the scalar.
+void FsrEasuTapF(
+ inout vec3 aC, // Accumulated color, with negative lobe.
+ inout float aW, // Accumulated weight.
+ vec2 off, // Pixel offset from resolve position to tap.
+ vec2 dir, // Gradient direction.
+ vec2 len, // Length.
+ float lob, // Negative lobe strength.
+ float clp, // Clipping point.
+ vec3 c
+)
+{
+ // Tap color.
+ // Rotate offset by direction.
+ vec2 v = vec2(dot(off, dir), dot(off,vec2(-dir.y,dir.x)));
+ // Anisotropy.
+ v *= len;
+ // Compute distance^2.
+ float d2 = min(dot(v,v),clp);
+ // Limit to the window as at corner, 2 taps can easily be outside.
+ // Approximation of lancos2 without sin() or rcp(), or sqrt() to get x.
+ // (25/16 * (2/5 * x^2 - 1)^2 - (25/16 - 1)) * (1/4 * x^2 - 1)^2
+ // |_______________________________________| |_______________|
+ // base window
+ // The general form of the 'base' is,
+ // (a*(b*x^2-1)^2-(a-1))
+ // Where 'a=1/(2*b-b^2)' and 'b' moves around the negative lobe.
+ float wB = .4 * d2 - 1.;
+ float wA = lob * d2 -1.;
+ wB *= wB;
+ wA *= wA;
+ wB = 1.5625*wB-.5625;
+ float w= wB * wA;
+ // Do weighted average.
+ aC += c*w;
+ aW += w;
+}
+
+//------------------------------------------------------------------------------------------------------------------------------
+// Accumulate direction and length.
+void FsrEasuSetF(
+ inout vec2 dir,
+ inout float len,
+ float w,
+ float lA,float lB,float lC,float lD,float lE
+)
+{
+ // Direction is the '+' diff.
+ // a
+ // b c d
+ // e
+ // Then takes magnitude from abs average of both sides of 'c'.
+ // Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms.
+ float lenX = max(abs(lD - lC), abs(lC - lB));
+ float dirX = lD - lB;
+ dir.x += dirX * w;
+ lenX = clamp(abs(dirX)/lenX,0.,1.);
+ lenX *= lenX;
+ len += lenX * w;
+ // Repeat for the y axis.
+ float lenY = max(abs(lE - lC), abs(lC - lA));
+ float dirY = lE - lA;
+ dir.y += dirY * w;
+ lenY = clamp(abs(dirY) / lenY,0.,1.);
+ lenY *= lenY;
+ len += lenY * w;
+}
+
+//------------------------------------------------------------------------------------------------------------------------------
+void FsrEasuF(
+ out vec3 pix,
+ vec2 ip, // Integer pixel position in output.
+ // Constants generated by FsrEasuCon().
+ vec4 con0, // xy = output to input scale, zw = first pixel offset correction
+ vec4 con1,
+ vec4 con2,
+ vec4 con3
+)
+{
+ //------------------------------------------------------------------------------------------------------------------------------
+ // Get position of 'f'.
+ vec2 pp = ip * con0.xy + con0.zw; // Corresponding input pixel/subpixel
+ vec2 fp = floor(pp);// fp = source nearest pixel
+ pp -= fp; // pp = source subpixel
+
+ //------------------------------------------------------------------------------------------------------------------------------
+ // 12-tap kernel.
+ // b c
+ // e f g h
+ // i j k l
+ // n o
+ // Gather 4 ordering.
+ // a b
+ // r g
+ vec2 p0 = fp * con1.xy + con1.zw;
+
+ // These are from p0 to avoid pulling two constants on pre-Navi hardware.
+ vec2 p1 = p0 + con2.xy;
+ vec2 p2 = p0 + con2.zw;
+ vec2 p3 = p0 + con3.xy;
+
+ // TextureGather is not available on WebGL2
+ vec4 off = vec4(-.5,.5,-.5,.5)*con1.xxyy;
+ // textureGather to texture offsets
+ // x=west y=east z=north w=south
+ vec3 bC = FsrEasuCF(p0 + off.xw); float bL = bC.g + 0.5 *(bC.r + bC.b);
+ vec3 cC = FsrEasuCF(p0 + off.yw); float cL = cC.g + 0.5 *(cC.r + cC.b);
+ vec3 iC = FsrEasuCF(p1 + off.xw); float iL = iC.g + 0.5 *(iC.r + iC.b);
+ vec3 jC = FsrEasuCF(p1 + off.yw); float jL = jC.g + 0.5 *(jC.r + jC.b);
+ vec3 fC = FsrEasuCF(p1 + off.yz); float fL = fC.g + 0.5 *(fC.r + fC.b);
+ vec3 eC = FsrEasuCF(p1 + off.xz); float eL = eC.g + 0.5 *(eC.r + eC.b);
+ vec3 kC = FsrEasuCF(p2 + off.xw); float kL = kC.g + 0.5 *(kC.r + kC.b);
+ vec3 lC = FsrEasuCF(p2 + off.yw); float lL = lC.g + 0.5 *(lC.r + lC.b);
+ vec3 hC = FsrEasuCF(p2 + off.yz); float hL = hC.g + 0.5 *(hC.r + hC.b);
+ vec3 gC = FsrEasuCF(p2 + off.xz); float gL = gC.g + 0.5 *(gC.r + gC.b);
+ vec3 oC = FsrEasuCF(p3 + off.yz); float oL = oC.g + 0.5 *(oC.r + oC.b);
+ vec3 nC = FsrEasuCF(p3 + off.xz); float nL = nC.g + 0.5 *(nC.r + nC.b);
+
+ //------------------------------------------------------------------------------------------------------------------------------
+ // Simplest multi-channel approximate luma possible (luma times 2, in 2 FMA/MAD).
+ // Accumulate for bilinear interpolation.
+ vec2 dir = vec2(0);
+ float len = 0.;
+
+ FsrEasuSetF(dir, len, (1.-pp.x)*(1.-pp.y), bL, eL, fL, gL, jL);
+ FsrEasuSetF(dir, len, pp.x *(1.-pp.y), cL, fL, gL, hL, kL);
+ FsrEasuSetF(dir, len, (1.-pp.x)* pp.y , fL, iL, jL, kL, nL);
+ FsrEasuSetF(dir, len, pp.x * pp.y , gL, jL, kL, lL, oL);
+
+ //------------------------------------------------------------------------------------------------------------------------------
+ // Normalize with approximation, and cleanup close to zero.
+ vec2 dir2 = dir * dir;
+ float dirR = dir2.x + dir2.y;
+ bool zro = dirR < (1.0/32768.0);
+ dirR = inversesqrt(dirR);
+ dirR = zro ? 1.0 : dirR;
+ dir.x = zro ? 1.0 : dir.x;
+ dir *= vec2(dirR);
+ // Transform from {0 to 2} to {0 to 1} range, and shape with square.
+ len = len * 0.5;
+ len *= len;
+ // Stretch kernel {1.0 vert|horz, to sqrt(2.0) on diagonal}.
+ float stretch = dot(dir,dir) / (max(abs(dir.x), abs(dir.y)));
+ // Anisotropic length after rotation,
+ // x := 1.0 lerp to 'stretch' on edges
+ // y := 1.0 lerp to 2x on edges
+ vec2 len2 = vec2(1. +(stretch-1.0)*len, 1. -.5 * len);
+ // Based on the amount of 'edge',
+ // the window shifts from +/-{sqrt(2.0) to slightly beyond 2.0}.
+ float lob = .5 - .29 * len;
+ // Set distance^2 clipping point to the end of the adjustable window.
+ float clp = 1./lob;
+
+ //------------------------------------------------------------------------------------------------------------------------------
+ // Accumulation mixed with min/max of 4 nearest.
+ // b c
+ // e f g h
+ // i j k l
+ // n o
+ vec3 min4 = min(min(fC,gC),min(jC,kC));
+ vec3 max4 = max(max(fC,gC),max(jC,kC));
+ // Accumulation.
+ vec3 aC = vec3(0);
+ float aW = 0.;
+ FsrEasuTapF(aC, aW, vec2( 0,-1)-pp, dir, len2, lob, clp, bC);
+ FsrEasuTapF(aC, aW, vec2( 1,-1)-pp, dir, len2, lob, clp, cC);
+ FsrEasuTapF(aC, aW, vec2(-1, 1)-pp, dir, len2, lob, clp, iC);
+ FsrEasuTapF(aC, aW, vec2( 0, 1)-pp, dir, len2, lob, clp, jC);
+ FsrEasuTapF(aC, aW, vec2( 0, 0)-pp, dir, len2, lob, clp, fC);
+ FsrEasuTapF(aC, aW, vec2(-1, 0)-pp, dir, len2, lob, clp, eC);
+ FsrEasuTapF(aC, aW, vec2( 1, 1)-pp, dir, len2, lob, clp, kC);
+ FsrEasuTapF(aC, aW, vec2( 2, 1)-pp, dir, len2, lob, clp, lC);
+ FsrEasuTapF(aC, aW, vec2( 2, 0)-pp, dir, len2, lob, clp, hC);
+ FsrEasuTapF(aC, aW, vec2( 1, 0)-pp, dir, len2, lob, clp, gC);
+ FsrEasuTapF(aC, aW, vec2( 1, 2)-pp, dir, len2, lob, clp, oC);
+ FsrEasuTapF(aC, aW, vec2( 0, 2)-pp, dir, len2, lob, clp, nC);
+ //------------------------------------------------------------------------------------------------------------------------------
+ // Normalize and dering.
+ pix=min(max4,max(min4,aC/aW));
+}
+
+void main()
+{
+ vec3 c;
+ vec4 con0,con1,con2,con3;
+
+ vec2 fragCoord = vTexCoord.xy * OutputSize.xy;
+
+ FsrEasuCon(
+ con0, con1, con2, con3, SourceSize.xy, SourceSize.xy, OutputSize.xy
+ );
+ FsrEasuF(c, fragCoord, con0, con1, con2, con3);
+ FragColor = vec4(c.xyz, 1);
+}
+
+#endif
diff --git a/Shaders/interpolation/fsr.glsl.pass1 b/Shaders/interpolation/fsr.glsl.pass1
new file mode 100644
index 000000000..d9ce74fc6
--- /dev/null
+++ b/Shaders/interpolation/fsr.glsl.pass1
@@ -0,0 +1,178 @@
+/*
+ FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
+ Ported from https://www.shadertoy.com/view/stXSWB, MIT license
+*/
+
+#pragma parameter FSR_SHARPENING "FSR RCAS Sharpening Amount (Lower = Sharper)" 0.6 0.0 2.0 0.1
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING out
+#define COMPAT_ATTRIBUTE in
+#define COMPAT_TEXTURE texture
+#else
+#define COMPAT_VARYING varying
+#define COMPAT_ATTRIBUTE attribute
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+COMPAT_ATTRIBUTE vec4 VertexCoord;
+COMPAT_ATTRIBUTE vec4 COLOR;
+COMPAT_ATTRIBUTE vec4 TexCoord;
+COMPAT_VARYING vec4 COL0;
+COMPAT_VARYING vec4 TEX0;
+
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ COL0 = COLOR;
+ TEX0.xy = TexCoord.xy;
+}
+
+#elif defined(FRAGMENT)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING in
+#define COMPAT_TEXTURE texture
+out vec4 FragColor;
+#else
+#define COMPAT_VARYING varying
+#define FragColor gl_FragColor
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D Texture;
+COMPAT_VARYING vec4 TEX0;
+
+// compatibility #defines
+#define Source Texture
+#define vTexCoord TEX0.xy
+
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define outsize vec4(OutputSize, 1.0 / OutputSize)
+
+#ifdef PARAMETER_UNIFORM
+uniform COMPAT_PRECISION float FSR_SHARPENING;
+#else
+#define FSR_SHARPENING 0.6
+#endif
+
+#define FSR_RCAS_LIMIT (0.25-(1.0/16.0))
+//#define FSR_RCAS_DENOISE
+
+// Input callback prototypes that need to be implemented by calling shader
+vec4 FsrRcasLoadF(vec2 p);
+//------------------------------------------------------------------------------------------------------------------------------
+void FsrRcasCon(
+ out float con,
+ // The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}.
+ float sharpness
+){
+ // Transform from stops to linear value.
+ con = exp2(-sharpness);
+}
+
+vec3 FsrRcasF(
+ vec2 ip, // Integer pixel position in output.
+ float con
+)
+{
+ // Constant generated by RcasSetup().
+ // Algorithm uses minimal 3x3 pixel neighborhood.
+ // b
+ // d e f
+ // h
+ vec2 sp = vec2(ip);
+ vec3 b = FsrRcasLoadF(sp + vec2( 0,-1)).rgb;
+ vec3 d = FsrRcasLoadF(sp + vec2(-1, 0)).rgb;
+ vec3 e = FsrRcasLoadF(sp).rgb;
+ vec3 f = FsrRcasLoadF(sp+vec2( 1, 0)).rgb;
+ vec3 h = FsrRcasLoadF(sp+vec2( 0, 1)).rgb;
+ // Luma times 2.
+ float bL = b.g + .5 * (b.b + b.r);
+ float dL = d.g + .5 * (d.b + d.r);
+ float eL = e.g + .5 * (e.b + e.r);
+ float fL = f.g + .5 * (f.b + f.r);
+ float hL = h.g + .5 * (h.b + h.r);
+ // Noise detection.
+ float nz = .25 * (bL + dL + fL + hL) - eL;
+ nz=clamp(
+ abs(nz)
+ /(
+ max(max(bL,dL),max(eL,max(fL,hL)))
+ -min(min(bL,dL),min(eL,min(fL,hL)))
+ ),
+ 0., 1.
+ );
+ nz=1.-.5*nz;
+ // Min and max of ring.
+ vec3 mn4 = min(b, min(f, h));
+ vec3 mx4 = max(b, max(f, h));
+ // Immediate constants for peak range.
+ vec2 peakC = vec2(1., -4.);
+ // Limiters, these need to be high precision RCPs.
+ vec3 hitMin = mn4 / (4. * mx4);
+ vec3 hitMax = (peakC.x - mx4) / (4.* mn4 + peakC.y);
+ vec3 lobeRGB = max(-hitMin, hitMax);
+ float lobe = max(
+ -FSR_RCAS_LIMIT,
+ min(max(lobeRGB.r, max(lobeRGB.g, lobeRGB.b)), 0.)
+ )*con;
+ // Apply noise removal.
+ #ifdef FSR_RCAS_DENOISE
+ lobe *= nz;
+ #endif
+ // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes.
+ return (lobe * (b + d + h + f) + e) / (4. * lobe + 1.);
+}
+
+
+vec4 FsrRcasLoadF(vec2 p) {
+ return COMPAT_TEXTURE(Source,p/OutputSize.xy);
+}
+
+void main()
+{
+ vec2 fragCoord = vTexCoord.xy * OutputSize.xy;
+
+ // Set up constants
+ float con;
+ FsrRcasCon(con, FSR_SHARPENING);
+
+ // Perform RCAS pass
+ vec3 col = FsrRcasF(fragCoord, con);
+
+ FragColor = vec4(col,1);
+}
+
+#endif
diff --git a/Shaders/interpolation/jinc2-dedither.glsl b/Shaders/interpolation/jinc2-dedither.glsl
new file mode 100644
index 000000000..32235e056
--- /dev/null
+++ b/Shaders/interpolation/jinc2-dedither.glsl
@@ -0,0 +1,202 @@
+/*
+ Hyllian's jinc windowed-jinc 2-lobe sharper with anti-ringing Shader
+
+ Copyright (C) 2011-2016 Hyllian/Jararaca - sergiogdb@gmail.com
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+*/
+
+#define JINC2_WINDOW_SINC 0.405
+#define JINC2_SINC 0.79
+#define JINC2_AR_STRENGTH 0.8
+
+#define texCoord TEX0
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define OUT out
+#define IN in
+#define tex2D texture
+#else
+#define OUT varying
+#define IN attribute
+#define tex2D texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+
+IN vec4 VertexCoord;
+IN vec4 Color;
+IN vec2 TexCoord;
+OUT vec4 color;
+OUT vec2 texCoord;
+
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ color = Color;
+ texCoord = TexCoord * 1.0001;
+}
+
+#elif defined(FRAGMENT)
+
+#if __VERSION__ >= 130
+#define IN in
+#define tex2D texture
+out vec4 FragColor;
+#else
+#define IN varying
+#define FragColor gl_FragColor
+#define tex2D texture2D
+#endif
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D s_p;
+IN vec2 texCoord;
+
+const float halfpi = 1.5707963267948966192313216916398;
+const float pi = 3.1415926535897932384626433832795;
+const float wa = JINC2_WINDOW_SINC*pi;
+const float wb = JINC2_SINC*pi;
+
+// Calculates the distance between two points
+float d(vec2 pt1, vec2 pt2)
+{
+ vec2 v = pt2 - pt1;
+ return sqrt(dot(v,v));
+}
+
+vec3 min4(vec3 a, vec3 b, vec3 c, vec3 d)
+{
+ return min(a, min(b, min(c, d)));
+}
+
+vec3 max4(vec3 a, vec3 b, vec3 c, vec3 d)
+{
+ return max(a, max(b, max(c, d)));
+}
+
+vec4 resampler(vec4 x)
+{
+ vec4 res;
+
+ res = (x==vec4(0.0, 0.0, 0.0, 0.0)) ? vec4(wa*wb) : sin(x*wa)*sin(x*wb)/(x*x);
+
+ return res;
+}
+
+void main()
+{
+
+ vec3 color;
+ vec4 weights[4];
+
+ vec2 dx = vec2(1.0, 0.0);
+ vec2 dy = vec2(0.0, 1.0);
+
+ vec2 pc = texCoord*TextureSize;
+
+ vec2 tc = (floor(pc-vec2(0.5,0.5))+vec2(0.5,0.5));
+
+ weights[0] = resampler(vec4(d(pc, tc -dx -dy), d(pc, tc -dy), d(pc, tc +dx -dy), d(pc, tc+2.0*dx -dy)));
+ weights[1] = resampler(vec4(d(pc, tc -dx ), d(pc, tc ), d(pc, tc +dx ), d(pc, tc+2.0*dx )));
+ weights[2] = resampler(vec4(d(pc, tc -dx +dy), d(pc, tc +dy), d(pc, tc +dx +dy), d(pc, tc+2.0*dx +dy)));
+ weights[3] = resampler(vec4(d(pc, tc -dx+2.0*dy), d(pc, tc +2.0*dy), d(pc, tc +dx+2.0*dy), d(pc, tc+2.0*dx+2.0*dy)));
+
+ dx = dx/TextureSize;
+ dy = dy/TextureSize;
+ tc = tc/TextureSize;
+
+ vec3 c00 = tex2D(s_p, tc -dx -dy).xyz;
+ vec3 c10 = tex2D(s_p, tc -dy).xyz;
+ vec3 c20 = tex2D(s_p, tc +dx -dy).xyz;
+ vec3 c30 = tex2D(s_p, tc+2.0*dx -dy).xyz;
+ vec3 c01 = tex2D(s_p, tc -dx ).xyz;
+ vec3 c11 = tex2D(s_p, tc ).xyz;
+ vec3 c21 = tex2D(s_p, tc +dx ).xyz;
+ vec3 c31 = tex2D(s_p, tc+2.0*dx ).xyz;
+ vec3 c02 = tex2D(s_p, tc -dx +dy).xyz;
+ vec3 c12 = tex2D(s_p, tc +dy).xyz;
+ vec3 c22 = tex2D(s_p, tc +dx +dy).xyz;
+ vec3 c32 = tex2D(s_p, tc+2.0*dx +dy).xyz;
+ vec3 c03 = tex2D(s_p, tc -dx+2.0*dy).xyz;
+ vec3 c13 = tex2D(s_p, tc +2.0*dy).xyz;
+ vec3 c23 = tex2D(s_p, tc +dx+2.0*dy).xyz;
+ vec3 c33 = tex2D(s_p, tc+2.0*dx+2.0*dy).xyz;
+
+ color = tex2D(s_p, texCoord).xyz;
+
+ // Get min/max samples
+ vec3 min_sample = min4(c11, c21, c12, c22);
+ vec3 max_sample = max4(c11, c21, c12, c22);
+/*
+ color = mat4x3(c00, c10, c20, c30) * weights[0];
+ color+= mat4x3(c01, c11, c21, c31) * weights[1];
+ color+= mat4x3(c02, c12, c22, c32) * weights[2];
+ color+= mat4x3(c03, c13, c23, c33) * weights[3];
+ mat4 wgts = mat4(weights[0], weights[1], weights[2], weights[3]);
+ vec4 wsum = wgts * vec4(1.0,1.0,1.0,1.0);
+ color = color/(dot(wsum, vec4(1.0,1.0,1.0,1.0)));
+*/
+
+
+ color = vec3(dot(weights[0], vec4(c00.x, c10.x, c20.x, c30.x)), dot(weights[0], vec4(c00.y, c10.y, c20.y, c30.y)), dot(weights[0], vec4(c00.z, c10.z, c20.z, c30.z)));
+ color+= vec3(dot(weights[1], vec4(c01.x, c11.x, c21.x, c31.x)), dot(weights[1], vec4(c01.y, c11.y, c21.y, c31.y)), dot(weights[1], vec4(c01.z, c11.z, c21.z, c31.z)));
+ color+= vec3(dot(weights[2], vec4(c02.x, c12.x, c22.x, c32.x)), dot(weights[2], vec4(c02.y, c12.y, c22.y, c32.y)), dot(weights[2], vec4(c02.z, c12.z, c22.z, c32.z)));
+ color+= vec3(dot(weights[3], vec4(c03.x, c13.x, c23.x, c33.x)), dot(weights[3], vec4(c03.y, c13.y, c23.y, c33.y)), dot(weights[3], vec4(c03.z, c13.z, c23.z, c33.z)));
+ color = color/(dot(weights[0], vec4(1,1,1,1)) + dot(weights[1], vec4(1,1,1,1)) + dot(weights[2], vec4(1,1,1,1)) + dot(weights[3], vec4(1,1,1,1)));
+
+ // Anti-ringing
+ vec3 aux = color;
+ color = clamp(color, min_sample, max_sample);
+ color = mix(aux, color, JINC2_AR_STRENGTH);
+
+ // final sum and weight normalization
+ FragColor.xyz = color;
+}
+#endif
diff --git a/Shaders/windowed/lanczos2-sharp.glsl b/Shaders/interpolation/lanczos2-sharp.glsl
similarity index 100%
rename from Shaders/windowed/lanczos2-sharp.glsl
rename to Shaders/interpolation/lanczos2-sharp.glsl
diff --git a/Shaders/readme.txt b/Shaders/readme.txt
index c262bee6d..abd02a01b 100644
--- a/Shaders/readme.txt
+++ b/Shaders/readme.txt
@@ -5,3 +5,6 @@ https://github.com/libretro/glsl-shaders
Note: Filename must end with "bilinear.glsl" to enable bilinear hardware filtering (GL_LINEAR)
+
+
+Extract shader-package.zip to unlock 100+ additional shaders
diff --git a/Shaders/shader-package.zip b/Shaders/shader-package.zip
index 2f3e07f7d..21290e21f 100644
Binary files a/Shaders/shader-package.zip and b/Shaders/shader-package.zip differ
diff --git a/Shaders/sharpen/fast-sharpen.glsl b/Shaders/sharpen/fast-sharpen.glsl
deleted file mode 100644
index 623fd6d58..000000000
--- a/Shaders/sharpen/fast-sharpen.glsl
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- Fast Sharpen Shader
-
- Copyright (C) 2005 - 2019 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.
-*/
-
-#pragma parameter SHARPEN "Sharpen strength" 1.00 0.0 2.00 0.05
-#pragma parameter CONTR "Ammount of sharpening" 0.07 0.0 0.25 0.01
-#pragma parameter DETAILS "Details sharpened " 1.00 0.0 1.00 0.05
-
-#if defined(VERTEX)
-
-#if __VERSION__ >= 130
-#define COMPAT_VARYING out
-#define COMPAT_ATTRIBUTE in
-#define COMPAT_TEXTURE texture
-#else
-#define COMPAT_VARYING varying
-#define COMPAT_ATTRIBUTE attribute
-#define COMPAT_TEXTURE texture2D
-#endif
-
-#ifdef GL_ES
-#define COMPAT_PRECISION mediump
-#else
-#define COMPAT_PRECISION
-#endif
-
-COMPAT_ATTRIBUTE vec4 VertexCoord;
-COMPAT_ATTRIBUTE vec4 TexCoord;
-COMPAT_VARYING vec4 TEX0;
-
-vec4 _oPosition1;
-uniform mat4 MVPMatrix;
-uniform COMPAT_PRECISION int FrameDirection;
-uniform COMPAT_PRECISION int FrameCount;
-uniform COMPAT_PRECISION vec2 OutputSize;
-uniform COMPAT_PRECISION vec2 TextureSize;
-uniform COMPAT_PRECISION vec2 InputSize;
-COMPAT_VARYING vec2 g10;
-COMPAT_VARYING vec2 g01;
-COMPAT_VARYING vec2 g12;
-COMPAT_VARYING vec2 g21;
-
-// compatibility #defines
-#define vTexCoord TEX0.xy
-#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
-#define OutSize vec4(OutputSize, 1.0 / OutputSize)
-
-void main()
-{
- gl_Position = MVPMatrix * VertexCoord;
- TEX0.xy = TexCoord.xy * 1.00001;
- g10 = vec2( 0.3333,-1.0)*SourceSize.zw;
- g01 = vec2(-1.0,-0.3333)*SourceSize.zw;
- g12 = vec2(-0.3333, 1.0)*SourceSize.zw;
- g21 = vec2( 1.0, 0.3333)*SourceSize.zw;
-}
-
-#elif defined(FRAGMENT)
-
-#ifdef GL_ES
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-#define COMPAT_PRECISION mediump
-#else
-#define COMPAT_PRECISION
-#endif
-
-#if __VERSION__ >= 130
-#define COMPAT_VARYING in
-#define COMPAT_TEXTURE texture
-out COMPAT_PRECISION vec4 FragColor;
-#else
-#define COMPAT_VARYING varying
-#define FragColor gl_FragColor
-#define COMPAT_TEXTURE texture2D
-#endif
-
-uniform COMPAT_PRECISION int FrameDirection;
-uniform COMPAT_PRECISION int FrameCount;
-uniform COMPAT_PRECISION vec2 OutputSize;
-uniform COMPAT_PRECISION vec2 TextureSize;
-uniform COMPAT_PRECISION vec2 InputSize;
-uniform sampler2D Texture;
-COMPAT_VARYING vec4 TEX0;
-COMPAT_VARYING vec2 g10;
-COMPAT_VARYING vec2 g01;
-COMPAT_VARYING vec2 g12;
-COMPAT_VARYING vec2 g21;
-
-// compatibility #defines
-#define Source Texture
-#define vTexCoord TEX0.xy
-
-#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
-#define OutSize vec4(OutputSize, 1.0 / OutputSize)
-
-#ifdef PARAMETER_UNIFORM
-uniform COMPAT_PRECISION float SHARPEN;
-uniform COMPAT_PRECISION float CONTR;
-uniform COMPAT_PRECISION float DETAILS;
-#else
-#define SHARPEN 1.2
-#define CONTR 0.08
-#define DETAILS 1.0
-#endif
-
-void main()
-{
- vec3 c10 = COMPAT_TEXTURE(Source, vTexCoord + g10).rgb;
- vec3 c01 = COMPAT_TEXTURE(Source, vTexCoord + g01).rgb;
- vec3 c21 = COMPAT_TEXTURE(Source, vTexCoord + g21).rgb;
- vec3 c12 = COMPAT_TEXTURE(Source, vTexCoord + g12).rgb;
- vec3 c11 = COMPAT_TEXTURE(Source, vTexCoord ).rgb;
- vec3 b11 = (c10+c01+c12+c21)*0.25;
-
- float contrast = max(max(c11.r,c11.g),c11.b);
- contrast = mix(2.0*CONTR, CONTR, contrast);
-
- vec3 mn1 = min(min(c10,c01),min(c12,c21)); mn1 = min(mn1,c11*(1.0-contrast));
- vec3 mx1 = max(max(c10,c01),max(c12,c21)); mx1 = max(mx1,c11*(1.0+contrast));
-
- vec3 dif = pow(mx1-mn1+0.0001, vec3(0.75,0.75,0.75));
- vec3 sharpen = mix(vec3(SHARPEN*DETAILS), vec3(SHARPEN), dif);
-
- c11 = clamp(mix(c11,b11,-sharpen), mn1,mx1);
-
- FragColor = vec4(c11,1.0);
-}
-#endif
diff --git a/Shaders/sharpen/rca-sharpen.glsl b/Shaders/sharpen/rca-sharpen.glsl
new file mode 100644
index 000000000..d9ce74fc6
--- /dev/null
+++ b/Shaders/sharpen/rca-sharpen.glsl
@@ -0,0 +1,178 @@
+/*
+ FSR - [RCAS] ROBUST CONTRAST ADAPTIVE SHARPENING
+ Ported from https://www.shadertoy.com/view/stXSWB, MIT license
+*/
+
+#pragma parameter FSR_SHARPENING "FSR RCAS Sharpening Amount (Lower = Sharper)" 0.6 0.0 2.0 0.1
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING out
+#define COMPAT_ATTRIBUTE in
+#define COMPAT_TEXTURE texture
+#else
+#define COMPAT_VARYING varying
+#define COMPAT_ATTRIBUTE attribute
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+COMPAT_ATTRIBUTE vec4 VertexCoord;
+COMPAT_ATTRIBUTE vec4 COLOR;
+COMPAT_ATTRIBUTE vec4 TexCoord;
+COMPAT_VARYING vec4 COL0;
+COMPAT_VARYING vec4 TEX0;
+
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ COL0 = COLOR;
+ TEX0.xy = TexCoord.xy;
+}
+
+#elif defined(FRAGMENT)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING in
+#define COMPAT_TEXTURE texture
+out vec4 FragColor;
+#else
+#define COMPAT_VARYING varying
+#define FragColor gl_FragColor
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D Texture;
+COMPAT_VARYING vec4 TEX0;
+
+// compatibility #defines
+#define Source Texture
+#define vTexCoord TEX0.xy
+
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define outsize vec4(OutputSize, 1.0 / OutputSize)
+
+#ifdef PARAMETER_UNIFORM
+uniform COMPAT_PRECISION float FSR_SHARPENING;
+#else
+#define FSR_SHARPENING 0.6
+#endif
+
+#define FSR_RCAS_LIMIT (0.25-(1.0/16.0))
+//#define FSR_RCAS_DENOISE
+
+// Input callback prototypes that need to be implemented by calling shader
+vec4 FsrRcasLoadF(vec2 p);
+//------------------------------------------------------------------------------------------------------------------------------
+void FsrRcasCon(
+ out float con,
+ // The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}.
+ float sharpness
+){
+ // Transform from stops to linear value.
+ con = exp2(-sharpness);
+}
+
+vec3 FsrRcasF(
+ vec2 ip, // Integer pixel position in output.
+ float con
+)
+{
+ // Constant generated by RcasSetup().
+ // Algorithm uses minimal 3x3 pixel neighborhood.
+ // b
+ // d e f
+ // h
+ vec2 sp = vec2(ip);
+ vec3 b = FsrRcasLoadF(sp + vec2( 0,-1)).rgb;
+ vec3 d = FsrRcasLoadF(sp + vec2(-1, 0)).rgb;
+ vec3 e = FsrRcasLoadF(sp).rgb;
+ vec3 f = FsrRcasLoadF(sp+vec2( 1, 0)).rgb;
+ vec3 h = FsrRcasLoadF(sp+vec2( 0, 1)).rgb;
+ // Luma times 2.
+ float bL = b.g + .5 * (b.b + b.r);
+ float dL = d.g + .5 * (d.b + d.r);
+ float eL = e.g + .5 * (e.b + e.r);
+ float fL = f.g + .5 * (f.b + f.r);
+ float hL = h.g + .5 * (h.b + h.r);
+ // Noise detection.
+ float nz = .25 * (bL + dL + fL + hL) - eL;
+ nz=clamp(
+ abs(nz)
+ /(
+ max(max(bL,dL),max(eL,max(fL,hL)))
+ -min(min(bL,dL),min(eL,min(fL,hL)))
+ ),
+ 0., 1.
+ );
+ nz=1.-.5*nz;
+ // Min and max of ring.
+ vec3 mn4 = min(b, min(f, h));
+ vec3 mx4 = max(b, max(f, h));
+ // Immediate constants for peak range.
+ vec2 peakC = vec2(1., -4.);
+ // Limiters, these need to be high precision RCPs.
+ vec3 hitMin = mn4 / (4. * mx4);
+ vec3 hitMax = (peakC.x - mx4) / (4.* mn4 + peakC.y);
+ vec3 lobeRGB = max(-hitMin, hitMax);
+ float lobe = max(
+ -FSR_RCAS_LIMIT,
+ min(max(lobeRGB.r, max(lobeRGB.g, lobeRGB.b)), 0.)
+ )*con;
+ // Apply noise removal.
+ #ifdef FSR_RCAS_DENOISE
+ lobe *= nz;
+ #endif
+ // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes.
+ return (lobe * (b + d + h + f) + e) / (4. * lobe + 1.);
+}
+
+
+vec4 FsrRcasLoadF(vec2 p) {
+ return COMPAT_TEXTURE(Source,p/OutputSize.xy);
+}
+
+void main()
+{
+ vec2 fragCoord = vTexCoord.xy * OutputSize.xy;
+
+ // Set up constants
+ float con;
+ FsrRcasCon(con, FSR_SHARPENING);
+
+ // Perform RCAS pass
+ vec3 col = FsrRcasF(fragCoord, con);
+
+ FragColor = vec4(col,1);
+}
+
+#endif
diff --git a/Shaders/xbrz/xbrz-freescale.glsl b/Shaders/xbrz/xbrz-freescale-multipass.glsl
similarity index 66%
rename from Shaders/xbrz/xbrz-freescale.glsl
rename to Shaders/xbrz/xbrz-freescale-multipass.glsl
index 3cc9eddec..5a01406d2 100644
--- a/Shaders/xbrz/xbrz-freescale.glsl
+++ b/Shaders/xbrz/xbrz-freescale-multipass.glsl
@@ -78,12 +78,6 @@ uniform COMPAT_PRECISION vec2 InputSize;
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)
-#ifdef PARAMETER_UNIFORM
-uniform COMPAT_PRECISION float WHATEVER;
-#else
-#define WHATEVER 0.0
-#endif
-
void main()
{
gl_Position = MVPMatrix * VertexCoord;
@@ -120,6 +114,7 @@ uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
+// in variables go here as COMPAT_VARYING whatever
// compatibility #defines
#define Source Texture
@@ -181,7 +176,6 @@ void main()
// x|G|H|I|x
// -|x|x|x|-
- vec2 scale = OutputSize.xy * SourceSize.zw;
vec2 pos = fract(vTexCoord * SourceSize.xy) - vec2(0.5, 0.5);
vec2 coord = vTexCoord - pos * SourceSize.zw;
@@ -207,8 +201,8 @@ void main()
// -|-|x|x|-
if (!((eq(E,F) && eq(H,I)) || (eq(E,H) && eq(F,I))))
{
- float dist_H_F = DistYCbCr(G, E) + DistYCbCr(E, C) + DistYCbCr(P(0,2), I) + DistYCbCr(I, P(2.,0.)) + (4.0 * DistYCbCr(H, F));
- float dist_E_I = DistYCbCr(D, H) + DistYCbCr(H, P(1,2)) + DistYCbCr(B, F) + DistYCbCr(F, P(2.,1.)) + (4.0 * DistYCbCr(E, I));
+ float dist_H_F = DistYCbCr(G, E) + DistYCbCr(E, C) + DistYCbCr(P(0.,2.), I) + DistYCbCr(I, P(2.,0.)) + (4.0 * DistYCbCr(H, F));
+ float dist_E_I = DistYCbCr(D, H) + DistYCbCr(H, P(1.,2.)) + DistYCbCr(B, F) + DistYCbCr(F, P(2.,1.)) + (4.0 * DistYCbCr(E, I));
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_H_F) < dist_E_I;
blendResult.z = ((dist_H_F < dist_E_I) && neq(E,F) && neq(E,H)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
}
@@ -234,7 +228,7 @@ void main()
// -|-|-|-|-
if (!((eq(B,C) && eq(E,F)) || (eq(B,E) && eq(C,F))))
{
- float dist_E_C = DistYCbCr(D, B) + DistYCbCr(B, P(1.,-2.)) + DistYCbCr(H, F) + DistYCbCr(F, P(2.,-1.)) + (4.0 * DistYCbCr(E, C));
+ float dist_E_C = DistYCbCr(D, B) + DistYCbCr(B, P(1,-2)) + DistYCbCr(H, F) + DistYCbCr(F, P(2.,-1.)) + (4.0 * DistYCbCr(E, C));
float dist_B_F = DistYCbCr(A, E) + DistYCbCr(E, I) + DistYCbCr(P(0.,-2.), C) + DistYCbCr(C, P(2.,0.)) + (4.0 * DistYCbCr(B, F));
bool dominantGradient = (DOMINANT_DIRECTION_THRESHOLD * dist_B_F) < dist_E_C;
blendResult.y = ((dist_E_C > dist_B_F) && neq(E,B) && neq(E,F)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
@@ -253,123 +247,91 @@ void main()
blendResult.x = ((dist_D_B < dist_A_E) && neq(E,D) && neq(E,B)) ? ((dominantGradient) ? BLEND_DOMINANT : BLEND_NORMAL) : BLEND_NONE;
}
- vec3 res = E;
+ FragColor = vec4(blendResult);
// Pixel Tap Mapping: -|-|-|-|-
// -|-|B|C|-
// -|D|E|F|x
// -|G|H|I|x
// -|-|x|x|-
- if(blendResult.z != BLEND_NONE)
- {
- float dist_F_G = DistYCbCr(F, G);
- float dist_H_C = DistYCbCr(H, C);
- bool doLineBlend = (blendResult.z == BLEND_DOMINANT ||
- !((blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || (blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) ||
- (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && IsPixEqual(F, C) && !IsPixEqual(E, I))));
+ if(blendResult.z == BLEND_DOMINANT || (blendResult.z == BLEND_NORMAL &&
+ !((blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) || (blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) ||
+ (IsPixEqual(G, H) && IsPixEqual(H, I) && IsPixEqual(I, F) && IsPixEqual(F, C) && !IsPixEqual(E, I)))))
+ {
+ FragColor.z += 4.0;
- vec2 origin = vec2(0.0, 1.0 / sqrt(2.0));
- vec2 direction = vec2(1.0, -1.0);
- if(doLineBlend)
- {
- bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && neq(E,G) && neq(D,G);
- bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && neq(E,C) && neq(B,C);
- origin = haveShallowLine? vec2(0.0, 0.25) : vec2(0.0, 0.5);
- direction.x += haveShallowLine? 1.0: 0.0;
- direction.y -= haveSteepLine? 1.0: 0.0;
- }
+ float dist_F_G = DistYCbCr(F, G);
+ float dist_H_C = DistYCbCr(H, C);
- vec3 blendPix = mix(H,F, step(DistYCbCr(E, F), DistYCbCr(E, H)));
- res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
- }
+ if((STEEP_DIRECTION_THRESHOLD * dist_F_G <= dist_H_C) && neq(E,G) && neq(D,G))
+ FragColor.z += 16.0;
+
+ if((STEEP_DIRECTION_THRESHOLD * dist_H_C <= dist_F_G) && neq(E,C) && neq(B,C))
+ FragColor.z += 64.0;
+ }
// Pixel Tap Mapping: -|-|-|-|-
// -|A|B|-|-
// x|D|E|F|-
// x|G|H|I|-
// -|x|x|-|-
- if(blendResult.w != BLEND_NONE)
- {
- float dist_H_A = DistYCbCr(H, A);
- float dist_D_I = DistYCbCr(D, I);
- bool doLineBlend = (blendResult.w == BLEND_DOMINANT ||
- !((blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || (blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) ||
- (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && IsPixEqual(H, I) && !IsPixEqual(E, G))));
+ if(blendResult.w == BLEND_DOMINANT || (blendResult.w == BLEND_NORMAL &&
+ !((blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) || (blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) ||
+ (IsPixEqual(A, D) && IsPixEqual(D, G) && IsPixEqual(G, H) && IsPixEqual(H, I) && !IsPixEqual(E, G)))))
+ {
+ FragColor.w += 4.0;
- vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0);
- vec2 direction = vec2(1.0, 1.0);
- if(doLineBlend)
- {
- bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && neq(E,A) && neq(B,A);
- bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && neq(E,I) && neq(F,I);
- origin = haveShallowLine? vec2(-0.25, 0.0) : vec2(-0.5, 0.0);
- direction.y += haveShallowLine? 1.0: 0.0;
- direction.x += haveSteepLine? 1.0: 0.0;
- }
- origin = origin;
- direction = direction;
+ float dist_H_A = DistYCbCr(H, A);
+ float dist_D_I = DistYCbCr(D, I);
- vec3 blendPix = mix(H,D, step(DistYCbCr(E, D), DistYCbCr(E, H)));
- res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
- }
+ if((STEEP_DIRECTION_THRESHOLD * dist_H_A <= dist_D_I) && neq(E,A) && neq(B,A))
+ FragColor.w += 16.0;
+
+ if((STEEP_DIRECTION_THRESHOLD * dist_D_I <= dist_H_A) && neq(E,I) && neq(F,I))
+ FragColor.w += 64.0;
+ }
// Pixel Tap Mapping: -|-|x|x|-
// -|A|B|C|x
// -|D|E|F|x
// -|-|H|I|-
// -|-|-|-|-
- if(blendResult.y != BLEND_NONE)
- {
- float dist_B_I = DistYCbCr(B, I);
- float dist_F_A = DistYCbCr(F, A);
- bool doLineBlend = (blendResult.y == BLEND_DOMINANT ||
- !((blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || (blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) ||
- (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && IsPixEqual(B, A) && !IsPixEqual(E, C))));
+ if(blendResult.y == BLEND_DOMINANT || (blendResult.y == BLEND_NORMAL &&
+ !((blendResult.x != BLEND_NONE && !IsPixEqual(E, I)) || (blendResult.z != BLEND_NONE && !IsPixEqual(E, A)) ||
+ (IsPixEqual(I, F) && IsPixEqual(F, C) && IsPixEqual(C, B) && IsPixEqual(B, A) && !IsPixEqual(E, C)))))
+ {
+ FragColor.y += 4.0;
- vec2 origin = vec2(1.0 / sqrt(2.0), 0.0);
- vec2 direction = vec2(-1.0, -1.0);
+ float dist_B_I = DistYCbCr(B, I);
+ float dist_F_A = DistYCbCr(F, A);
- if(doLineBlend)
- {
- bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && neq(E,I) && neq(H,I);
- bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && neq(E,A) && neq(D,A);
- origin = haveShallowLine? vec2(0.25, 0.0) : vec2(0.5, 0.0);
- direction.y -= haveShallowLine? 1.0: 0.0;
- direction.x -= haveSteepLine? 1.0: 0.0;
- }
+ if((STEEP_DIRECTION_THRESHOLD * dist_B_I <= dist_F_A) && neq(E,I) && neq(H,I))
+ FragColor.y += 16.0;
- vec3 blendPix = mix(F,B, step(DistYCbCr(E, B), DistYCbCr(E, F)));
- res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
- }
+ if((STEEP_DIRECTION_THRESHOLD * dist_F_A <= dist_B_I) && neq(E,A) && neq(D,A))
+ FragColor.y += 64.0;
+ }
// Pixel Tap Mapping: -|x|x|-|-
// x|A|B|C|-
// x|D|E|F|-
// -|G|H|-|-
// -|-|-|-|-
- if(blendResult.x != BLEND_NONE)
- {
- float dist_D_C = DistYCbCr(D, C);
- float dist_B_G = DistYCbCr(B, G);
- bool doLineBlend = (blendResult.x == BLEND_DOMINANT ||
- !((blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || (blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) ||
- (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && IsPixEqual(D, G) && !IsPixEqual(E, A))));
+ if(blendResult.x == BLEND_DOMINANT || (blendResult.x == BLEND_NORMAL &&
+ !((blendResult.w != BLEND_NONE && !IsPixEqual(E, C)) || (blendResult.y != BLEND_NONE && !IsPixEqual(E, G)) ||
+ (IsPixEqual(C, B) && IsPixEqual(B, A) && IsPixEqual(A, D) && IsPixEqual(D, G) && !IsPixEqual(E, A)))))
+ {
+ FragColor.x += 4.0;
- vec2 origin = vec2(0.0, -1.0 / sqrt(2.0));
- vec2 direction = vec2(-1.0, 1.0);
- if(doLineBlend)
- {
- bool haveShallowLine = (STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && neq(E,C) && neq(F,C);
- bool haveSteepLine = (STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && neq(E,G) && neq(H,G);
- origin = haveShallowLine? vec2(0.0, -0.25) : vec2(0.0, -0.5);
- direction.x -= haveShallowLine? 1.0: 0.0;
- direction.y += haveSteepLine? 1.0: 0.0;
- }
+ float dist_D_C = DistYCbCr(D, C);
+ float dist_B_G = DistYCbCr(B, G);
- vec3 blendPix = mix(D,B, step(DistYCbCr(E, B), DistYCbCr(E, D)));
- res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
- }
+ if((STEEP_DIRECTION_THRESHOLD * dist_D_C <= dist_B_G) && neq(E,C) && neq(F,C))
+ FragColor.x += 16.0;
- FragColor = vec4(res, 1.0);
+ if((STEEP_DIRECTION_THRESHOLD * dist_B_G <= dist_D_C) && neq(E,G) && neq(H,G))
+ FragColor.x += 64.0;
+ }
+ FragColor /= 255.0;
}
#endif
diff --git a/Shaders/xbrz/xbrz-freescale-multipass.glsl.pass1 b/Shaders/xbrz/xbrz-freescale-multipass.glsl.pass1
new file mode 100644
index 000000000..0001c2dcb
--- /dev/null
+++ b/Shaders/xbrz/xbrz-freescale-multipass.glsl.pass1
@@ -0,0 +1,277 @@
+/*
+ Hyllian's xBR-vertex code and texel mapping
+
+ Copyright (C) 2011/2016 Hyllian - sergiogdb@gmail.com
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+*/
+
+// This shader also uses code and/or concepts from xBRZ as it appears
+// in the Desmume source code. The license for which is as follows:
+
+// ****************************************************************************
+// * This file is part of the HqMAME project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
+// * *
+// * Additionally and as a special exception, the author gives permission *
+// * to link the code of this program with the MAME library (or with modified *
+// * versions of MAME that use the same license as MAME), and distribute *
+// * linked combinations including the two. You must obey the GNU General *
+// * Public License in all respects for all of the code used other than MAME. *
+// * If you modify this file, you may extend this exception to your version *
+// * of the file, but you are not obligated to do so. If you do not wish to *
+// * do so, delete this exception statement from your version. *
+// ****************************************************************************
+
+#if defined(VERTEX)
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING out
+#define COMPAT_ATTRIBUTE in
+#define COMPAT_TEXTURE texture
+#else
+#define COMPAT_VARYING varying
+#define COMPAT_ATTRIBUTE attribute
+#define COMPAT_TEXTURE texture2D
+#endif
+
+#ifdef GL_ES
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+COMPAT_ATTRIBUTE vec4 VertexCoord;
+COMPAT_ATTRIBUTE vec4 COLOR;
+COMPAT_ATTRIBUTE vec4 TexCoord;
+COMPAT_VARYING vec4 COL0;
+COMPAT_VARYING vec4 TEX0;
+
+vec4 _oPosition1;
+uniform mat4 MVPMatrix;
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+
+// compatibility #defines
+#define vTexCoord TEX0.xy
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define OutSize vec4(OutputSize, 1.0 / OutputSize)
+
+void main()
+{
+ gl_Position = MVPMatrix * VertexCoord;
+ TEX0.xy = TexCoord.xy * 1.0001;
+}
+
+#elif defined(FRAGMENT)
+
+#ifdef GL_ES
+#ifdef GL_FRAGMENT_PRECISION_HIGH
+precision highp float;
+#else
+precision mediump float;
+#endif
+#define COMPAT_PRECISION mediump
+#else
+#define COMPAT_PRECISION
+#endif
+
+#if __VERSION__ >= 130
+#define COMPAT_VARYING in
+#define COMPAT_TEXTURE texture
+out COMPAT_PRECISION vec4 FragColor;
+#else
+#define COMPAT_VARYING varying
+#define FragColor gl_FragColor
+#define COMPAT_TEXTURE texture2D
+#endif
+
+uniform COMPAT_PRECISION int FrameDirection;
+uniform COMPAT_PRECISION int FrameCount;
+uniform COMPAT_PRECISION vec2 OutputSize;
+uniform COMPAT_PRECISION vec2 TextureSize;
+uniform COMPAT_PRECISION vec2 InputSize;
+uniform sampler2D Texture;
+uniform sampler2D PassPrev2Texture;
+uniform COMPAT_PRECISION vec2 PassPrev2TextureSize;
+COMPAT_VARYING vec4 TEX0;
+
+// compatibility #defines
+#define Source Texture
+#define vTexCoord TEX0.xy
+
+#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
+#define OutSize vec4(OutputSize, 1.0 / OutputSize)
+#define OriginalSize vec4(PassPrev2TextureSize, 1.0 / PassPrev2TextureSize)
+
+#define BLEND_NONE 0.
+#define BLEND_NORMAL 1.
+#define BLEND_DOMINANT 2.
+#define LUMINANCE_WEIGHT 1.0
+#define EQUAL_COLOR_TOLERANCE 30.0/255.0
+#define STEEP_DIRECTION_THRESHOLD 2.2
+#define DOMINANT_DIRECTION_THRESHOLD 3.6
+
+float DistYCbCr(vec3 pixA, vec3 pixB)
+{
+ const vec3 w = vec3(0.2627, 0.6780, 0.0593);
+ const float scaleB = 0.5 / (1.0 - w.b);
+ const float scaleR = 0.5 / (1.0 - w.r);
+ vec3 diff = pixA - pixB;
+ float Y = dot(diff.rgb, w);
+ float Cb = scaleB * (diff.b - Y);
+ float Cr = scaleR * (diff.r - Y);
+
+ return sqrt(((LUMINANCE_WEIGHT * Y) * (LUMINANCE_WEIGHT * Y)) + (Cb * Cb) + (Cr * Cr));
+}
+
+bool IsPixEqual(const vec3 pixA, const vec3 pixB)
+{
+ return (DistYCbCr(pixA, pixB) < EQUAL_COLOR_TOLERANCE);
+}
+
+float get_left_ratio(vec2 center, vec2 origin, vec2 direction, vec2 scale)
+{
+ vec2 P0 = center - origin;
+ vec2 proj = direction * (dot(P0, direction) / dot(direction, direction));
+ vec2 distv = P0 - proj;
+ vec2 orth = vec2(-direction.y, direction.x);
+ float side = sign(dot(P0, orth));
+ float v = side * length(distv * scale);
+
+// return step(0, v);
+ return smoothstep(-sqrt(2.0)/2.0, sqrt(2.0)/2.0, v);
+}
+
+#define eq(a,b) (a == b)
+#define neq(a,b) (a != b)
+
+#define P(x,y) COMPAT_TEXTURE(PassPrev2Texture, coord + OriginalSize.zw * vec2(x, y)).rgb
+
+void main()
+{
+ //---------------------------------------
+ // Input Pixel Mapping: -|B|-
+ // D|E|F
+ // -|H|-
+
+ vec2 scale = OutputSize.xy * OriginalSize.zw;
+ vec2 pos = fract(vTexCoord * OriginalSize.xy) - vec2(0.5, 0.5);
+ vec2 coord = vTexCoord - pos * OriginalSize.zw;
+
+ vec3 B = P( 0.,-1.);
+ vec3 D = P(-1., 0.);
+ vec3 E = P( 0., 0.);
+ vec3 F = P( 1., 0.);
+ vec3 H = P( 0., 1.);
+
+ vec4 info = floor(COMPAT_TEXTURE(Source, coord) * 255.0 + 0.5);
+
+ // info Mapping: x|y|
+ // w|z|
+
+ vec4 blendResult = floor(mod(info, 4.0));
+ vec4 doLineBlend = floor(mod(info / 4.0, 4.0));
+ vec4 haveShallowLine = floor(mod(info / 16.0, 4.0));
+ vec4 haveSteepLine = floor(mod(info / 64.0, 4.0));
+
+ vec3 res = E;
+
+ // Pixel Tap Mapping: -|-|-
+ // -|E|F
+ // -|H|-
+
+ if(blendResult.z > BLEND_NONE)
+ {
+ vec2 origin = vec2(0.0, 1.0 / sqrt(2.0));
+ vec2 direction = vec2(1.0, -1.0);
+ if(doLineBlend.z > 0.0)
+ {
+ origin = haveShallowLine.z > 0.0? vec2(0.0, 0.25) : vec2(0.0, 0.5);
+ direction.x += haveShallowLine.z;
+ direction.y -= haveSteepLine.z;
+ }
+
+ vec3 blendPix = mix(H,F, step(DistYCbCr(E, F), DistYCbCr(E, H)));
+ res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
+ }
+
+ // Pixel Tap Mapping: -|-|-
+ // D|E|-
+ // -|H|-
+ if(blendResult.w > BLEND_NONE)
+ {
+ vec2 origin = vec2(-1.0 / sqrt(2.0), 0.0);
+ vec2 direction = vec2(1.0, 1.0);
+ if(doLineBlend.w > 0.0)
+ {
+ origin = haveShallowLine.w > 0.0? vec2(-0.25, 0.0) : vec2(-0.5, 0.0);
+ direction.y += haveShallowLine.w;
+ direction.x += haveSteepLine.w;
+ }
+
+ vec3 blendPix = mix(H,D, step(DistYCbCr(E, D), DistYCbCr(E, H)));
+ res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
+ }
+
+ // Pixel Tap Mapping: -|B|-
+ // -|E|F
+ // -|-|-
+ if(blendResult.y > BLEND_NONE)
+ {
+ vec2 origin = vec2(1.0 / sqrt(2.0), 0.0);
+ vec2 direction = vec2(-1.0, -1.0);
+
+ if(doLineBlend.y > 0.0)
+ {
+ origin = haveShallowLine.y > 0.0? vec2(0.25, 0.0) : vec2(0.5, 0.0);
+ direction.y -= haveShallowLine.y;
+ direction.x -= haveSteepLine.y;
+ }
+
+ vec3 blendPix = mix(F,B, step(DistYCbCr(E, B), DistYCbCr(E, F)));
+ res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
+ }
+
+ // Pixel Tap Mapping: -|B|-
+ // D|E|-
+ // -|-|-
+ if(blendResult.x > BLEND_NONE)
+ {
+ vec2 origin = vec2(0.0, -1.0 / sqrt(2.0));
+ vec2 direction = vec2(-1.0, 1.0);
+ if(doLineBlend.x > 0.0)
+ {
+ origin = haveShallowLine.x > 0.0? vec2(0.0, -0.25) : vec2(0.0, -0.5);
+ direction.x -= haveShallowLine.x;
+ direction.y += haveSteepLine.x;
+ }
+
+ vec3 blendPix = mix(D,B, step(DistYCbCr(E, B), DistYCbCr(E, D)));
+ res = mix(res, blendPix, get_left_ratio(pos, origin, direction, scale));
+ }
+
+ FragColor = vec4(res, 1.0);
+}
+#endif
diff --git a/cnc-ddraw config.exe b/cnc-ddraw config.exe
index 2a5fb8d31..3ad01cd56 100644
Binary files a/cnc-ddraw config.exe and b/cnc-ddraw config.exe differ
diff --git a/ddraw.dll b/ddraw.dll
index 8ef5eb725..57da59487 100644
Binary files a/ddraw.dll and b/ddraw.dll differ
diff --git a/ddraw.ini b/ddraw.ini
index aa0540341..159497f89 100644
--- a/ddraw.ini
+++ b/ddraw.ini
@@ -19,6 +19,9 @@ windowed=true
; Maintain aspect ratio
maintas=false
+; Use custom aspect ratio - Example values: 4:3, 16:10, 16:9, 21:9
+aspect_ratio=
+
; Windowboxing / Integer Scaling
boxing=false
@@ -36,7 +39,9 @@ adjmouse=true
; Preliminary libretro shader support - (Requires 'renderer=opengl*') https://github.com/libretro/glsl-shaders
; 2x scaling example: https://imgur.com/a/kxsM1oY - 4x scaling example: https://imgur.com/a/wjrhpFV
-shader=Shaders\cubic\catmull-rom-bilinear.glsl
+; You can specify a full path to a .glsl shader file here or use one of the values listed below
+; Possible values: Nearest neighbor, Bilinear, Bicubic, Lanczos, xBR-lv2
+shader=Shaders\interpolation\catmull-rom-bilinear.glsl
; Window position, -32000 = center to screen
posX=-32000
@@ -59,24 +64,35 @@ savesettings=1
resizable=true
; Upscaling filter for the direct3d9* renderers
-; Possible values: 0 = nearest-neighbor, 1 = bilinear, 2 = bicubic (16/32bit color depth games only)
+; Possible values: 0 = nearest-neighbor, 1 = bilinear, 2 = bicubic, 3 = lanczos (bicubic/lanczos only support 16/32bit color depth games)
d3d9_filter=2
-; Enable upscale hack for high resolution patches (Supports C&C1, Red Alert 1 and KKND Xtreme)
+; Disable font smoothing for fonts that are smaller than size X
+anti_aliased_fonts_min_size=13
+
+; Raise the size of small fonts to X
+min_font_size=0
+
+; Center window to screen when game changes the display resolution
+; Possible values: 0 = never center, 1 = automatic, 2 = always center
+center_window=1
+
+; Inject a custom display resolution into the in-game resolution list - Example values: 960x540, 3840x2160
+; Note: This setting can used for downscaling as well, you can insert resolutions higher than your monitor supports
+inject_resolution=
+
+; Enable upscale hack for high resolution patches (Supports C&C1, Red Alert 1, Worms 2 and KKND Xtreme)
vhack=false
-; cnc-ddraw config program language, possible values: auto, english, chinese, german, spanish, russian, hungarian, french, italian
-configlang=auto
-
-; cnc-ddraw config program theme, possible values: Windows10, Cobalt XEMedia
-configtheme=Windows10
-
; Where should screenshots be saved
screenshotdir=.\Screenshots\
; Switch between windowed/borderless modes with alt+enter rather than windowed/fullscreen modes
toggle_borderless=true
+; Switch between windowed/fullscreen upscaled modes with alt+enter rather than windowed/fullscreen modes
+toggle_upscaled=false
+
; ### Compatibility settings ###
@@ -84,53 +100,61 @@ toggle_borderless=true
; Hide WM_ACTIVATEAPP and WM_NCACTIVATE messages to prevent problems on alt+tab
-noactivateapp=true
+noactivateapp=false
; Max game ticks per second, possible values: -1 = disabled, -2 = refresh rate, 0 = emulate 60hz vblank, 1-1000 = custom game speed
; Note: Can be used to slow down a too fast running game, fix flickering or too fast animations
; Note: Usually one of the following values will work: 60 / 30 / 25 / 20 / 15 (lower value = slower game speed)
maxgameticks=-1
+; Method that should be used to limit game ticks (maxgameticks=): 0 = Automatic, 1 = TestCooperativeLevel, 2 = BltFast, 3 = Unlock, 4 = PeekMessage
+limiter_type=0
+
; Force minimum FPS, possible values: 0 = disabled, -1 = use 'maxfps=' value, -2 = same as -1 but force full redraw, 1-1000 = custom FPS
; Note: Set this to a low value such as 5 or 10 if some parts of the game are not being displayed (e.g. menus or loading screens)
minfps=0
; Disable fullscreen-exclusive mode for the direct3d9*/opengl* renderers
; Note: Can be used in case some GUI elements like buttons/textboxes/videos/etc.. are invisible
-nonexclusive=false
+nonexclusive=true
; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact
; Note: Disable this if the game is not running smooth or there are sound issues
singlecpu=false
-; Available resolutions, possible values: 0 = Small list, 1 = Very small list, 2 = Full list
+; Available display resolutions, possible values: 0 = Small list, 1 = Very small list, 2 = Full list
; Note: Set this to 2 if your chosen resolution is not working or does not show up in the list
; Note: Set this to 1 if the game is crashing on startup
resolutions=0
-; Child window handling, possible values: 0 = Disabled, 1 = Display top left, 2 = Display top left + repaint, 3 = Hide
+; Child window handling, possible values: 0 = Disabled, 1 = Display top left, 2 = Display top left + repaint, 3 = Hide, 4 = Display top left + hide
; Note: Disables upscaling if a child window was detected (to ensure the game is fully playable, may look weird though)
fixchilds=2
-; Enable the following setting if your cursor doesn't work properly when upscaling is enabled
+; Enable the following setting if your cursor doesn't lock to the window or it doesn't work properly when upscaling is enabled
hook_peekmessage=false
-; Undocumented settings - You may or may not change these (You should rather focus on the settings above)
-releasealt=true
+; Undocumented compatibility settings - These will probably not solve your problem, you should rather focus on the settings above
+fix_alt_key_stuck=true
game_handles_close=false
-fixnotresponding=false
-hook=4
+fix_not_responding=false
+no_compat_warning=false
guard_lines=200
max_resolutions=0
-limit_bltfast=false
lock_surfaces=false
-allow_wmactivate=false
flipclear=false
-fixmousehook=true
rgb555=false
no_dinput_hook=false
-
+center_cursor_fix=false
+;fake_mode=640x480x32
+lock_mouse_top_left=false
+;win_version=95
+hook=4
+limit_gdi_handles=false
+remove_menu=false
+refresh_rate=0
+sirtech_hack=true
; ### Hotkeys ###
@@ -141,9 +165,15 @@ no_dinput_hook=false
; Switch between windowed and fullscreen mode = [Alt] + ???
keytogglefullscreen=0x0D
+; Switch between windowed and fullscreen mode (single key) = ???
+keytogglefullscreen2=0x00
+
; Maximize window = [Alt] + ???
keytogglemaximize=0x22
+; Maximize window (single key) = ???
+keytogglemaximize2=0x00
+
; Unlock cursor 1 = [Ctrl] + ???
keyunlockcursor1=0x09
@@ -155,16 +185,36 @@ keyscreenshot=0x2C
+; ### Config program settings ###
+; The following settings are for cnc-ddraw config.exe
+
+
+; cnc-ddraw config program language, possible values: auto, english, chinese, german, spanish, russian, hungarian, french, italian, vietnamese
+configlang=auto
+
+; cnc-ddraw config program theme, possible values: Windows10, Cobalt XEMedia
+configtheme=Windows10
+
+; Hide the 'Compatibility Settings' tab in cnc-ddraw config
+hide_compat_tab=false
+
+; Allow the users to 'Restore default settings' via cnc-ddraw config
+allow_reset=false
+
+
+
; ### Game specific settings ###
; The following settings override all settings shown above, section name = executable name
+; 7th Legion
+[legion]
+maxgameticks=25
+singlecpu=false
+
; Atrox
[Atrox]
-renderer=gdi
-hook=2
-fixchilds=0
-allow_wmactivate=true
+nonexclusive=true
; Atomic Bomberman
[BM]
@@ -182,6 +232,12 @@ nonexclusive=true
adjmouse=true
resolutions=2
+; Age of Empires: The Rise of Rome (RockNRor patch)
+[EmpiresX_RockNRor]
+nonexclusive=true
+adjmouse=true
+resolutions=2
+
; Age of Empires II
[EMPIRES2]
nonexclusive=true
@@ -192,22 +248,47 @@ adjmouse=true
nonexclusive=true
adjmouse=true
+; Abomination - The Nemesis Project
+[abomb]
+singlecpu=false
+
; American Conquest / Cossacks
[DMCR]
resolutions=2
guard_lines=300
minfps=-2
+; American Girls Dress Designer
+[Dress Designer]
+fake_mode=640x480x32
+nonexclusive=true
+
+; Age of Wonders
+[AoW]
+resolutions=2
+nonexclusive=false
+singlecpu=false
+
+; Age of Wonders
+[AoWCompat]
+resolutions=2
+nonexclusive=false
+singlecpu=false
+
+; Age of Wonders Config Tool
+[AoWSetup]
+resolutions=2
+
; Age of Wonders 2
[AoW2]
resolutions=2
-renderer=opengl
+nonexclusive=false
singlecpu=false
; Age of Wonders 2
[AoW2Compat]
resolutions=2
-renderer=opengl
+nonexclusive=false
singlecpu=false
; Age of Wonders 2 Config Tool
@@ -217,13 +298,13 @@ resolutions=2
; Age of Wonders: Shadow Magic
[AoWSM]
resolutions=2
-renderer=opengl
+nonexclusive=false
singlecpu=false
; Age of Wonders: Shadow Magic
[AoWSMCompat]
resolutions=2
-renderer=opengl
+nonexclusive=false
singlecpu=false
; Age of Wonders: Shadow Magic Config Tool
@@ -239,24 +320,81 @@ adjmouse=true
[1602]
adjmouse=true
+; Army Men: World War / Army Men: Operation Meltdown
+[amww]
+maxfps=60
+maxgameticks=120
+minfps=-1
+
+; Army Men: Air Tactics
+[Amat]
+maxfps=60
+maxgameticks=120
+minfps=-1
+
+; Army Men: Toys in Space
+[ARMYMENTIS]
+maxfps=60
+maxgameticks=120
+minfps=-1
+
+; Army Men 2
+[ArmyMen2]
+maxfps=60
+maxgameticks=120
+minfps=-1
+
; Alien Nations
[AN]
adjmouse=true
+; Another War
+[AnotherWar]
+singlecpu=false
+
; Atlantis
[ATLANTIS]
renderer=opengl
maxgameticks=60
+center_cursor_fix=true
; Airline Tycoon Deluxe
[AT]
-fixchilds=0
+lock_mouse_top_left=true
+fixchilds=3
+
+; Arthur's Wilderness Rescue
+[Arthur]
+renderer=gdi
+
+; Axis & Allies
+[AxisAllies]
+hook_peekmessage=true
+maxgameticks=60
+
+; A Bug's Life Action Game
+[bugs]
+fix_not_responding=true
+
+; Barney - Secret of the Rainbow
+[Barney]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
; Baldur's Gate II
; Note: 'Use 3D Acceleration' must be disabled and 'Full Screen' must be enabled in BGConfig.exe
[BGMain]
resolutions=2
+; Balls of Steel v1.2
+[bos]
+checkfile=.\barbarin.ddp
+win_version=95
+
; BALDR FORCE EXE
[BaldrForce]
noactivateapp=true
@@ -271,19 +409,60 @@ fixchilds=3
checkfile=.\SOUND.REZ
noactivateapp=true
+; Blue's 123 Time Activities
+[Blues123Time]
+renderer=gdi
+hook=3
+
+; Blue's Treasure Hunt
+[Blue'sTreasureHunt-Disc1]
+renderer=gdi
+
+; Blue's Treasure Hunt
+[Blue'sTreasureHunt-Disc2]
+renderer=gdi
+
+; Blue's Reading Time Activities
+[Blue's Reading Time]
+renderer=gdi
+
+; Blue's ArtTime Activities
+[ArtTime]
+renderer=gdi
+
+; Callus 95 - CPS-1 (Capcom Play System 1) emulator
+[CALLUS95]
+game_handles_close=true
+windowed=true
+toggle_borderless=true
+devmode=true
+
+; Callus 95 - CPS-1 (Capcom Play System 1) emulator
+[CALLUS95p]
+game_handles_close=true
+windowed=true
+toggle_borderless=true
+devmode=true
+
; Carmageddon
[CARMA95]
-noactivateapp=true
flipclear=true
+carma95_hack=true
; Carmageddon
[CARM95]
-noactivateapp=true
flipclear=true
+carma95_hack=true
-; Carmageddon 2
-[Carma2_SW]
-noactivateapp=true
+; Carmen Sandiego's Great Chase - NOT WORKING YET
+[TIME32]
+renderer=gdi
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
; Captain Claw
[claw]
@@ -291,6 +470,10 @@ adjmouse=true
noactivateapp=true
nonexclusive=true
+; Championship Manager 99-00
+[cm9900]
+singlecpu=false
+
; Command & Conquer: Sole Survivor
[SOLE]
maxgameticks=120
@@ -330,6 +513,7 @@ minfps=-1
; Command & Conquer: Tiberian Sun / Command & Conquer: Red Alert 2
[game]
+nonexclusive=false
checkfile=.\blowfish.dll
tshack=true
noactivateapp=true
@@ -341,6 +525,7 @@ boxing=false
; Command & Conquer: Tiberian Sun Demo
[SUN]
+nonexclusive=false
noactivateapp=true
tshack=true
adjmouse=true
@@ -351,6 +536,7 @@ boxing=false
; Command & Conquer: Tiberian Sun - CnCNet
[ts-spawn]
+nonexclusive=false
noactivateapp=true
tshack=true
adjmouse=true
@@ -361,6 +547,7 @@ boxing=false
; Command & Conquer: Red Alert 2 - XWIS
[ra2]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -370,6 +557,7 @@ boxing=false
; Command & Conquer: Red Alert 2 - XWIS
[Red Alert 2]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -379,6 +567,7 @@ boxing=false
; Command & Conquer: Red Alert 2: Yuri's Revenge
[gamemd]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -388,6 +577,7 @@ boxing=false
; Command & Conquer: Red Alert 2: Yuri's Revenge - ?ModExe?
[ra2md]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -397,6 +587,7 @@ boxing=false
; Command & Conquer: Red Alert 2: Yuri's Revenge - CnCNet
[gamemd-spawn]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -406,6 +597,7 @@ boxing=false
; Command & Conquer: Red Alert 2: Yuri's Revenge - XWIS
[Yuri's Revenge]
+nonexclusive=false
noactivateapp=true
tshack=true
maxfps=60
@@ -413,13 +605,26 @@ minfps=-1
maintas=false
boxing=false
+; Commandos
+[comandos]
+maxgameticks=-1
+
+; Commandos
+[comandos_w10]
+maxgameticks=-1
+
+; Constructor
+[Game_W95]
+noactivateapp=true
+
; Caesar III
[c3]
nonexclusive=true
adjmouse=true
; Chris Sawyer's Locomotion
-[LOCO]
+[LOCO/2]
+checkfile=.\LOCO.EXE
adjmouse=true
; Cultures 2
@@ -450,6 +655,24 @@ nonexclusive=true
adjmouse=true
nonexclusive=true
+; ClueFinders Math Adventures 1.0
+[TCFM32]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; ClueFinders Math Adventures 1.0
+[cfmath32]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
; Call To Power 2
[ctp2]
maintas=false
@@ -464,11 +687,15 @@ adjmouse=true
resolutions=2
singlecpu=false
+; Die by the Sword
+[windie]
+maxgameticks=30
+
; Dragon Throne: Battle of Red Cliffs
[AdSanguo]
maxgameticks=60
noactivateapp=true
-limit_bltfast=true
+limiter_type=2
; Dark Reign: The Future of War
[DKReign]
@@ -479,6 +706,10 @@ maxgameticks=60
maxgameticks=60
noactivateapp=true
+; Dreams to Realty
+[windream]
+maxgameticks=60
+
; Deadlock 2
[DEADLOCK]
fixchilds=0
@@ -494,9 +725,27 @@ devmode=true
[hellfire]
devmode=true
+; Disney Trivia Challenge
+[DisneyTr]
+fixchilds=3
+lock_mouse_top_left=true
+renderer=gdi
+
+; Discoworld Noir
+[dn]
+fake_mode=640x480x16
+
+; Dominion - Storm Over Gift 3
+[dominion]
+flipclear=true
+
+; Excalibur 2555AD
+[_FISH]
+singlecpu=false
+
; Escape Velocity Nova
[EV Nova]
-devmode=true
+nonexclusive=true
hook_peekmessage=true
rgb555=true
keytogglefullscreen=0x46
@@ -505,25 +754,116 @@ adjmouse=true
; Economic War
[EcoW]
maxgameticks=60
-fixnotresponding=true
+fix_not_responding=true
+
+; Emperor: Rise of the Middle Kingdom
+[Emperor]
+nonexclusive=true
+adjmouse=true
+
+; Enemy Infestation
+[EI]
+hook_peekmessage=true
+
+; F-16 Agressor
+[f-16]
+resolutions=1
+
+; Fable
+[FABLE]
+singlecpu=false
+
+; Fallout Tactics: Brotherhood of Steel
+[BOS/2]
+checkfile=.\binkw32.dll
+hook_peekmessage=true
+
+; Fallout Tactics: Brotherhood of Steel
+[BOS_HR]
+hook_peekmessage=true
+
+; Fallout Tactics: Brotherhood of Steel
+[FT Tools]
+hook_peekmessage=true
+
+; Falcon 4.0 (Microprose version)
+[falcon4]
+singlecpu=false
+
+; Flight Simulator 98
+[FLTSIM95]
+flightsim98_hack=true
+
+; Flight Simulator 98
+[FLTSIM98]
+flightsim98_hack=true
; Fairy Tale About Father Frost, Ivan and Nastya
[mrazik]
guard_lines=0
+; Final Liberation: Warhammer Epic 40000
+[Epic40k]
+hook_peekmessage=true
+maxgameticks=125
+
; Future Cop - L.A.P.D.
[FCopLAPD]
nonexclusive=true
adjmouse=true
+; Freddi 1
+[Freddi1]
+renderer=gdi
+
+; Freddi Fish : The Case of the Hogfish Rustlers of Briny Gulch
+[Freddihrbg]
+renderer=gdi
+
+; Freddi Water Worries
+[Water]
+renderer=gdi
+
+; Freddi Fish
+[FreddiSCS]
+renderer=gdi
+
+; Freddi Fish
+[FREDDI4]
+renderer=gdi
+hook=3
+
+; Freddi Fish's One-Stop Fun Shop
+[FreddisFunShop]
+renderer=gdi
+
+; Freddi Fish: The Case of the Creature of Coral Cove
+[freddicove]
+renderer=gdi
+
+; Freddi Fish: The Case of the Haunted Schoolhouse
+[FreddiCHSH]
+renderer=gdi
+
+; Freddi Fish: Maze Madness
+[Maze]
+renderer=gdi
+
+; Glover
+[glover]
+fix_not_responding=true
+
; G-Police
[GPOLICE]
maxgameticks=60
+singlecpu=false
; Gangsters: Organized Crime
[gangsters]
adjmouse=true
nonexclusive=true
+fixchilds=0
+fake_mode=640x480x8
; Grand Theft Auto
[Grand Theft Auto]
@@ -537,17 +877,59 @@ singlecpu=false
[Gta_61]
singlecpu=false
+; Gruntz
+[GRUNTZ]
+adjmouse=true
+noactivateapp=true
+nonexclusive=true
+
+; Girl Talk
+[GirlTalk]
+resolutions=2
+game_handles_close=true
+
+; Jazz Jackrabbit 2 plus
+[Jazz2]
+inject_resolution=800x450
+
+; Jazz Jackrabbit 2
+[Jazz2_NonPlus]
+inject_resolution=800x450
+
+; Jungle Storm
+[Jstorm]
+no_compat_warning=true
+win_version=98
+
+; Hades Challenge
+[HADESCH]
+no_compat_warning=true
+
; Heroes of Might and Magic II: The Succession Wars
[HEROES2W]
adjmouse=true
; Heroes of Might and Magic III
[Heroes3]
+renderer=opengl
game_handles_close=true
+keytogglefullscreen2=0x73
; Heroes of Might and Magic III HD Mod
[Heroes3 HD]
+renderer=opengl
game_handles_close=true
+keytogglefullscreen2=0x73
+
+; Heroes of Might and Magic III - Master of Puppets mod
+[MoP]
+game_handles_close=true
+keytogglefullscreen2=0x73
+
+; Heroes of Might and Magic IV
+[heroes4]
+remove_menu=true
+keytogglefullscreen2=0x73
; Hard Truck: Road to Victory
[htruck]
@@ -555,6 +937,26 @@ maxgameticks=25
renderer=opengl
noactivateapp=true
+; Hooligans: Storm over Europe
+[hooligans]
+limit_gdi_handles=true
+
+; Imperialism 2: The Age of Exploration
+[Imperialism II]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Icewind Dale 2
+; Note: 'Full Screen' must be enabled in Config.exe
+; Note: 1070x602 is the lowest possible 16:9 resolution for the Widescreen patch (600/601 height will crash)
+[iwd2]
+resolutions=2
+inject_resolution=1070x602
+
; Invictus
[Invictus]
adjmouse=true
@@ -564,9 +966,14 @@ renderer=opengl
[i76]
adjmouse=true
-; Infantry Online
+; Infantry
[infantry]
-devmode=true
+resolutions=2
+infantryhack=true
+max_resolutions=90
+
+; Infantry Steam
+[FreeInfantry]
resolutions=2
infantryhack=true
max_resolutions=90
@@ -574,41 +981,42 @@ max_resolutions=90
; Jagged Alliance 2
[ja2]
singlecpu=false
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
; Jagged Alliance 2: Unfinished Business
[JA2UB]
singlecpu=false
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
; Jagged Alliance 2: Wildfire
[WF6]
singlecpu=false
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
; Jagged Alliance 2 - UC mod
[JA2_UC]
singlecpu=false
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
; Jagged Alliance 2 - Vengeance Reloaded mod
[JA2_Vengeance]
singlecpu=false
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
-; Kings Quest 8
-[Mask]
-renderer=opengl
+; Jeopardy! - NOT WORKING YET
+[jeoppc]
+singlecpu=false
+
+; Karma Immortal Wrath
+[karma]
+fix_not_responding=true
+maxgameticks=60
+limiter_type=4
; Konung
[konung]
@@ -626,10 +1034,129 @@ vhack=true
[KKND2]
noactivateapp=true
+; Knights and Merchants The Shattered Kingdom
+[KaM_800]
+limiter_type=2
+maxgameticks=60
+
+; Knights and Merchants The Shattered Kingdom
+[KaM_1024]
+limiter_type=2
+maxgameticks=60
+
+; Lode Runner 2
+[LR2]
+no_dinput_hook=true
+fake_mode=640x480x16
+
+; Last Bronx
+[LB]
+maxgameticks=30
+
+; Lapis (lapis.mgame.com)
+[Lapis]
+fixchilds=3
+lock_mouse_top_left=true
+
+; LEGO LOCO - NOT WORKING YET
+[LOCO]
+checkfile=.\LEGO.INI
+fake_mode=1024x768x16
+posX=0
+posY=0
+border=false
+fullscreen=false
+
+; Little Bear Kindergarten/Preschool Thinking Adventures: Parent's Progress Report
+[LBPR]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Little Bear Kindergarten/Preschool Thinking Adventures
+[LBSTART]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Little Bear Toddler Discovery Adventures
+[LBT]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
; Lionheart
[Lionheart]
hook_peekmessage=true
+; Links Extreme
+[EXTREME]
+singlecpu=false
+
+; Lost Vikings 2
+[LOSTV95]
+fake_mode=320x240x16
+
+; Nightmare Creatures
+[NC]
+maxgameticks=30
+singlecpu=false
+
+; Moto Racer (software mode)
+[moto]
+maxgameticks=59
+
+; Madeline 1st Grade Math
+[madmath1]
+nonexclusive=true
+no_compat_warning=true
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+renderer=gdi
+hook=2
+win_version=nt4
+
+; Madeline 1st Grade Math: Progress Report
+[madpr]
+nonexclusive=true
+no_compat_warning=true
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+renderer=gdi
+hook=2
+win_version=nt4
+
+; Madeline 2nd Grade Math
+[madmath2]
+nonexclusive=true
+no_compat_warning=true
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+renderer=gdi
+hook=2
+win_version=nt4
+
; Majesty Gold
[Majesty]
minfps=-2
@@ -648,13 +1175,53 @@ nonexclusive=true
; Moorhuhn 2
[Moorhuhn2]
-releasealt=true
+fix_alt_key_stuck=true
+
+; Metal Knight
+[mk]
+maxgameticks=60
+limiter_type=4
; New Robinson
[ROBY]
adjmouse=true
hook_peekmessage=true
+; Neo Sonic Universe
+[nsu]
+fake_mode=320x240x32
+
+; Neo Sonic Universe - battle mode
+[nsu_battle]
+fake_mode=320x240x32
+
+; Nancy Drew (All games)
+[Game/3]
+checkfile=.\Nancy.cid
+limiter_type=1
+maxgameticks=120
+
+; NBA Full Court Press
+[NBA_FCP]
+fake_mode=640x480x8
+
+; Nox
+[NOX]
+checkfile=.\NOX.ICD
+renderer=direct3d9
+nonexclusive=false
+windowed=false
+maxgameticks=125
+
+; Nox Reloaded
+[NoxReloaded]
+maxgameticks=125
+
+; Nox GOG
+[Game/2]
+checkfile=.\nox.cfg
+maxgameticks=125
+
; Outlaws
[olwin]
noactivateapp=true
@@ -662,22 +1229,211 @@ maxgameticks=60
adjmouse=true
renderer=gdi
+; Pandora's Box Puzzle Game
+[Pandora]
+fixchilds=0
+
+; Paddle Bash Hotshot
+[SPAGHSPaddle]
+no_compat_warning=true
+
+; Pajama Sam's Games to Play on Any Day
+[PJGAMES]
+renderer=gdi
+
+; Pajama Sam
+[PajamaTAL]
+renderer=gdi
+
+; Pajama Sam: No Need to Hide When It's Dark Outside
+[PajamaNHD]
+renderer=gdi
+
+; Pajama Sam 3
+[Pajama3]
+renderer=gdi
+
+; Pajama Sam's One-Stop Fun Shop
+[SamsFunShop]
+renderer=gdi
+
+; Pajama Sam DON'T FEAR THE DARK
+[pjSam]
+renderer=gdi
+
+; Pajama Sam 3: You Are What You Eat From Your Head To Your Feet
+[UKpajamaEAT]
+renderer=gdi
+
; Pharaoh
[Pharaoh]
adjmouse=true
+; Putt-Putt Saves The Zoo
+[PUTTZOO]
+renderer=gdi
+hook=3
+
+; Putt-Putt's One-Stop Fun Shop
+[PuttsFunShop]
+renderer=gdi
+
+; Putt-Putt and Pep's Dog On A Stick
+[DOG]
+renderer=gdi
+
+; Putt-Putt Joins the Circus
+[puttcircus]
+renderer=gdi
+
+; Putt-Putt Enters The Race
+[UKPuttRace]
+renderer=gdi
+
+; Putt-Putt: Travels Through Time
+[PuttTTT]
+renderer=gdi
+
+; Putt-Putt and Pep's Balloon-o-Rama
+[Balloon]
+renderer=gdi
+
+; Putt-Putt Travels Through Time
+[PUTTPUTTTTT]
+renderer=gdi
+
+; Putt-Putt Joins the Circus
+[puttputtjtc]
+renderer=gdi
+
+; Pizza Syndicate
+[Pizza2]
+renderer=opengl
+
+; Pizza Syndicate - Mehr Biss (Mission CD)
+[Pizza_Mission]
+renderer=opengl
+
; Pax Imperia
[Pax Imperia]
nonexclusive=true
+; Panzer Dragoon
+[PANZERDG]
+singlecpu=false
+
+; Play with the Teletubbies
+[PlayWTT]
+hook=3
+
+; Populous - The Beginning
+[popTB]
+singlecpu=false
+
+; Rage of Mages
+[rom]
+maxgameticks=60
+limiter_type=4
+singlecpu=true
+
; Railroad Tycoon II
[RT2]
-adjmouse=true
+maxgameticks=60adjmouse=true
+
+; Reader Rabbit Thinking Ages 4-6 (US)
+[rrta32]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Reader Rabbit Reading Ages 4-6
+[rrirjw32]
+renderer=gdi
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Reader Rabbit Reading Ages 6-9
+[irj2w32]
+renderer=gdi
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; Real War
+[RealWar]
+maxgameticks=60
+limiter_type=3
+
+; Return to Krondor
+[RtK]
+fixchilds=3
+lock_mouse_top_left=true
+singlecpu=false
+limiter_type=2
+game_handles_close=true
+maxgameticks=59
+anti_aliased_fonts_min_size=99
+
+; Rent-A-Hero
+[Rent-A-Hero]
+singlecpu=false
; ROAD RASH
[RoadRash]
adjmouse=true
-fixchilds=1
+nonexclusive=true
+
+; Rising Lands (patched)
+[Rising]
+singlecpu=false
+
+; Robin Hood - The Legend of Sherwood (GOG)
+[Game/4]
+checkfile=.\Robin Hood.exe
+singlecpu=false
+fix_not_responding=true
+
+; Roland Garros 98 (software mode)
+[rg98]
+singlecpu=false
+
+; Robin Hood - The Legend of Sherwood (Steam)
+[_rh]
+singlecpu=false
+fix_not_responding=true
+
+; Robin Hood - The Legend of Sherwood
+[Robin Hood]
+singlecpu=false
+fix_not_responding=true
+
+; Scooby-Doo(TM), Case File #1 The Glowing Bug Man - NOT WORKING YET
+[Case File #1]
+windowed=true
+nonexclusive=true
+fake_mode=640x480x32
+
+; Seven Kingdoms II
+[7k2]
+fake_mode=352x240x32
+fix_not_responding=true
+
+; Swarog
+[Swarog]
+singlecpu=false
+maxfps=60
+maxgameticks=60
+minfps=-1
; Sim Copter
[SimCopter]
@@ -695,6 +1451,15 @@ adjmouse=true
maintas=false
boxing=false
+; Star Wars Rebellion
+[REBEXE]
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
; Star Wars: Galactic Battlegrounds
[battlegrounds]
nonexclusive=true
@@ -713,6 +1478,34 @@ game_handles_close=true
[Rangers]
hook_peekmessage=true
+; SPYFox: Hold the Mustard
+[mustard]
+renderer=gdi
+
+; SPY Fox: Some Assembly Required
+[Spyfox2]
+renderer=gdi
+
+; SPY Fox in Dry Cereal (2008)
+[SpyFox]
+renderer=gdi
+
+; SPY Fox in Dry Cereal (2001)
+[SPYFOXDC]
+renderer=gdi
+
+; SPY Fox : Some Assembly Required
+[SPYFOXSR]
+renderer=gdi
+
+; SPY Fox: Operation Ozone
+[spyozon]
+renderer=gdi
+
+; SPY Fox: Operation Ozone
+[spyfoxozu]
+renderer=gdi
+
; Stronghold Crusader HD
[Stronghold Crusader]
resolutions=2
@@ -734,35 +1527,95 @@ adjmouse=true
; Sim City 3000
[SC3]
minfps=-2
-
+maxgameticks=60
; Shadow Watch
[sw]
adjmouse=true
-
+maxgameticks=30
; Shadow Flare
[ShadowFlare]
nonexclusive=true
adjmouse=true
-maintas=false
-boxing=false
+
+; Squad Leader
+[SquadLeader]
+maxgameticks=30
+limiter_type=4
+
+; Soldiers At War
+[SAW_Game]
+maxgameticks=30
+limiter_type=4
+
+; The Curse Of Monkey Island
+[COMI]
+singlecpu=false
+
+; The Tone Rebellion
+[Float]
+hook_peekmessage=true
; Total Annihilation (Unofficial Beta Patch v3.9.02)
[TotalA]
-resolutions=2
+max_resolutions=32
lock_surfaces=true
singlecpu=false
; Total Annihilation Replay Viewer (Unofficial Beta Patch v3.9.02)
[Viewer]
-resolutions=2
+max_resolutions=32
lock_surfaces=true
singlecpu=false
+; Virtual Springfield
+[VIRTUAL]
+game_handles_close=true
+singlecpu=false
+
+; Total Annihilation: Kingdoms
+[Kingdoms]
+game_handles_close=true
+max_resolutions=32
+
+; The Missing on Lost Island
+[Island]
+lock_mouse_top_left=true
+fixchilds=3
+
+; The Neverhood
+[nhc]
+singlecpu=false
+
+; The X-Files DVD
+[XFiles]
+windowed=true
+fullscreen=true
+toggle_borderless=true
+
+; The Learning Company Launcher
+[TLCLauncher]
+tlc_hack=true
+adjmouse=false
+width=0
+height=0
+resizable=false
+maintas=false
+boxing=false
+
+; The Jungle Book Groove Party
+[Jungle_vr]
+fix_not_responding=true
+
; Three Kingdoms: Fate of the Dragon
[sanguo]
maxgameticks=60
noactivateapp=true
-limit_bltfast=true
+limiter_type=2
+
+; Thomas & Friends - The Great Festival Adventure
+[Thomas]
+no_compat_warning=true
+noactivateapp=true
; RollerCoaster Tycoon
[rct]
@@ -791,6 +1644,12 @@ boxing=false
[Tzar]
adjmouse=true
+; Unreal
+[Unreal]
+adjmouse=false
+lock_mouse_top_left=true
+center_cursor_fix=true
+
; Uprising
[uprising]
adjmouse=true
@@ -800,24 +1659,75 @@ adjmouse=true
renderer=opengl
adjmouse=true
+; Unreal
+[Unreal]
+noactivateapp=true
+
+; Vermeer
+[vermeer]
+adjmouse=true
+fake_mode=640x480x32
+
+; Virtua Fighter 2
+[VF2]
+fake_mode=640x480x8
+
+; Wall Street Trader 2000 - NOT WORKING YET
+[WSTrader]
+nonexclusive=false
+windowed=false
+
+; WarCraft 2000: Nuclear Epidemic
+[war2000]
+resolutions=2
+guard_lines=600
+minfps=-2
+
+; Warhammer 40000: Chaos Gate
+[WH40K]
+maxgameticks=250
+
+; Weird War
+[WeirdWar]
+singlecpu=false
+
; Wizardry 8
[Wiz8]
-fixmousehook=true
-noactivateapp=true
-releasealt=true
+sirtech_hack=true
+fix_alt_key_stuck=true
+
+; Worms 2
+[worms2]
+vhack=true
+flipclear=true
+game_handles_close=true
+center_cursor_fix=true
; Worms Armageddon
[WA]
-adjmouse=true
-width=0
-height=0
-resizable=false
+lock_mouse_top_left=true
+
+; Wheel Of Fortune
+[WHEEL]
+singlecpu=false
; War Wind
[WW]
minfps=-1
+; Jeff Wayne's 'The War Of The Worlds'
+[WoW]
+singlecpu=false
+minfps=-1
+
; Zeus and Poseidon
[Zeus]
adjmouse=true
+; Zork Nemesis
+[znemesis]
+fix_not_responding=true
+singlecpu=false
+maxgameticks=60
+limiter_type=4
+