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
This commit is contained in:
bicarus
2026-05-09 21:32:43 -07:00
committed by GitHub
parent 33f2e1d4b7
commit 2014e9cf75
5 changed files with 66 additions and 7 deletions
+40 -5
View File
@@ -61,6 +61,7 @@ static std::condition_variable GRAPHICS_CAPTURE_CV[GRAPHICS_CAPTURE_SCREEN_NO] {
static std::optional<graphics_orientation> target_orientation_on_boot; static std::optional<graphics_orientation> target_orientation_on_boot;
static UINT target_refresh_rate_on_boot = 0; static UINT target_refresh_rate_on_boot = 0;
static std::optional<std::pair<uint32_t, uint32_t>> target_resolution_on_boot;
static bool monitor_settings_changed = false; static bool monitor_settings_changed = false;
static bool monitor_layout_needs_reset = false; static bool monitor_layout_needs_reset = false;
@@ -1279,8 +1280,13 @@ void change_primary_monitor(const std::string &monitor_name) {
Sleep(2000); Sleep(2000);
} }
void update_monitor(bool is_boot, std::optional<graphics_orientation> target_orientation, UINT target_refresh_rate) { void update_monitor(
// note: all of this is only being done for the primary motnior bool is_boot,
std::optional<graphics_orientation> target_orientation,
UINT target_refresh_rate,
std::optional<std::pair<uint32_t, uint32_t>> target_resolution) {
// note: all of this is only being done for the primary monitor
// get current settings // get current settings
DEVMODEA dm = {}; DEVMODEA dm = {};
@@ -1358,6 +1364,22 @@ void update_monitor(bool is_boot, std::optional<graphics_orientation> target_ori
needs_update = true; 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) { if (!needs_update) {
// nothing to do // nothing to do
log_misc("graphics", "display settings are already up to date, no changes needed"); 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<graphics_orientation> target_ori
} }
} }
void update_monitor_on_boot(std::optional<graphics_orientation> target_orientation, UINT target_refresh_rate) { void update_monitor_on_boot(
std::optional<graphics_orientation> target_orientation,
UINT target_refresh_rate,
std::optional<std::pair<uint32_t, uint32_t>> target_resolution) {
target_orientation_on_boot = target_orientation; target_orientation_on_boot = target_orientation;
target_refresh_rate_on_boot = target_refresh_rate; target_refresh_rate_on_boot = target_refresh_rate;
target_resolution_on_boot = target_resolution;
log_misc("graphics", "applying monitor updates at boot..."); 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() { void update_monitor_at_runtime() {
if (!GRAPHICS_WINDOWED && monitor_settings_changed) { if (!GRAPHICS_WINDOWED && monitor_settings_changed) {
log_misc("graphics", "applying monitor updates at runtime as window regained focus..."); 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);
} }
} }
+5 -1
View File
@@ -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 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 change_primary_monitor(const std::string &monitor_name);
void update_monitor_on_boot(std::optional<graphics_orientation> target_orientation, UINT target_refresh_rate); void update_monitor_on_boot(
std::optional<graphics_orientation> target_orientation,
UINT target_refresh_rate,
std::optional<std::pair<uint32_t, uint32_t>> target_resolution);
void update_monitor_at_runtime(); void update_monitor_at_runtime();
void reset_monitor_on_exit(); void reset_monitor_on_exit();
+11 -1
View File
@@ -385,6 +385,16 @@ int main_implementation(int argc, char *argv[]) {
monitor_orientation = ORIENTATION_CW; monitor_orientation = ORIENTATION_CW;
} }
std::optional<std::pair<uint32_t, uint32_t>> monitor_resolution;
if (options[launcher::Options::ChangeResolution].is_active()) {
std::pair<uint32_t, uint32_t> 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()) { if (options[launcher::Options::spice2x_NoD3D9DeviceHook].value_bool()) {
D3D9_DEVICE_HOOK_DISABLE = true; D3D9_DEVICE_HOOK_DISABLE = true;
// touch emulation gets disabled, might as well turn these on // 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()) { if (options[launcher::Options::PrimaryMonitor].is_active()) {
change_primary_monitor(options[launcher::Options::PrimaryMonitor].value_text()); 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 // initialize raw input
RI_MGR = std::make_unique<rawinput::RawInputManager>(); RI_MGR = std::make_unique<rawinput::RawInputManager>();
+9
View File
@@ -1920,6 +1920,15 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
{"3", "Landscape, Flipped"} {"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", .title = "AVS Log Level",
.name = "loglevel", .name = "loglevel",
+1
View File
@@ -199,6 +199,7 @@ namespace launcher {
LoadStubs, LoadStubs,
AdjustOrientation, AdjustOrientation,
spice2x_AutoOrientation, spice2x_AutoOrientation,
ChangeResolution,
LogLevel, LogLevel,
EAAutomap, EAAutomap,
EANetdump, EANetdump,