add more 1.5x render filters, fix the EPX 1.5x filter, fix loading of frameskip=0 setting
This commit is contained in:
parent
04e3d1dafd
commit
c9d1c8e467
|
@ -19,7 +19,10 @@
|
|||
|
||||
#include "filter.h"
|
||||
#include "types.h"
|
||||
#include "interp.h"
|
||||
|
||||
// transforms each 1 pixel into a 2x2 block of output pixels
|
||||
// where each corner is selected based on equivalence of neighboring pixels
|
||||
void RenderEPX (SSurface Src, SSurface Dst)
|
||||
{
|
||||
uint32 *lpSrc;
|
||||
|
@ -66,7 +69,203 @@ void RenderEPX (SSurface Src, SSurface Dst)
|
|||
}
|
||||
}
|
||||
|
||||
// transforms each 2x2 block of pixels into a 3x3 block of output pixels
|
||||
// where each pixel is selected based on equivalence of neighboring pixels
|
||||
void RenderEPX_1Point5x (SSurface Src, SSurface Dst)
|
||||
{
|
||||
u32 *lpSrc;
|
||||
|
||||
u32 srcHeight = Src.Height;
|
||||
u32 srcWidth = Src.Width;
|
||||
u32 dstHeight = Dst.Height;
|
||||
u32 dstWidth = Dst.Width;
|
||||
|
||||
const unsigned int srcPitch = Src.Pitch >> 1;
|
||||
lpSrc = reinterpret_cast<u32 *>(Src.Surface);
|
||||
|
||||
const unsigned int dstPitch = Dst.Pitch >> 1;
|
||||
u32 *lpDst = (u32*)Dst.Surface;
|
||||
|
||||
for(int yi=0, yo=0; yi < srcHeight; yi+=2, yo+=3)
|
||||
{
|
||||
u32* SrcLine = lpSrc + srcPitch*yi;
|
||||
u32* DstLine1 = lpDst + dstPitch*(yo);
|
||||
u32* DstLine2 = lpDst + dstPitch*(yo+1);
|
||||
u32* DstLine3 = lpDst + dstPitch*(yo+2);
|
||||
for(int xi=0; xi < srcWidth; xi+=2)
|
||||
{
|
||||
u32 s10 = *(SrcLine-srcPitch), s20 = *(SrcLine-srcPitch+1), s30 = *(SrcLine-srcPitch+2);
|
||||
u32 s01 = *(SrcLine-1), s11 = *(SrcLine), s21 = *(SrcLine+1), s31 = *(SrcLine+2);
|
||||
u32 s02 = *(SrcLine+srcPitch-1), s12 = *(SrcLine+srcPitch), s22 = *(SrcLine+srcPitch+1), s32 = *(SrcLine+srcPitch+2);
|
||||
u32 s03 = *(SrcLine+2*srcPitch-1), s13 = *(SrcLine+2*srcPitch), s23 = *(SrcLine+2*srcPitch+1), s33 = *(SrcLine+2*srcPitch+2);
|
||||
*DstLine1++ = s01==s10 && s10!=s21 && s01!=s12
|
||||
? s01:s11;
|
||||
*DstLine1++ = s10==s21 && s10!=s01 && s21!=s12
|
||||
? s21:s11;
|
||||
*DstLine1++ = (s11==s20 && s20!=s31 && s11!=s22 && s21!=s30)
|
||||
|| (s20==s31 && s20!=s11 && s31!=s22 && s21!=s10) ? s20:s21;
|
||||
*DstLine2++ = s01==s12 && s01!=s10 && s12!=s21
|
||||
? s01:s11;
|
||||
*DstLine2++ = s12==s21 && s01!=s12 && s10!=s21
|
||||
? s21:s11;
|
||||
*DstLine2++ = (s11==s22 && s11!=s20 && s22!=s31 && s21!=s32)
|
||||
|| (s22==s31 && s11!=s22 && s20!=s31 && s21!=s12) ? s22:s21;
|
||||
*DstLine3++ = (s02==s11 && s11!=s22 && s02!=s13 && s12!=s03)
|
||||
|| (s02==s13 && s02!=s11 && s13!=s22 && s12!=s01) ? s02:s12;
|
||||
*DstLine3++ = (s11==s22 && s11!=s02 && s22!=s13 && s12!=s23)
|
||||
|| (s13==s22 && s02!=s13 && s11!=s22 && s12!=s21) ? s22:s12;
|
||||
*DstLine3++ = s22;
|
||||
SrcLine+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 min(u32 a, u32 b) { return (a < b) ? a : b; }
|
||||
static u32 min3(u32 a, u32 b, u32 c) { return min(a,min(b,c)); }
|
||||
static u32 dist(u32 a, u32 b)
|
||||
{
|
||||
return ABS( (a & 0x0000FF) - (b & 0x0000FF))*2
|
||||
+ ABS(((a & 0x00FF00)>>8) - ((b & 0x00FF00)>>8))*3
|
||||
+ ABS(((a & 0xFF0000)>>16) - ((b & 0xFF0000)>>16))*3;
|
||||
}
|
||||
// note: we only use mix to make the arbitrary choice between two almost-equal colors.
|
||||
// this filter doesn't really do much interpolating or have the appearance of doing any.
|
||||
#define mix interp_32_11
|
||||
|
||||
// transforms each 1 pixel into a 2x2 block of output pixels
|
||||
// where each corner is selected based on relative equivalence of neighboring pixels
|
||||
void RenderEPXPlus (SSurface Src, SSurface Dst)
|
||||
{
|
||||
uint32 *lpSrc;
|
||||
|
||||
const uint32 srcHeight = Src.Height;
|
||||
const uint32 srcWidth = Src.Width;
|
||||
|
||||
const unsigned int srcPitch = Src.Pitch >> 1;
|
||||
lpSrc = reinterpret_cast<uint32 *>(Src.Surface);
|
||||
|
||||
const unsigned int dstPitch = Dst.Pitch >> 1;
|
||||
uint32 *lpDst = (uint32*)Dst.Surface;
|
||||
|
||||
for(int j = 0; j < srcHeight; j++)
|
||||
{
|
||||
uint32* SrcLine = lpSrc + srcPitch*j;
|
||||
uint32* DstLine1 = lpDst + dstPitch*(j*2);
|
||||
uint32* DstLine2 = lpDst + dstPitch*(j*2+1);
|
||||
for(int i = 0; i < srcWidth; i++)
|
||||
{
|
||||
uint32 L = *(SrcLine-1);
|
||||
uint32 C = *(SrcLine);
|
||||
uint32 R = *(SrcLine+1);
|
||||
uint32 U = *(SrcLine-srcPitch);
|
||||
uint32 D = *(SrcLine+srcPitch);
|
||||
*DstLine1++ = dist(L,U) < min(dist(L,D),dist(R,U)) ? mix(L,U) : C;
|
||||
*DstLine1++ = dist(R,U) < min(dist(L,U),dist(R,D)) ? mix(R,U) : C;
|
||||
*DstLine2++ = dist(L,D) < min(dist(L,U),dist(R,D)) ? mix(L,D) : C;
|
||||
*DstLine2++ = dist(R,D) < min(dist(L,D),dist(R,U)) ? mix(R,D) : C;
|
||||
SrcLine++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transforms each 2x2 block of pixels into a 3x3 block of output pixels
|
||||
// where each pixel is selected based on relative equivalence of neighboring pixels
|
||||
void RenderEPXPlus_1Point5x (SSurface Src, SSurface Dst)
|
||||
{
|
||||
u32 *lpSrc;
|
||||
|
||||
u32 srcHeight = Src.Height;
|
||||
u32 srcWidth = Src.Width;
|
||||
u32 dstHeight = Dst.Height;
|
||||
u32 dstWidth = Dst.Width;
|
||||
|
||||
const unsigned int srcPitch = Src.Pitch >> 1;
|
||||
lpSrc = reinterpret_cast<u32 *>(Src.Surface);
|
||||
|
||||
const unsigned int dstPitch = Dst.Pitch >> 1;
|
||||
u32 *lpDst = (u32*)Dst.Surface;
|
||||
|
||||
for(int yi=0, yo=0; yi < srcHeight; yi+=2, yo+=3)
|
||||
{
|
||||
u32* SrcLine = lpSrc + srcPitch*yi;
|
||||
u32* DstLine1 = lpDst + dstPitch*(yo);
|
||||
u32* DstLine2 = lpDst + dstPitch*(yo+1);
|
||||
u32* DstLine3 = lpDst + dstPitch*(yo+2);
|
||||
for(int xi=0; xi < srcWidth; xi+=2)
|
||||
{
|
||||
u32 s10 = *(SrcLine-srcPitch), s20 = *(SrcLine-srcPitch+1), s30 = *(SrcLine-srcPitch+2);
|
||||
u32 s01 = *(SrcLine-1), s11 = *(SrcLine), s21 = *(SrcLine+1), s31 = *(SrcLine+2);
|
||||
u32 s02 = *(SrcLine+srcPitch-1), s12 = *(SrcLine+srcPitch), s22 = *(SrcLine+srcPitch+1), s32 = *(SrcLine+srcPitch+2);
|
||||
u32 s03 = *(SrcLine+2*srcPitch-1), s13 = *(SrcLine+2*srcPitch), s23 = *(SrcLine+2*srcPitch+1), s33 = *(SrcLine+2*srcPitch+2);
|
||||
*DstLine1++ = dist(s01,s10) < min( dist(s10,s21),dist(s01,s12))
|
||||
? mix(s01,s10):s11;
|
||||
*DstLine1++ = dist(s10,s21) < min( dist(s10,s01),dist(s21,s12))
|
||||
? mix(s10,s21):s11;
|
||||
*DstLine1++ = dist(s11,s20) < min3(dist(s20,s31),dist(s11,s22),dist(s21,s30)) ? mix(s11,s20):
|
||||
dist(s20,s31) < min3(dist(s20,s11),dist(s31,s22),dist(s21,s10)) ? mix(s20,s31):s21;
|
||||
*DstLine2++ = dist(s01,s12) < min( dist(s01,s10),dist(s12,s21))
|
||||
? mix(s01,s12):s11;
|
||||
*DstLine2++ = dist(s12,s21) < min( dist(s01,s12),dist(s10,s21))
|
||||
? mix(s12,s21):s11;
|
||||
*DstLine2++ = dist(s11,s22) < min3(dist(s11,s20),dist(s22,s31),dist(s21,s32)) ? mix(s11,s22):
|
||||
dist(s22,s31) < min3(dist(s11,s22),dist(s20,s31),dist(s21,s12)) ? mix(s22,s31):s21;
|
||||
*DstLine3++ = dist(s02,s11) < min3(dist(s11,s22),dist(s02,s13),dist(s12,s03)) ? mix(s02,s11):
|
||||
dist(s02,s13) < min3(dist(s02,s11),dist(s13,s22),dist(s12,s01)) ? mix(s02,s13):s12;
|
||||
*DstLine3++ = dist(s11,s22) < min3(dist(s11,s02),dist(s22,s13),dist(s12,s23)) ? mix(s11,s22):
|
||||
dist(s13,s22) < min3(dist(s02,s13),dist(s11,s22),dist(s12,s21)) ? mix(s13,s22):s12;
|
||||
*DstLine3++ = s22;
|
||||
SrcLine+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// transforms each 2x2 block of pixels into 3x3 output which is
|
||||
// a 2x2 block that has 1 block of padding on the right and bottom sides
|
||||
// which are selected stupidly from neighboring pixels in the original 2x2 block
|
||||
void RenderNearest_1Point5x (SSurface Src, SSurface Dst)
|
||||
{
|
||||
uint32 *lpSrc;
|
||||
|
||||
uint32 srcHeight = Src.Height;
|
||||
uint32 srcWidth = Src.Width;
|
||||
uint32 dstHeight = Dst.Height;
|
||||
uint32 dstWidth = Dst.Width;
|
||||
|
||||
const unsigned int srcPitch = Src.Pitch >> 1;
|
||||
lpSrc = reinterpret_cast<uint32 *>(Src.Surface);
|
||||
|
||||
const unsigned int dstPitch = Dst.Pitch >> 1;
|
||||
uint32 *lpDst = (uint32*)Dst.Surface;
|
||||
|
||||
for(int yi = 0, yo = 0; yi < srcHeight; yi+=2, yo+=3)
|
||||
{
|
||||
u32* srcPix1 = lpSrc + srcPitch*(yi);
|
||||
u32* srcPix2 = lpSrc + srcPitch*(yi+1);
|
||||
u32* dstPix1 = lpDst + dstPitch*(yo);
|
||||
u32* dstPix2 = lpDst + dstPitch*(yo+1);
|
||||
u32* dstPix3 = lpDst + dstPitch*(yo+2);
|
||||
|
||||
for(int xi = 0; xi < srcWidth; xi+=2)
|
||||
{
|
||||
*dstPix1++ = *srcPix1++;
|
||||
*dstPix1++ = *srcPix1;
|
||||
*dstPix1++ = *srcPix1++;
|
||||
*dstPix2++ = *srcPix2;
|
||||
*dstPix3++ = *srcPix2++;
|
||||
*dstPix2++ = *srcPix2;
|
||||
*dstPix3++ = *srcPix2;
|
||||
*dstPix2++ = *srcPix2;
|
||||
*dstPix3++ = *srcPix2++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// transforms each 2x2 block of pixels into 3x3 output which is
|
||||
// a 2x2 block that has 1 block of padding on the right and bottom sides
|
||||
// which are selected from neighboring pixels depending on matching diagonals
|
||||
void RenderNearestPlus_1Point5x (SSurface Src, SSurface Dst)
|
||||
{
|
||||
uint32 *lpSrc;
|
||||
|
||||
|
@ -108,4 +307,3 @@ void RenderEPX_1Point5x (SSurface Src, SSurface Dst)
|
|||
#undef BETTER
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,5 +35,8 @@ void RenderSuperEagle (SSurface Src, SSurface Dst);
|
|||
void RenderScanline( SSurface Src, SSurface Dst);
|
||||
void RenderBilinear( SSurface Src, SSurface Dst);
|
||||
void RenderEPX( SSurface Src, SSurface Dst);
|
||||
void RenderEPXPlus( SSurface Src, SSurface Dst);
|
||||
void RenderEPX_1Point5x( SSurface Src, SSurface Dst);
|
||||
|
||||
void RenderEPXPlus_1Point5x( SSurface Src, SSurface Dst);
|
||||
void RenderNearest_1Point5x( SSurface Src, SSurface Dst);
|
||||
void RenderNearestPlus_1Point5x( SSurface Src, SSurface Dst);
|
||||
|
|
|
@ -329,8 +329,6 @@ static void hq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1,
|
|||
int diffBright = ((maxBright - minBright) * 7) >> 4;
|
||||
if(diffBright > 7)
|
||||
{
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
const int centerBright = brightArray[4];
|
||||
if(ABS(brightArray[0] - centerBright) > diffBright)
|
||||
mask |= 1 << 0;
|
||||
|
@ -461,8 +459,6 @@ static void hq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1,
|
|||
int diffBright = ((maxBright - minBright) * 7) >> 4;
|
||||
if(diffBright > 7)
|
||||
{
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
const int centerBright = brightArray[4];
|
||||
if(ABS(brightArray[0] - centerBright) > diffBright)
|
||||
mask |= 1 << 0;
|
||||
|
|
|
@ -277,7 +277,8 @@ static int interp_32_diff(u32 p1, u32 p2)
|
|||
|
||||
|
||||
#define INTERP_LIMIT2 (96000)
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
//#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
static __forceinline unsigned int ABS(int x) { return (x+(x>>31))^(x>>31); } // faster
|
||||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||||
#define MIN(x,y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
|
|
|
@ -193,8 +193,6 @@ static void lq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1,
|
|||
int diffBright = ((maxBright - minBright) * 7) >> 4;
|
||||
if(diffBright > 7)
|
||||
{
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
const int centerBright = brightArray[4];
|
||||
if(ABS(brightArray[0] - centerBright) > diffBright)
|
||||
mask |= 1 << 0;
|
||||
|
@ -434,8 +432,6 @@ static void lq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1,
|
|||
int diffBright = ((maxBright - minBright) * 7) >> 4;
|
||||
if(diffBright > 7)
|
||||
{
|
||||
#define ABS(x) ((x) < 0 ? -(x) : (x))
|
||||
|
||||
const int centerBright = brightArray[4];
|
||||
if(ABS(brightArray[0] - centerBright) > diffBright)
|
||||
mask |= 1 << 0;
|
||||
|
|
|
@ -2442,7 +2442,7 @@ int _main()
|
|||
frameskiprate=9;
|
||||
else
|
||||
frameskiprate=atoi(text+4);
|
||||
if(frameskiprate < 1)
|
||||
if(frameskiprate < 0)
|
||||
frameskiprate = 9;
|
||||
}
|
||||
else
|
||||
|
@ -3689,7 +3689,11 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
MainWindow->checkMenu(IDM_RENDER_BILINEAR, video.currentfilter == video.BILINEAR );
|
||||
MainWindow->checkMenu(IDM_RENDER_NEAREST2X, video.currentfilter == video.NEAREST2X );
|
||||
MainWindow->checkMenu(IDM_RENDER_EPX, video.currentfilter == video.EPX );
|
||||
MainWindow->checkMenu(IDM_RENDER_EPXPLUS, video.currentfilter == video.EPXPLUS );
|
||||
MainWindow->checkMenu(IDM_RENDER_EPX1POINT5, video.currentfilter == video.EPX1POINT5 );
|
||||
MainWindow->checkMenu(IDM_RENDER_EPXPLUS1POINT5, video.currentfilter == video.EPXPLUS1POINT5 );
|
||||
MainWindow->checkMenu(IDM_RENDER_NEAREST1POINT5, video.currentfilter == video.NEAREST1POINT5 );
|
||||
MainWindow->checkMenu(IDM_RENDER_NEARESTPLUS1POINT5, video.currentfilter == video.NEARESTPLUS1POINT5 );
|
||||
|
||||
MainWindow->checkMenu(IDC_STATEREWINDING, staterewindingenabled == 1 );
|
||||
|
||||
|
@ -4333,6 +4337,13 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_EPXPLUS:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.EPXPLUS);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_EPX1POINT5:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
|
@ -4340,6 +4351,27 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_EPXPLUS1POINT5:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.EPXPLUS1POINT5);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_NEAREST1POINT5:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.NEAREST1POINT5);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_NEARESTPLUS1POINT5:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.NEARESTPLUS1POINT5);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_STATE_LOAD:
|
||||
{
|
||||
|
|
|
@ -176,7 +176,11 @@
|
|||
#define IDM_RENDER_BILINEAR 557
|
||||
#define IDM_RENDER_NEAREST2X 558
|
||||
#define IDM_RENDER_EPX 559
|
||||
#define IDM_RENDER_EPX1POINT5 560
|
||||
#define IDM_RENDER_EPXPLUS 560
|
||||
#define IDM_RENDER_EPX1POINT5 561
|
||||
#define IDM_RENDER_EPXPLUS1POINT5 562
|
||||
#define IDM_RENDER_NEAREST1POINT5 563
|
||||
#define IDM_RENDER_NEARESTPLUS1POINT5 564
|
||||
#define IDD_IO_REG 601
|
||||
#define IDM_RECORD_MOVIE 602
|
||||
#define IDM_PLAY_MOVIE 603
|
||||
|
|
Binary file not shown.
|
@ -33,7 +33,11 @@ public:
|
|||
LQ2X,
|
||||
LQ2XS,
|
||||
EPX,
|
||||
NEARESTPLUS1POINT5,
|
||||
NEAREST1POINT5,
|
||||
EPXPLUS,
|
||||
EPX1POINT5,
|
||||
EPXPLUS1POINT5,
|
||||
|
||||
NUM_FILTERS,
|
||||
};
|
||||
|
@ -58,6 +62,9 @@ public:
|
|||
height = 384;
|
||||
break;
|
||||
case EPX1POINT5:
|
||||
case EPXPLUS1POINT5:
|
||||
case NEAREST1POINT5:
|
||||
case NEARESTPLUS1POINT5:
|
||||
width = 256*3/2;
|
||||
height = 384*3/2;
|
||||
break;
|
||||
|
@ -127,9 +134,21 @@ public:
|
|||
case EPX:
|
||||
RenderEPX(src,dst);
|
||||
break;
|
||||
case EPXPLUS:
|
||||
RenderEPXPlus(src,dst);
|
||||
break;
|
||||
case EPX1POINT5:
|
||||
RenderEPX_1Point5x(src,dst);
|
||||
break;
|
||||
case EPXPLUS1POINT5:
|
||||
RenderEPXPlus_1Point5x(src,dst);
|
||||
break;
|
||||
case NEAREST1POINT5:
|
||||
RenderNearest_1Point5x(src,dst);
|
||||
break;
|
||||
case NEARESTPLUS1POINT5:
|
||||
RenderNearestPlus_1Point5x(src,dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue