-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:
nitsuja 2009-11-29 06:17:32 +00:00
parent a9cfa9ba4c
commit c5834ad616
10 changed files with 185 additions and 17 deletions

View File

@ -914,6 +914,10 @@
RelativePath=".\filter\bilinear.cpp"
>
</File>
<File
RelativePath=".\filter\epx.cpp"
>
</File>
<File
RelativePath=".\filter\hq2x.cpp"
>

View File

@ -1375,6 +1375,10 @@
RelativePath=".\filter\bilinear.cpp"
>
</File>
<File
RelativePath=".\filter\epx.cpp"
>
</File>
<File
RelativePath=".\filter\filter.h"
>

View File

@ -637,6 +637,8 @@
RelativePath=".\filter\2xsai.cpp"/>
<File
RelativePath=".\filter\bilinear.cpp"/>
<File
RelativePath=".\filter\epx.cpp"/>
<File
RelativePath=".\filter\filter.h"/>
<File

View File

@ -1240,6 +1240,10 @@
RelativePath=".\filter\bilinear.cpp"
>
</File>
<File
RelativePath=".\filter\epx.cpp"
>
</File>
<File
RelativePath=".\filter\filter.h"
>

View File

@ -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
}
}

View File

@ -33,4 +33,7 @@ void Render2xSaI (SSurface Src, SSurface Dst);
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 RenderBilinear( SSurface Src, SSurface Dst);
void RenderEPX( SSurface Src, SSurface Dst);
void RenderEPX_1Point5x( SSurface Src, SSurface Dst);

View File

@ -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;

View File

@ -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.

View File

@ -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;
}
};