From a093258ec27f2856c5ca930d670ab3334f2a54fa Mon Sep 17 00:00:00 2001 From: zeromus Date: Fri, 24 May 2013 08:47:31 +0000 Subject: [PATCH] win32-add Pad To Integer view menu option, for help when maximizing or fullscreening to keep from distorting the image non-integerly --- desmume/src/windows/main.cpp | 119 +++++++++++++++++++++++++------ desmume/src/windows/resource.h | 3 +- desmume/src/windows/resources.rc | Bin 230230 -> 230238 bytes 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/desmume/src/windows/main.cpp b/desmume/src/windows/main.cpp index 9f88996c5..70b0b411a 100644 --- a/desmume/src/windows/main.cpp +++ b/desmume/src/windows/main.cpp @@ -500,6 +500,7 @@ bool romloaded = false; void SetScreenGap(int gap); bool ForceRatio = true; +bool PadToInteger = false; bool SeparationBorderDrag = true; int ScreenGapColor = 0xFFFFFF; float DefaultWidth; @@ -1093,6 +1094,65 @@ template static void doRotate(void* dst) } } +struct DisplayLayoutInfo +{ + int vx,vy,vw,vh; + float widthScale, heightScale; + int bufferWidth, bufferHeight; +}; + +//performs aspect ratio letterboxing correction and integer clamping +DisplayLayoutInfo CalculateDisplayLayout(RECT rcClient, bool maintainAspect, bool maintainInteger, int targetWidth, int targetHeight) +{ + DisplayLayoutInfo ret; + + //do maths on the viewport and the native resolution and the user settings to get a display rectangle + SIZE sz = { rcClient.right - rcClient.left, rcClient.bottom - rcClient.top }; + + float widthScale = (float)sz.cx / targetWidth; + float heightScale = (float)sz.cy / targetHeight; + if(maintainAspect) + { + if(widthScale > heightScale) widthScale = heightScale; + if(heightScale > widthScale) heightScale = widthScale; + } + if(maintainInteger) + { + widthScale = floorf(widthScale); + heightScale = floorf(heightScale); + } + ret.vw = (int)(widthScale * targetWidth); + ret.vh = (int)(heightScale * targetHeight); + ret.vx = (sz.cx - ret.vw)/2; + ret.vy = (sz.cy - ret.vh)/2; + ret.widthScale = widthScale; + ret.heightScale = heightScale; + ret.bufferWidth = sz.cx; + ret.bufferHeight = sz.cy; + + return ret; +} + +//reformulates CalculateDisplayLayout() into a format more convenient for this purpose +RECT CalculateDisplayLayoutWrapper(RECT rcClient, int targetWidth, int targetHeight, int tbHeight, bool maximized) +{ + bool maintainInteger = !!PadToInteger; + bool maintainAspect = !!ForceRatio; + + if(maintainInteger) maintainAspect = true; + + //nothing to do here if maintain aspect isnt chosen + if(!maintainAspect) return rcClient; + + RECT rc = { rcClient.left, rcClient.top + tbHeight, rcClient.right, rcClient.bottom }; + DisplayLayoutInfo dli = CalculateDisplayLayout(rc, maintainAspect, maintainInteger, targetWidth, targetHeight); + rc.left = rcClient.left + dli.vx; + rc.top = rcClient.top + dli.vy; + rc.right = rc.left + dli.vw; + rc.bottom = rc.top + dli.vh + tbHeight; + return rc; +} + void UpdateWndRects(HWND hwnd) { POINT ptClient; @@ -1112,12 +1172,13 @@ void UpdateWndRects(HWND hwnd) if(maximized) rc = FullScreenRect; - + tbheight = MainWindowToolbar->GetHeight(); - - - if (video.layout == 1) + + if (video.layout == 1) //horizontal { + rc = CalculateDisplayLayoutWrapper(rc, 512, 192, tbheight, maximized); + wndWidth = (rc.bottom - rc.top) - tbheight; wndHeight = (rc.right - rc.left); @@ -1150,8 +1211,9 @@ void UpdateWndRects(HWND hwnd) SubScreenRect.bottom = ptClient.y; } else - if (video.layout == 2) + if (video.layout == 2) //one screen { + rc = CalculateDisplayLayoutWrapper(rc, 256, 192, tbheight, maximized); wndWidth = (rc.bottom - rc.top) - tbheight; wndHeight = (rc.right - rc.left); @@ -1172,8 +1234,18 @@ void UpdateWndRects(HWND hwnd) MainScreenRect.bottom = ptClient.y; } else - if (video.layout == 0) + if (video.layout == 0) //vertical { + //apply logic to correct things if forced integer is selected + if((video.rotation == 90) || (video.rotation == 270)) + { + rc = CalculateDisplayLayoutWrapper(rc, 384 + video.screengap, 256, tbheight, maximized); + } + else + { + rc = CalculateDisplayLayoutWrapper(rc, 256, 384 + video.screengap, tbheight, maximized); + } + if((video.rotation == 90) || (video.rotation == 270)) { wndWidth = (rc.bottom - rc.top) - tbheight; @@ -1186,6 +1258,7 @@ void UpdateWndRects(HWND hwnd) } ratio = ((float)wndHeight / (float)defHeight); + oneScreenHeight = (int)((video.height/2) * ratio); gapHeight = (wndHeight - (oneScreenHeight * 2)); @@ -1226,6 +1299,8 @@ void UpdateWndRects(HWND hwnd) } else { + + // Main screen ptClient.x = rc.left; ptClient.y = rc.top; @@ -2381,14 +2456,16 @@ static BOOL LoadROM(const char * filename, const char * physicalName, const char Pause(); //if (strcmp(filename,"")!=0) INFO("Attempting to load ROM: %s\n",filename); + //since loading a rom can take a long time and happens in the main thread, forcibly display a message here so users dont think it froze video.clear(); osd->clear(); - osd->addFixed(90, 80, "Loading ROM."); - osd->addFixed(90, 100, "Please, wait..."); - osd->addFixed(90, 192 + 80, "Loading ROM."); - osd->addFixed(90, 192 + 100, "Please, wait..."); + osd->addFixed(70, 80, "Loading ROM."); + osd->addFixed(70, 100, "Please wait..."); + osd->addFixed(70, 192 + 80, "Loading ROM."); + osd->addFixed(70, 192 + 100, "Please wait..."); bRefreshDisplay = true; Display(); + if (NDS_LoadROM(filename, physicalName, logicalName) > 0) { INFO("Loading %s was successful\n",logicalName); @@ -2938,6 +3015,7 @@ int _main() video.rotation = GetPrivateProfileInt("Video","Window Rotate", 0, IniName); video.rotation_userset = GetPrivateProfileInt("Video","Window Rotate Set", video.rotation, IniName); ForceRatio = GetPrivateProfileBool("Video","Window Force Ratio", 1, IniName); + PadToInteger = GetPrivateProfileBool("Video","Window Pad To Integer", 0, IniName); WndX = GetPrivateProfileInt("Video","WindowPosX", CW_USEDEFAULT, IniName); WndY = GetPrivateProfileInt("Video","WindowPosY", CW_USEDEFAULT, IniName); if(WndX < -10000) WndX = CW_USEDEFAULT; // fix for missing window problem @@ -4397,6 +4475,7 @@ LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM MainWindow->checkMenu(ID_LCDS_SUBGPU, video.swap == 3); //Force Maintain Ratio MainWindow->checkMenu(IDC_FORCERATIO, ((ForceRatio))); + MainWindow->checkMenu(IDC_VIEW_PADTOINTEGER, ((PadToInteger))); //Screen rotation MainWindow->checkMenu(IDC_ROTATE0, ((video.rotation_userset==0))); MainWindow->checkMenu(IDC_ROTATE90, ((video.rotation_userset==90))); @@ -5941,18 +6020,18 @@ DOKEYDOWN: WritePrivateProfileInt("Video","Window Size",windowSize,IniName); break; - case IDC_FORCERATIO: - if (ForceRatio) { - ForceRatio = FALSE; - WritePrivateProfileInt("Video","Window Force Ratio",0,IniName); - } - else { - ForceRatio = TRUE; - FixAspectRatio(); - WritePrivateProfileInt("Video","Window Force Ratio",1,IniName); - } + case IDC_VIEW_PADTOINTEGER: + PadToInteger = (!PadToInteger)?TRUE:FALSE; + WritePrivateProfileInt("Video","Window Pad To Integer",PadToInteger,IniName); + UpdateWndRects(hwnd); break; + case IDC_FORCERATIO: + ForceRatio = (!ForceRatio)?TRUE:FALSE; + if(ForceRatio) + FixAspectRatio(); + WritePrivateProfileInt("Video","Window Force Ratio",ForceRatio,IniName); + break; case IDM_DEFSIZE: { diff --git a/desmume/src/windows/resource.h b/desmume/src/windows/resource.h index 7fb253a63..f8bd05273 100644 --- a/desmume/src/windows/resource.h +++ b/desmume/src/windows/resource.h @@ -914,6 +914,7 @@ #define ID_DISPLAYMETHOD_OPENGL_FILTER 40104 #define IDM_AUTODETECTSAVETYPE_FROMDATABASE 40105 #define ID_DISPLAYMETHOD_FILTER 40106 +#define IDC_VIEW_PADTOINTEGER 40107 #define ID_LABEL_HK3b 44670 #define ID_LABEL_HK3c 44671 #define ID_LABEL_HK3d 44672 @@ -1019,7 +1020,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 128 -#define _APS_NEXT_COMMAND_VALUE 40106 +#define _APS_NEXT_COMMAND_VALUE 40108 #define _APS_NEXT_CONTROL_VALUE 1054 #define _APS_NEXT_SYMED_VALUE 101 #endif diff --git a/desmume/src/windows/resources.rc b/desmume/src/windows/resources.rc index fd47fc5b0564c1c1eeff5cd0f4de270f79593856..545262581dfaf989aef4118bd2fa8f6e3c414b30 100644 GIT binary patch delta 1140 zcmY*YT}&Kh6uoor7MAU@9V$>Mr5%VJK}=j*#7b-3;?iGGT9nq|oev5E0# zF^1@qB%ADMeCa+ApG>nR>KaSi7k?g%4Qj%JHT*;nQ z%4o&2v)qVlpR*6CEU(4rEQhKsswbPe=mq6IuTKLVr9s7-HQ&%2*EkaO2+wg-Sw6H~ z1JBYa>ZJypo8x<(fOi{hYNL}BRceHKRHm0K>ehQi&sI9EjFXC;)msETlAEAuxOtf-AkwNSdQ1hDwFb>ZbjSF%yH^eepn-) zROAUg+h`AdtCU8JJRmLWx~N|@&Z&y+s-4yQ5HUv!GXj060X(}CT;#7A*oj{S$ z4}Cd4qUhB@sX}T=hgguj8{aPRZcTki-93&-P#W-Sj@Kubxw+t>?2J)`;GO@mdhT$z z#I@^GhDVoq>x!liZ!EK&Fuh&`t7JWrx4Ajdnem`KBz{cZW((;rRV}_nd>AhlFH#e1 zW`0=a(PB0EI?HyaD_(rYvR{ExDFBB=oWZ{R51?$35XNt@C*c`06UndEB2XfgNPnY0 z#1W6|&|r06fmF=!;C+wOVca9f-2drdl{}38Rq`GdOsO<1ylQIgp_|;287`8Tq1458 zZQ@&A*?^$e)%v7mAeqX&aEGt(mn7uV@jm}ppTDP98{(H^XgMUll=lWl+)_q|u=H16Ykr>6ade!oN;nq@-C;jY-RARB zo(ro&AI{$43aR)Xyk>$c@cTGdA~DCh`6SP0atsf zX|Kw)(;kdW^EM1U;I>rJLmu+J9km;`tHuUxR5iP(lakpR(|>Uc{WD6{2akEN=Sx+3 zP?aUIWQO0ji8s%1!dXXOPz_@DcoVM9aTNxeG#6Yic-8SVuku7~S^H=wj%9c`o(wBt zEot>d;S4upb(%}F4|b%v6~pu4qcq3SIIFS^qw0mq7Gq$Rci_8B&WmDP&u|n439Sf6 z$|N}7z6j5ra}6T19B?+$X8Oc3#=AM`_;X(4ww05C^>bW4ufm7kIW_X&6}79QW4tWY z@q$mdO~=_F43QFh?go*1<)RvFx}+_F;gygX&|QdJW*xUgDp7Yy3t4yxb{C2l10P8M z36b~A-fJr?yaV(EJNT5V>( zZGxoQSG$S~>Q=itU~eypV*yzL;|5oy3f$7E;agp@{`f_g3XF9~F@De`WP2Gs!|cF1 zk5t27t88e^U{n9>k%+k=|6e2(^-4rT|0pju|19+tHrf8L6d2T~&V#mR;?Q2P`icy@ z%+~K+=J-PWtw#Ekw$f+RKsEMRi?0?)IZiH+F0BqDK3Sgq^wB&es?{egxagA=|HXnR z&XXki^W<-1sp9P@_2+~k^!eq8XA3paVddU-%i|v++caP5(fo(zOP$M?lihCs`*~-<