From c5834ad6165a7bbc1696a32cce84b008222b87d5 Mon Sep 17 00:00:00 2001 From: nitsuja Date: Sun, 29 Nov 2009 06:17:32 +0000 Subject: [PATCH] -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 --- desmume/src/windows/DeSmuME_2005.vcproj | 4 + desmume/src/windows/DeSmuME_2008.vcproj | 4 + desmume/src/windows/DeSmuME_Intel.icproj | 2 + desmume/src/windows/DeSmuME_Intel.vcproj | 4 + desmume/src/windows/filter/epx.cpp | 111 +++++++++++++++++++++++ desmume/src/windows/filter/filter.h | 5 +- desmume/src/windows/main.cpp | 27 +++++- desmume/src/windows/resource.h | 2 + desmume/src/windows/resources.rc | Bin 636306 -> 636906 bytes desmume/src/windows/video.h | 43 ++++++--- 10 files changed, 185 insertions(+), 17 deletions(-) create mode 100644 desmume/src/windows/filter/epx.cpp 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 24503eabb6d9f9d4e5bfd59507949458d023af9b..e2bca18799dc370148a0c7421dd981930378844f 100644 GIT binary patch delta 264 zcmbRATJ6<)wT2eP7N#xC0paSt42cZs40#Nh3~4}|4CIvn>3pDw0)rcnl>_9bG89dA zG!C5ZAjZzKeMdMm6WjC$sZ27gt_%ST5tBEHnNL@cU>9Qsa;FETGa2)P#ew<_8T1%T z86u`PsvGABs@ 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; + } };