diff --git a/desmume/src/windows/DeSmuME_2005.vcproj b/desmume/src/windows/DeSmuME_2005.vcproj
index 9013caf79..4b17c743f 100644
--- a/desmume/src/windows/DeSmuME_2005.vcproj
+++ b/desmume/src/windows/DeSmuME_2005.vcproj
@@ -914,6 +914,10 @@
RelativePath=".\filter\bilinear.cpp"
>
+
+
diff --git a/desmume/src/windows/DeSmuME_2008.vcproj b/desmume/src/windows/DeSmuME_2008.vcproj
index b313cc53a..cb9a4ee37 100644
--- a/desmume/src/windows/DeSmuME_2008.vcproj
+++ b/desmume/src/windows/DeSmuME_2008.vcproj
@@ -1375,6 +1375,10 @@
RelativePath=".\filter\bilinear.cpp"
>
+
+
diff --git a/desmume/src/windows/DeSmuME_Intel.icproj b/desmume/src/windows/DeSmuME_Intel.icproj
index cf8fd670d..b13907d6b 100644
--- a/desmume/src/windows/DeSmuME_Intel.icproj
+++ b/desmume/src/windows/DeSmuME_Intel.icproj
@@ -637,6 +637,8 @@
RelativePath=".\filter\2xsai.cpp"/>
+
+
+
diff --git a/desmume/src/windows/filter/epx.cpp b/desmume/src/windows/filter/epx.cpp
new file mode 100644
index 000000000..55d7dcb01
--- /dev/null
+++ b/desmume/src/windows/filter/epx.cpp
@@ -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(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(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
+ }
+}
+
diff --git a/desmume/src/windows/filter/filter.h b/desmume/src/windows/filter/filter.h
index 8cc9fbfc1..4de9664bd 100644
--- a/desmume/src/windows/filter/filter.h
+++ b/desmume/src/windows/filter/filter.h
@@ -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);
\ No newline at end of file
+void RenderBilinear( SSurface Src, SSurface Dst);
+void RenderEPX( SSurface Src, SSurface Dst);
+void RenderEPX_1Point5x( SSurface Src, SSurface Dst);
+
diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp
index 6748f2fdd..3b4c21815 100644
--- a/desmume/src/windows/main.cpp
+++ b/desmume/src/windows/main.cpp
@@ -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;
diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h
index d825b7273..00fa455a8 100644
--- a/desmume/src/windows/resource.h
+++ b/desmume/src/windows/resource.h
@@ -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
diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc
index 24503eabb..e2bca1879 100644
Binary files a/desmume/src/windows/resources.rc and b/desmume/src/windows/resources.rc differ
diff --git a/desmume/src/windows/video.h b/desmume/src/windows/video.h
index 4df15012c..27f0f902f 100644
--- a/desmume/src/windows/video.h
+++ b/desmume/src/windows/video.h
@@ -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;
+ }
};