-add EPX magnification filter
-add EPX1.5x filter (something I made up just now for 1.5x scaling) -fix screen gap size not scaling properly when using magnification filters
This commit is contained in:
parent
a9cfa9ba4c
commit
c5834ad616
|
@ -914,6 +914,10 @@
|
|||
RelativePath=".\filter\bilinear.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\epx.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\hq2x.cpp"
|
||||
>
|
||||
|
|
|
@ -1375,6 +1375,10 @@
|
|||
RelativePath=".\filter\bilinear.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\epx.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\filter.h"
|
||||
>
|
||||
|
|
|
@ -637,6 +637,8 @@
|
|||
RelativePath=".\filter\2xsai.cpp"/>
|
||||
<File
|
||||
RelativePath=".\filter\bilinear.cpp"/>
|
||||
<File
|
||||
RelativePath=".\filter\epx.cpp"/>
|
||||
<File
|
||||
RelativePath=".\filter\filter.h"/>
|
||||
<File
|
||||
|
|
|
@ -1240,6 +1240,10 @@
|
|||
RelativePath=".\filter\bilinear.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\epx.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\filter\filter.h"
|
||||
>
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/* Copyright (C) 2009 DeSmuME team
|
||||
|
||||
This file is part of DeSmuME
|
||||
|
||||
DeSmuME 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.
|
||||
|
||||
DeSmuME 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 DeSmuME; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "filter.h"
|
||||
#include "types.h"
|
||||
|
||||
void RenderEPX (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);
|
||||
if(L != R)
|
||||
{
|
||||
uint32 U = *(SrcLine-srcPitch);
|
||||
uint32 D = *(SrcLine+srcPitch);
|
||||
if(U != D)
|
||||
{
|
||||
*DstLine1++ = (U == L) ? U : C;
|
||||
*DstLine1++ = (R == U) ? R : C;
|
||||
*DstLine2++ = (L == D) ? L : C;
|
||||
*DstLine2++ = (D == R) ? D : C;
|
||||
SrcLine++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
*DstLine1++ = C;
|
||||
*DstLine1++ = C;
|
||||
*DstLine2++ = C;
|
||||
*DstLine2++ = C;
|
||||
SrcLine++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderEPX_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 j = 0, y = 0; j < srcHeight; j+=2, y+=3)
|
||||
{
|
||||
u32* srcPix = lpSrc + srcPitch*j;
|
||||
u32* dstPix = lpDst + dstPitch*y;
|
||||
|
||||
#define GET(dx,dy) *(srcPix+(dy)*srcPitch+(dx))
|
||||
#define SET(dx,dy,val) *(dstPix+(dy)*dstPitch+(dx)) = (val)
|
||||
#define BETTER(dx,dy,dx2,dy2) (GET(dx,dy) == GET(dx2,dy2) && GET(dx2,dy) != GET(dx,dy2))
|
||||
|
||||
for(int i = 0, x = 0; i < srcWidth; i+=2, x+=3, srcPix+=2, dstPix+=3)
|
||||
{
|
||||
SET(0,0,GET(0,0));
|
||||
SET(1,0,GET(1,0));
|
||||
SET(2,0,GET(BETTER(2,0,1,-1)? 2:1,0));
|
||||
SET(0,1,GET(0,1));
|
||||
SET(1,1,GET(1,1));
|
||||
SET(2,1,GET(BETTER(1,0, 2,1)? 2:1,1));
|
||||
SET(0,2,GET(BETTER(0,2,-1,1)?-1:0,1));
|
||||
SET(1,2,GET(BETTER(0,1, 1,2)? 0:1,1));
|
||||
SET(2,2,GET(BETTER(2,1, 1,2)? 2:1,1));
|
||||
}
|
||||
|
||||
#undef GET
|
||||
#undef SET
|
||||
#undef BETTER
|
||||
}
|
||||
}
|
||||
|
|
@ -34,3 +34,6 @@ void RenderSuper2xSaI (SSurface Src, SSurface Dst);
|
|||
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 RenderEPX_1Point5x( SSurface Src, SSurface Dst);
|
||||
|
||||
|
|
|
@ -481,7 +481,7 @@ void UnscaleScreenCoords(s32& x, s32& y)
|
|||
|
||||
if (video.layout == 0)
|
||||
{
|
||||
defheight += video.screengap;
|
||||
defheight += video.scaledscreengap();
|
||||
|
||||
// translate from scaling (screen resolution to 256x384 or 512x192)
|
||||
switch (video.rotation)
|
||||
|
@ -513,8 +513,8 @@ void UnscaleScreenCoords(s32& x, s32& y)
|
|||
y = (y*defheight) / winheight / 2;
|
||||
}
|
||||
|
||||
x = x/video.ratio();
|
||||
y = y/video.ratio();
|
||||
x = video.dividebyratio(x);
|
||||
y = video.dividebyratio(y);
|
||||
}
|
||||
|
||||
// input x,y should be windows client-space coords already at 1x scaling.
|
||||
|
@ -527,7 +527,7 @@ void ToDSScreenRelativeCoords(s32& x, s32& y, int whichScreen)
|
|||
|
||||
if (video.layout == 0)
|
||||
{
|
||||
int gapSize = video.screengap / video.ratio();
|
||||
int gapSize = video.dividebyratio(video.scaledscreengap());
|
||||
// first deal with rotation
|
||||
switch(video.rotation)
|
||||
{
|
||||
|
@ -2671,7 +2671,7 @@ void UpdateWndRects(HWND hwnd)
|
|||
int wndWidth, wndHeight;
|
||||
int defHeight = video.height;
|
||||
if(video.layout == 0)
|
||||
defHeight += video.screengap;
|
||||
defHeight += video.scaledscreengap();
|
||||
float ratio;
|
||||
int oneScreenHeight, gapHeight;
|
||||
|
||||
|
@ -3623,6 +3623,8 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
MainWindow->checkMenu(IDM_RENDER_SCANLINE, video.currentfilter == video.SCANLINE );
|
||||
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_EPX1POINT5, video.currentfilter == video.EPX1POINT5 );
|
||||
|
||||
MainWindow->checkMenu(IDC_STATEREWINDING, staterewindingenabled == 1 );
|
||||
|
||||
|
@ -4256,6 +4258,21 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
|||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_EPX:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.EPX);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
case IDM_RENDER_EPX1POINT5:
|
||||
{
|
||||
Lock lock (win_backbuffer_sync);
|
||||
video.setfilter(video.EPX1POINT5);
|
||||
FilterUpdate(hwnd);
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_STATE_LOAD:
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
|
|
@ -181,6 +181,8 @@
|
|||
#define IDM_RENDER_SCANLINE 556
|
||||
#define IDM_RENDER_BILINEAR 557
|
||||
#define IDM_RENDER_NEAREST2X 558
|
||||
#define IDM_RENDER_EPX 559
|
||||
#define IDM_RENDER_EPX1POINT5 560
|
||||
#define IDD_IO_REG 601
|
||||
#define IDM_RECORD_MOVIE 602
|
||||
#define IDM_PLAY_MOVIE 603
|
||||
|
|
Binary file not shown.
|
@ -32,6 +32,10 @@ public:
|
|||
HQ2XS,
|
||||
LQ2X,
|
||||
LQ2XS,
|
||||
EPX,
|
||||
EPX1POINT5,
|
||||
|
||||
NUM_FILTERS,
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,6 +46,9 @@ public:
|
|||
|
||||
void setfilter(int filter) {
|
||||
|
||||
if(filter < 0 || filter >= NUM_FILTERS)
|
||||
filter = NONE;
|
||||
|
||||
currentfilter = filter;
|
||||
|
||||
switch(filter) {
|
||||
|
@ -50,9 +57,13 @@ public:
|
|||
width = 256;
|
||||
height = 384;
|
||||
break;
|
||||
case EPX1POINT5:
|
||||
width = 256*3/2;
|
||||
height = 384*3/2;
|
||||
break;
|
||||
default:
|
||||
width = 512;
|
||||
height = 768;
|
||||
width = 256*2;
|
||||
height = 384*2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -74,9 +85,9 @@ public:
|
|||
src.Pitch = 512;
|
||||
src.Surface = (u8*)buffer;
|
||||
|
||||
dst.Height = 768;
|
||||
dst.Width = 512;
|
||||
dst.Pitch = 1024;
|
||||
dst.Height = height;
|
||||
dst.Width = width;
|
||||
dst.Pitch = width*2;
|
||||
dst.Surface = (u8*)filteredbuffer;
|
||||
|
||||
switch(currentfilter)
|
||||
|
@ -113,6 +124,12 @@ public:
|
|||
case NEAREST2X:
|
||||
RenderNearest2X(src,dst);
|
||||
break;
|
||||
case EPX:
|
||||
RenderEPX(src,dst);
|
||||
break;
|
||||
case EPX1POINT5:
|
||||
RenderEPX_1Point5x(src,dst);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,8 +137,8 @@ public:
|
|||
return width*height;
|
||||
}
|
||||
|
||||
int ratio() {
|
||||
return width / 256;
|
||||
int dividebyratio(int x) {
|
||||
return x * 256 / width;
|
||||
}
|
||||
|
||||
int rotatedwidth() {
|
||||
|
@ -159,11 +176,11 @@ public:
|
|||
case 0:
|
||||
return width;
|
||||
case 90:
|
||||
return height + ((layout == 0) ? screengap : 0);
|
||||
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||
case 180:
|
||||
return width;
|
||||
case 270:
|
||||
return height + ((layout == 0) ? screengap : 0);
|
||||
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -172,15 +189,19 @@ public:
|
|||
int rotatedheightgap() {
|
||||
switch(rotation) {
|
||||
case 0:
|
||||
return height + ((layout == 0) ? screengap : 0);
|
||||
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||
case 90:
|
||||
return width;
|
||||
case 180:
|
||||
return height + ((layout == 0) ? screengap : 0);
|
||||
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||
case 270:
|
||||
return width;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int scaledscreengap() {
|
||||
return screengap * height / 384;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue