From 3cf50d01babec5d4ad32d10c7799598b5cc944aa Mon Sep 17 00:00:00 2001 From: tomcw Date: Fri, 29 Sep 2017 20:33:30 +0100 Subject: [PATCH] Cmd-line: support new -fs-height= (#488) --- source/Applewin.cpp | 44 +++++++++++++++++++++++ source/Frame.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++ source/Frame.h | 1 + 3 files changed, 131 insertions(+) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index fddafe1c..7fcea1d5 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -919,6 +919,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) bool bShutdown = false; bool bSetFullScreen = false; bool bBoot = false; + bool bChangedDisplayResolution = false; + UINT bestWidth = 0, bestHeight = 0; LPSTR szImageName_drive1 = NULL; LPSTR szImageName_drive2 = NULL; LPSTR szSnapshotName = NULL; @@ -963,6 +965,30 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) { bSetFullScreen = true; } +#define CMD_FS_HEIGHT "-fs-height=" + else if (strncmp(lpCmdLine, CMD_FS_HEIGHT, sizeof(CMD_FS_HEIGHT)-1) == 0) + { + bSetFullScreen = true; // Implied + + LPSTR lpTmp = lpCmdLine + sizeof(CMD_FS_HEIGHT)-1; + bool bRes = false; + if (strcmp(lpTmp, "best") == 0) + { + bRes = GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight); + } + else + { + UINT userSpecifiedHeight = atoi(lpTmp); + if (userSpecifiedHeight) + bRes = GetBestDisplayResolutionForFullScreen(bestWidth, bestHeight, userSpecifiedHeight); + else + LogFileOutput("Invalid cmd-line parameter for -fs-height=x switch\n"); + } + if (bRes) + LogFileOutput("Best resolution for -fs-height=x switch: Width=%d, Height=%d\n", bestWidth, bestHeight); + else + LogFileOutput("Failed to set parameter for -fs-height=x switch\n"); + } else if (strcmp(lpCmdLine, "-fs8bit") == 0) { SetFullScreen32Bit(false); // Support old v1.24 fullscreen 8-bit palette mode @@ -1299,6 +1325,21 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) { if (bSetFullScreen) { + if (bestWidth && bestHeight) + { + DEVMODE devMode; + memset(&devMode, 0, sizeof(devMode)); + devMode.dmSize = sizeof(devMode); + devMode.dmPelsWidth = bestWidth; + devMode.dmPelsHeight = bestHeight; + devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; + + DWORD dwFlags = 0; + LONG res = ChangeDisplaySettings(&devMode, dwFlags); + if (res == 0) + bChangedDisplayResolution = true; + } + PostMessage(g_hFrameWindow, WM_USER_FULLSCREEN, 0, 0); bSetFullScreen = false; } @@ -1332,6 +1373,9 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) } while (g_bRestart); + if (bChangedDisplayResolution) + ChangeDisplaySettings(NULL, 0); // restore default + // Release COM SysClk_UninitTimer(); LogFileOutput("Exit: SysClk_UninitTimer()\n"); diff --git a/source/Frame.cpp b/source/Frame.cpp index 387ae8c6..bb69ef19 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -2793,3 +2793,89 @@ void FrameUpdateApple2Type(void) // Draw buttons & call DrawStatusArea(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS) DrawFrameWindow(); } + +bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight /*= 0*/) +{ + typedef std::vector< std::pair > VEC_PAIR; + VEC_PAIR vecDisplayResolutions; + + for (UINT iModeNum = 0; ; iModeNum++) + { + DEVMODE devMode; + devMode.dmSize = sizeof(DEVMODE); + devMode.dmDriverExtra = 0; + BOOL bValid = EnumDisplaySettings(NULL, iModeNum, &devMode); + if (!bValid) + break; + if (iModeNum == 0) // 0 is the initial "cache info about display device" operation + continue; + + if (devMode.dmBitsPerPel != 32) + continue; + + if (userSpecifiedHeight == 0 || userSpecifiedHeight == devMode.dmPelsHeight) + { + if (vecDisplayResolutions.size() == 0 || vecDisplayResolutions.back() != std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) ) // Skip duplicate resolutions + { + vecDisplayResolutions.push_back( std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) ); + LogFileOutput("EnumDisplaySettings(%d) - %d x %d\n", iModeNum, devMode.dmPelsWidth, devMode.dmPelsHeight); + } + } + } + + const int A2_WINDOW_WIDTH = FRAMEBUFFER_BORDERLESS_W; + const int A2_WINDOW_HEIGHT = FRAMEBUFFER_BORDERLESS_H; + + if (userSpecifiedHeight) + { + if (vecDisplayResolutions.size() == 0) + return false; + + // Pick least width (such that it's wide enough to scale) + UINT width = (UINT)-1; + for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it) + { + if (width > it->first) + { + UINT scaleFactor = it->second / A2_WINDOW_HEIGHT; + if (it->first >= (A2_WINDOW_WIDTH * scaleFactor)) + { + width = it->first; + } + } + } + + if (width == (UINT)-1) + return false; + + bestWidth = width; + bestHeight = userSpecifiedHeight; + return true; + } + + // Pick max height that's an exact multiple of A2_WINDOW_HEIGHT + UINT tmpBestWidth = 0; + UINT tmpBestHeight = 0; + for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it) + { + if ((it->second % A2_WINDOW_HEIGHT) == 0) + { + if (it->second > tmpBestHeight) + { + UINT scaleFactor = it->second / A2_WINDOW_HEIGHT; + if (it->first >= (A2_WINDOW_WIDTH * scaleFactor)) + { + tmpBestWidth = it->first; + tmpBestHeight = it->second; + } + } + } + } + + if (tmpBestWidth == 0) + return false; + + bestWidth = tmpBestWidth; + bestHeight = tmpBestHeight; + return true; +} diff --git a/source/Frame.h b/source/Frame.h index 2c68c879..4abb05ac 100644 --- a/source/Frame.h +++ b/source/Frame.h @@ -69,6 +69,7 @@ bool GetFullScreen32Bit(void); void SetFullScreen32Bit(bool b32Bit); void FrameUpdateApple2Type(void); + bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight=0); void FrameDrawDiskLEDS( HDC hdc ); void FrameDrawDiskStatus( HDC hdc );