From 2014e9cf75e966c58750d068e59d2e10e3f059fb Mon Sep 17 00:00:00 2001 From: bicarus <202771338+bicarus-dev@users.noreply.github.com> Date: Sat, 9 May 2026 21:32:43 -0700 Subject: [PATCH] graphics: option to change monitor resolution (#689) ## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change Add a new option under `Monitor` group to change the monitor resolution before booting the game, very similar to how orientation / refresh rate options work. This would be useful for games like Polaris Chord that boots at current resolution but manages to have graphical issues when not in 1080p. ## Testing --- src/spice2x/hooks/graphics/graphics.cpp | 45 ++++++++++++++++++++++--- src/spice2x/hooks/graphics/graphics.h | 6 +++- src/spice2x/launcher/launcher.cpp | 12 ++++++- src/spice2x/launcher/options.cpp | 9 +++++ src/spice2x/launcher/options.h | 1 + 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/spice2x/hooks/graphics/graphics.cpp b/src/spice2x/hooks/graphics/graphics.cpp index 0cc203b..a654c29 100644 --- a/src/spice2x/hooks/graphics/graphics.cpp +++ b/src/spice2x/hooks/graphics/graphics.cpp @@ -61,6 +61,7 @@ static std::condition_variable GRAPHICS_CAPTURE_CV[GRAPHICS_CAPTURE_SCREEN_NO] { static std::optional target_orientation_on_boot; static UINT target_refresh_rate_on_boot = 0; +static std::optional> target_resolution_on_boot; static bool monitor_settings_changed = false; static bool monitor_layout_needs_reset = false; @@ -1279,8 +1280,13 @@ void change_primary_monitor(const std::string &monitor_name) { Sleep(2000); } -void update_monitor(bool is_boot, std::optional target_orientation, UINT target_refresh_rate) { - // note: all of this is only being done for the primary motnior +void update_monitor( + bool is_boot, + std::optional target_orientation, + UINT target_refresh_rate, + std::optional> target_resolution) { + + // note: all of this is only being done for the primary monitor // get current settings DEVMODEA dm = {}; @@ -1358,6 +1364,22 @@ void update_monitor(bool is_boot, std::optional target_ori needs_update = true; } + if (target_resolution.has_value()) { + if (dm.dmPelsWidth != target_resolution.value().first || + dm.dmPelsHeight != target_resolution.value().second) { + + log_misc( + "graphics", + "current resolution {}, {} => desired resolution {}, {}", + dm.dmPelsWidth, dm.dmPelsHeight, + target_resolution.value().first, target_resolution.value().second); + + dm.dmPelsWidth = target_resolution.value().first; + dm.dmPelsHeight = target_resolution.value().second; + needs_update = true; + } + } + if (!needs_update) { // nothing to do log_misc("graphics", "display settings are already up to date, no changes needed"); @@ -1394,17 +1416,30 @@ void update_monitor(bool is_boot, std::optional target_ori } } -void update_monitor_on_boot(std::optional target_orientation, UINT target_refresh_rate) { +void update_monitor_on_boot( + std::optional target_orientation, + UINT target_refresh_rate, + std::optional> target_resolution) { + target_orientation_on_boot = target_orientation; target_refresh_rate_on_boot = target_refresh_rate; + target_resolution_on_boot = target_resolution; log_misc("graphics", "applying monitor updates at boot..."); - update_monitor(true, target_orientation, target_refresh_rate); + update_monitor( + true, + target_orientation, + target_refresh_rate, + target_resolution); } void update_monitor_at_runtime() { if (!GRAPHICS_WINDOWED && monitor_settings_changed) { log_misc("graphics", "applying monitor updates at runtime as window regained focus..."); - update_monitor(false, target_orientation_on_boot, target_refresh_rate_on_boot); + update_monitor( + false, + target_orientation_on_boot, + target_refresh_rate_on_boot, + target_resolution_on_boot); } } diff --git a/src/spice2x/hooks/graphics/graphics.h b/src/spice2x/hooks/graphics/graphics.h index 4a91356..e2beb63 100644 --- a/src/spice2x/hooks/graphics/graphics.h +++ b/src/spice2x/hooks/graphics/graphics.h @@ -117,6 +117,10 @@ void graphics_load_windowed_subscreen_parameters(); void graphics_window_check_bounds_before_creation(int &x, int &y, const int width, const int height); void change_primary_monitor(const std::string &monitor_name); -void update_monitor_on_boot(std::optional target_orientation, UINT target_refresh_rate); +void update_monitor_on_boot( + std::optional target_orientation, + UINT target_refresh_rate, + std::optional> target_resolution); + void update_monitor_at_runtime(); void reset_monitor_on_exit(); \ No newline at end of file diff --git a/src/spice2x/launcher/launcher.cpp b/src/spice2x/launcher/launcher.cpp index 56c6ab6..a4879d8 100644 --- a/src/spice2x/launcher/launcher.cpp +++ b/src/spice2x/launcher/launcher.cpp @@ -385,6 +385,16 @@ int main_implementation(int argc, char *argv[]) { monitor_orientation = ORIENTATION_CW; } + std::optional> monitor_resolution; + if (options[launcher::Options::ChangeResolution].is_active()) { + std::pair result; + if (parse_width_height(options[launcher::Options::ChangeResolution].value_text(), result)) { + monitor_resolution = result; + } else if (!cfg_run && !cfg::CONFIGURATOR_STANDALONE) { + log_fatal("launcher", "failed to parse -changeres"); + } + } + if (options[launcher::Options::spice2x_NoD3D9DeviceHook].value_bool()) { D3D9_DEVICE_HOOK_DISABLE = true; // touch emulation gets disabled, might as well turn these on @@ -2189,7 +2199,7 @@ int main_implementation(int argc, char *argv[]) { if (options[launcher::Options::PrimaryMonitor].is_active()) { change_primary_monitor(options[launcher::Options::PrimaryMonitor].value_text()); } - update_monitor_on_boot(monitor_orientation, GRAPHICS_FORCE_REFRESH); + update_monitor_on_boot(monitor_orientation, GRAPHICS_FORCE_REFRESH, monitor_resolution); // initialize raw input RI_MGR = std::make_unique(); diff --git a/src/spice2x/launcher/options.cpp b/src/spice2x/launcher/options.cpp index fb35edf..b6f6679 100644 --- a/src/spice2x/launcher/options.cpp +++ b/src/spice2x/launcher/options.cpp @@ -1920,6 +1920,15 @@ static const std::vector OPTION_DEFINITIONS = { {"3", "Landscape, Flipped"} }, }, + { + // ChangeResolution + .title = "Change Monitor Resolution", + .name = "changeres", + .desc = "Changes monitor resolution before booting the game.", + .type = OptionType::Text, + .setting_name = "1280,720", + .category = "Monitor" + }, { .title = "AVS Log Level", .name = "loglevel", diff --git a/src/spice2x/launcher/options.h b/src/spice2x/launcher/options.h index 5e6e160..21ed49c 100644 --- a/src/spice2x/launcher/options.h +++ b/src/spice2x/launcher/options.h @@ -199,6 +199,7 @@ namespace launcher { LoadStubs, AdjustOrientation, spice2x_AutoOrientation, + ChangeResolution, LogLevel, EAAutomap, EANetdump,