-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"
|
RelativePath=".\filter\bilinear.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\filter\epx.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\filter\hq2x.cpp"
|
RelativePath=".\filter\hq2x.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -1375,6 +1375,10 @@
|
||||||
RelativePath=".\filter\bilinear.cpp"
|
RelativePath=".\filter\bilinear.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\filter\epx.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\filter\filter.h"
|
RelativePath=".\filter\filter.h"
|
||||||
>
|
>
|
||||||
|
|
|
@ -637,6 +637,8 @@
|
||||||
RelativePath=".\filter\2xsai.cpp"/>
|
RelativePath=".\filter\2xsai.cpp"/>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\filter\bilinear.cpp"/>
|
RelativePath=".\filter\bilinear.cpp"/>
|
||||||
|
<File
|
||||||
|
RelativePath=".\filter\epx.cpp"/>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\filter\filter.h"/>
|
RelativePath=".\filter\filter.h"/>
|
||||||
<File
|
<File
|
||||||
|
|
|
@ -1240,6 +1240,10 @@
|
||||||
RelativePath=".\filter\bilinear.cpp"
|
RelativePath=".\filter\bilinear.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\filter\epx.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\filter\filter.h"
|
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 RenderSuperEagle (SSurface Src, SSurface Dst);
|
||||||
void RenderScanline( SSurface Src, SSurface Dst);
|
void RenderScanline( SSurface Src, SSurface Dst);
|
||||||
void RenderBilinear( 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)
|
if (video.layout == 0)
|
||||||
{
|
{
|
||||||
defheight += video.screengap;
|
defheight += video.scaledscreengap();
|
||||||
|
|
||||||
// translate from scaling (screen resolution to 256x384 or 512x192)
|
// translate from scaling (screen resolution to 256x384 or 512x192)
|
||||||
switch (video.rotation)
|
switch (video.rotation)
|
||||||
|
@ -513,8 +513,8 @@ void UnscaleScreenCoords(s32& x, s32& y)
|
||||||
y = (y*defheight) / winheight / 2;
|
y = (y*defheight) / winheight / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
x = x/video.ratio();
|
x = video.dividebyratio(x);
|
||||||
y = y/video.ratio();
|
y = video.dividebyratio(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
// input x,y should be windows client-space coords already at 1x scaling.
|
// 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)
|
if (video.layout == 0)
|
||||||
{
|
{
|
||||||
int gapSize = video.screengap / video.ratio();
|
int gapSize = video.dividebyratio(video.scaledscreengap());
|
||||||
// first deal with rotation
|
// first deal with rotation
|
||||||
switch(video.rotation)
|
switch(video.rotation)
|
||||||
{
|
{
|
||||||
|
@ -2671,7 +2671,7 @@ void UpdateWndRects(HWND hwnd)
|
||||||
int wndWidth, wndHeight;
|
int wndWidth, wndHeight;
|
||||||
int defHeight = video.height;
|
int defHeight = video.height;
|
||||||
if(video.layout == 0)
|
if(video.layout == 0)
|
||||||
defHeight += video.screengap;
|
defHeight += video.scaledscreengap();
|
||||||
float ratio;
|
float ratio;
|
||||||
int oneScreenHeight, gapHeight;
|
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_SCANLINE, video.currentfilter == video.SCANLINE );
|
||||||
MainWindow->checkMenu(IDM_RENDER_BILINEAR, video.currentfilter == video.BILINEAR );
|
MainWindow->checkMenu(IDM_RENDER_BILINEAR, video.currentfilter == video.BILINEAR );
|
||||||
MainWindow->checkMenu(IDM_RENDER_NEAREST2X, video.currentfilter == video.NEAREST2X );
|
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 );
|
MainWindow->checkMenu(IDC_STATEREWINDING, staterewindingenabled == 1 );
|
||||||
|
|
||||||
|
@ -4256,6 +4258,21 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM
|
||||||
FilterUpdate(hwnd);
|
FilterUpdate(hwnd);
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case IDM_STATE_LOAD:
|
||||||
{
|
{
|
||||||
OPENFILENAME ofn;
|
OPENFILENAME ofn;
|
||||||
|
|
|
@ -181,6 +181,8 @@
|
||||||
#define IDM_RENDER_SCANLINE 556
|
#define IDM_RENDER_SCANLINE 556
|
||||||
#define IDM_RENDER_BILINEAR 557
|
#define IDM_RENDER_BILINEAR 557
|
||||||
#define IDM_RENDER_NEAREST2X 558
|
#define IDM_RENDER_NEAREST2X 558
|
||||||
|
#define IDM_RENDER_EPX 559
|
||||||
|
#define IDM_RENDER_EPX1POINT5 560
|
||||||
#define IDD_IO_REG 601
|
#define IDD_IO_REG 601
|
||||||
#define IDM_RECORD_MOVIE 602
|
#define IDM_RECORD_MOVIE 602
|
||||||
#define IDM_PLAY_MOVIE 603
|
#define IDM_PLAY_MOVIE 603
|
||||||
|
|
Binary file not shown.
|
@ -32,6 +32,10 @@ public:
|
||||||
HQ2XS,
|
HQ2XS,
|
||||||
LQ2X,
|
LQ2X,
|
||||||
LQ2XS,
|
LQ2XS,
|
||||||
|
EPX,
|
||||||
|
EPX1POINT5,
|
||||||
|
|
||||||
|
NUM_FILTERS,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +46,9 @@ public:
|
||||||
|
|
||||||
void setfilter(int filter) {
|
void setfilter(int filter) {
|
||||||
|
|
||||||
|
if(filter < 0 || filter >= NUM_FILTERS)
|
||||||
|
filter = NONE;
|
||||||
|
|
||||||
currentfilter = filter;
|
currentfilter = filter;
|
||||||
|
|
||||||
switch(filter) {
|
switch(filter) {
|
||||||
|
@ -50,9 +57,13 @@ public:
|
||||||
width = 256;
|
width = 256;
|
||||||
height = 384;
|
height = 384;
|
||||||
break;
|
break;
|
||||||
|
case EPX1POINT5:
|
||||||
|
width = 256*3/2;
|
||||||
|
height = 384*3/2;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
width = 512;
|
width = 256*2;
|
||||||
height = 768;
|
height = 384*2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,9 +85,9 @@ public:
|
||||||
src.Pitch = 512;
|
src.Pitch = 512;
|
||||||
src.Surface = (u8*)buffer;
|
src.Surface = (u8*)buffer;
|
||||||
|
|
||||||
dst.Height = 768;
|
dst.Height = height;
|
||||||
dst.Width = 512;
|
dst.Width = width;
|
||||||
dst.Pitch = 1024;
|
dst.Pitch = width*2;
|
||||||
dst.Surface = (u8*)filteredbuffer;
|
dst.Surface = (u8*)filteredbuffer;
|
||||||
|
|
||||||
switch(currentfilter)
|
switch(currentfilter)
|
||||||
|
@ -113,6 +124,12 @@ public:
|
||||||
case NEAREST2X:
|
case NEAREST2X:
|
||||||
RenderNearest2X(src,dst);
|
RenderNearest2X(src,dst);
|
||||||
break;
|
break;
|
||||||
|
case EPX:
|
||||||
|
RenderEPX(src,dst);
|
||||||
|
break;
|
||||||
|
case EPX1POINT5:
|
||||||
|
RenderEPX_1Point5x(src,dst);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,8 +137,8 @@ public:
|
||||||
return width*height;
|
return width*height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ratio() {
|
int dividebyratio(int x) {
|
||||||
return width / 256;
|
return x * 256 / width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rotatedwidth() {
|
int rotatedwidth() {
|
||||||
|
@ -159,11 +176,11 @@ public:
|
||||||
case 0:
|
case 0:
|
||||||
return width;
|
return width;
|
||||||
case 90:
|
case 90:
|
||||||
return height + ((layout == 0) ? screengap : 0);
|
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||||
case 180:
|
case 180:
|
||||||
return width;
|
return width;
|
||||||
case 270:
|
case 270:
|
||||||
return height + ((layout == 0) ? screengap : 0);
|
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -172,15 +189,19 @@ public:
|
||||||
int rotatedheightgap() {
|
int rotatedheightgap() {
|
||||||
switch(rotation) {
|
switch(rotation) {
|
||||||
case 0:
|
case 0:
|
||||||
return height + ((layout == 0) ? screengap : 0);
|
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||||
case 90:
|
case 90:
|
||||||
return width;
|
return width;
|
||||||
case 180:
|
case 180:
|
||||||
return height + ((layout == 0) ? screengap : 0);
|
return height + ((layout == 0) ? scaledscreengap() : 0);
|
||||||
case 270:
|
case 270:
|
||||||
return width;
|
return width;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int scaledscreengap() {
|
||||||
|
return screengap * height / 384;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue