Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 8897a46

Browse files
committed
Change resolution validation to support multiple screens
Add settings flag to disable validation for multi-screen to run unsafe/unsupported resolutions
1 parent 5d05e5c commit 8897a46

File tree

5 files changed

+110
-11
lines changed

5 files changed

+110
-11
lines changed

CHANGELOG.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
217217

218218
**Note:** Changing the game window resolution while an Activity is active requires ending the Activity. A dialog box will appear asking to confirm the change.
219219

220-
- Moved from C-style random number generation to C++ standard. This includes usage of an mt19937 random number generator.
221-
- For C++ coders the functions SelectRand, PosRand and RangeRand have been replaced by the function template RandomNum() and its overload RandomNum(T min, T max). The function NormalRand has been replaced by the function template RandomNormalNum(). For lua coders there is no change.
220+
- Moved from C-style random number generation to C++ standard. This includes usage of an mt19937 random number generator.
221+
For C++ coders the functions SelectRand, PosRand and RangeRand have been replaced by the function template RandomNum() and its overload RandomNum(T min, T max). The function NormalRand has been replaced by the function template RandomNormalNum(). For lua coders there is no change.
222+
223+
- Resolution validation changed to support multiple screens. Incompatible/bad resolution settings will be overridden at startup with messages explaining the issue.
224+
**Note:** For multi-screen to work properly, the left-most screen MUST be set as primary. Screens having different resolutions does not actually matter but different heights will still be warned about and overridden due to the likeliness of GUI elementes being cropped on the shortest screen.
225+
Resolution validation can be disabled for multi-screen setups with `Settings.ini` property `DisableMultiScreenResolutionValidation`. Bad settings are likely to crash, use at own risk.
226+
For setups with more than 3 screens `DisableMultiScreenResolutionValidation` must be set true.
222227

223228
### Fixed
224229

Managers/FrameMan.cpp

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ namespace RTE {
3232

3333
void FrameMan::Clear() {
3434
m_GfxDriver = GFX_AUTODETECT_WINDOWED;
35-
m_ScreenResX = GetSystemMetrics(SM_CXSCREEN);
36-
m_ScreenResY = GetSystemMetrics(SM_CYSCREEN);
35+
m_DisableMultiScreenResolutionValidation = false;
36+
m_NumScreens = GetSystemMetrics(SM_CMONITORS);
37+
m_ScreenResX = GetSystemMetrics(SM_CXVIRTUALSCREEN);
38+
m_ScreenResY = GetSystemMetrics(SM_CYVIRTUALSCREEN);
39+
m_PrimaryScreenResX = GetSystemMetrics(SM_CXSCREEN);
40+
m_PrimaryScreenResY = GetSystemMetrics(SM_CYSCREEN);
3741
m_ResX = 960;
3842
m_ResY = 540;
3943
m_NewResX = m_ResX;
@@ -124,14 +128,75 @@ namespace RTE {
124128
} else if ((resX * resMultiplier) % 4 > 0) {
125129
allegro_message("Resolution width that is not divisible by 4 is not supported!\nOverriding to closest valid width!");
126130
resX = m_NewResX = std::floor(resX / 4) * 4;
127-
} else {
131+
}
132+
133+
if (m_NumScreens == 1) {
128134
float currentAspectRatio = static_cast<float>(resX) / static_cast<float>(resY);
129135
if (currentAspectRatio < 1 || currentAspectRatio > 4) {
130136
allegro_message("Abnormal aspect ratio detected! Reverting to defaults!");
131137
resX = m_NewResX = 960;
132138
resY = m_NewResY = 540;
133139
resMultiplier = m_ResMultiplier = m_NewResMultiplier = 1;
134140
}
141+
} else if (!m_DisableMultiScreenResolutionValidation && m_NumScreens > 1 && m_NumScreens < 4) {
142+
if (resX * resMultiplier > m_PrimaryScreenResX || resY * resMultiplier > m_PrimaryScreenResY) { ValidateMultiScreenResolution(resX, resY, resMultiplier); }
143+
} else if (!m_DisableMultiScreenResolutionValidation && m_NumScreens > 3) {
144+
allegro_message("Number of screens is too damn high! Overriding to defaults!\n\nPlease disable multi-screen resolution validation in \"Settings.ini\" and run at your own risk!");
145+
resX = m_NewResX = 960;
146+
resY = m_NewResY = 540;
147+
resMultiplier = m_ResMultiplier = m_NewResMultiplier = 1;
148+
}
149+
150+
g_SettingsMan.UpdateSettingsFile();
151+
}
152+
153+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
154+
155+
void FrameMan::ValidateMultiScreenResolution(unsigned short &resX, unsigned short &resY, unsigned short &resMultiplier) {
156+
POINT pointOnScreen;
157+
HMONITOR screenHandle;
158+
MONITORINFO screenInfo;
159+
160+
pointOnScreen = { -1 , 0 };
161+
screenHandle = MonitorFromPoint(pointOnScreen, MONITOR_DEFAULTTONULL);
162+
if (screenHandle != NULL) {
163+
const char *leftNotPrimaryMessage = {
164+
"Due to limitations in Cortex Command's graphics API it is impossible to properly run multi-screen mode when the left-most screen is not set as primary.\n"
165+
"Please configure your left-most screen to be primary to utilize all screens, as the game window will extend right but will not extend left, leaving any screen left of the primary unused.\n\n"
166+
"You can disable multi-screen resolution validation in \"Settings.ini\" and run at your own risk!\n\nResolution settings will be overridden fit primary screen only!"
167+
};
168+
allegro_message(leftNotPrimaryMessage);
169+
resX = m_NewResX = m_PrimaryScreenResX / resMultiplier;
170+
resY = m_NewResY = m_PrimaryScreenResY / resMultiplier;
171+
return;
172+
}
173+
174+
pointOnScreen = { m_PrimaryScreenResX + 1 , 0 };
175+
screenHandle = MonitorFromPoint(pointOnScreen, MONITOR_DEFAULTTONULL);
176+
screenInfo = { sizeof(MONITORINFO) };
177+
GetMonitorInfo(screenHandle, &screenInfo);
178+
unsigned short centerScreenResY = screenInfo.rcMonitor.bottom;
179+
180+
if (centerScreenResY != m_PrimaryScreenResY) {
181+
allegro_message("Center screen height is not identical to primary screen, overriding to fit primary screen only!\n\nYou can disable multi-screen resolution validation in \"Settings.ini\" and run at your own risk!");
182+
resX = m_NewResX = m_PrimaryScreenResX / resMultiplier;
183+
resY = m_NewResY = m_PrimaryScreenResY / resMultiplier;
184+
return;
185+
}
186+
187+
if (m_NumScreens == 3) {
188+
pointOnScreen = { screenInfo.rcMonitor.right + 1 , 0 };
189+
screenHandle = MonitorFromPoint(pointOnScreen, MONITOR_DEFAULTTONULL);
190+
screenInfo = { sizeof(MONITORINFO) };
191+
GetMonitorInfo(screenHandle, &screenInfo);
192+
unsigned short rightScreenResY = screenInfo.rcMonitor.bottom;
193+
194+
if (rightScreenResY != m_PrimaryScreenResY) {
195+
allegro_message("Right screen height is not identical to primary screen, overriding to extend to center screen only!\n\nYou can disable multi-screen resolution validation in \"Settings.ini\" and run at your own risk!");
196+
resX = m_NewResX = (m_ScreenResX - (screenInfo.rcMonitor.right - screenInfo.rcMonitor.left)) / resMultiplier;
197+
resY = m_NewResY = m_PrimaryScreenResY / resMultiplier;
198+
return;
199+
}
135200
}
136201
}
137202

@@ -260,6 +325,8 @@ namespace RTE {
260325
m_NewResY = m_ResY;
261326
} else if (propName == "ResolutionMultiplier") {
262327
reader >> m_ResMultiplier;
328+
} else if (propName == "DisableMultiScreenResolutionValidation") {
329+
reader >> m_DisableMultiScreenResolutionValidation;
263330
} else if (propName == "HSplitScreen") {
264331
reader >> m_HSplitOverride;
265332
} else if (propName == "VSplitScreen") {
@@ -281,6 +348,10 @@ namespace RTE {
281348
writer << m_ResX;
282349
writer.NewProperty("ResolutionY");
283350
writer << m_ResY;
351+
writer.NewProperty("ResolutionMultiplier");
352+
writer << m_ResMultiplier;
353+
writer.NewProperty("DisableMultiScreenResolutionValidation");
354+
writer << m_DisableMultiScreenResolutionValidation;
284355
writer.NewProperty("HSplitScreen");
285356
writer << m_HSplitOverride;
286357
writer.NewProperty("VSplitScreen");

Managers/FrameMan.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ namespace RTE {
143143
/// <returns>What multiple the screen resolution is run in (1 normal).</returns>
144144
unsigned short ResolutionMultiplier() const { return m_ResMultiplier; }
145145

146+
/// <summary>
147+
/// Gets whether resolution validation in multi-screen mode is disabled or not.
148+
/// </summary>
149+
/// <returns>Whether resolution validation in multi-screen mode is disabled or not.</returns>
150+
bool IsMultiScreenResolutionValidationDisabled() const { return m_DisableMultiScreenResolutionValidation; }
151+
146152
/// <summary>
147153
/// Sets and switches to a new windowed mode resolution multiplier.
148154
/// </summary>
@@ -551,8 +557,13 @@ namespace RTE {
551557

552558
int m_GfxDriver; //!< The graphics driver that will be used for rendering.
553559

554-
unsigned short m_ScreenResX; //!< Width of the physical screen (desktop resolution).
555-
unsigned short m_ScreenResY; //!< Height of the physical screen (desktop resolution).
560+
bool m_DisableMultiScreenResolutionValidation; //!< Whether to disable resolution validation or not. Allows setting whatever crazy resolution that may or may not crash.
561+
562+
unsigned short m_NumScreens; //!< Number of physical screens.
563+
unsigned short m_ScreenResX; //!< Width of the primary or all physical screens combined if more than one available (desktop resolution).
564+
unsigned short m_ScreenResY; //!< Height of the primary or tallest screen if more than one available (desktop resolution).
565+
unsigned short m_PrimaryScreenResX; //!< Width of the primary physical screen only.
566+
unsigned short m_PrimaryScreenResY; //!< Height of the primary physical screen only.
556567

557568
unsigned short m_ResX; //!< Game window width.
558569
unsigned short m_ResY; //!< Game window height.
@@ -666,6 +677,14 @@ namespace RTE {
666677
/// <param name="resMultiplier">Game window resolution multiplier to check.</param>
667678
void ValidateResolution(unsigned short &resX, unsigned short &resY, unsigned short &resMultiplier);
668679

680+
/// <summary>
681+
/// Checks whether the passed in multi-screen resolution settings make sense. If not, overrides them to prevent crashes or unexpected behavior. This is called during ValidateResolution().
682+
/// </summary>
683+
/// <param name="resX">Game window width to check.</param>
684+
/// <param name="resY">Game window height to check.</param>
685+
/// <param name="resMultiplier">Game window resolution multiplier to check.</param>
686+
void ValidateMultiScreenResolution(unsigned short &resX, unsigned short &resY, unsigned short &resMultiplier);
687+
669688
/// <summary>
670689
/// Creates all the frame buffer bitmaps to be used by FrameMan. This is called during Create().
671690
/// </summary>

Managers/SettingsMan.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ namespace RTE {
107107
g_FrameMan.ReadProperty(propName, reader);
108108
} else if (propName == "ResolutionMultiplier") {
109109
g_FrameMan.ReadProperty(propName, reader);
110+
} else if (propName == "DisableMultiScreenResolutionValidation") {
111+
g_FrameMan.ReadProperty(propName, reader);
110112
} else if (propName == "HSplitScreen") {
111113
g_FrameMan.ReadProperty(propName, reader);
112114
} else if (propName == "VSplitScreen") {
@@ -265,6 +267,8 @@ namespace RTE {
265267
writer << g_FrameMan.GetNewResY();
266268
writer.NewProperty("ResolutionMultiplier");
267269
writer << g_FrameMan.ResolutionMultiplier();
270+
writer.NewProperty("DisableMultiScreenResolutionValidation");
271+
writer << g_FrameMan.IsMultiScreenResolutionValidationDisabled();
268272
writer.NewProperty("HSplitScreen");
269273
writer << g_FrameMan.GetHSplit();
270274
writer.NewProperty("VSplitScreen");
@@ -490,6 +494,8 @@ namespace RTE {
490494
writer << 540;
491495
writer.NewProperty("ResolutionMultiplier");
492496
writer << 1;
497+
writer.NewProperty("DisableMultiScreenResolutionValidation");
498+
writer << 0;
493499
writer.NewProperty("SoundVolume");
494500
writer << 40;
495501
writer.NewProperty("MusicVolume");

Menus/MainMenuGUI.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,8 +1142,7 @@ void MainMenuGUI::Update()
11421142
g_SettingsMan.SetShowToolTips(m_aOptionsCheckbox[SHOWTOOLTIPS]->GetCheck());
11431143
g_SettingsMan.SetPreciseCollisions(m_aOptionsCheckbox[PRECISECOLLISIONS]->GetCheck());
11441144

1145-
Writer writer("Base.rte/Settings.ini");
1146-
g_SettingsMan.Save(writer);
1145+
g_SettingsMan.UpdateSettingsFile();
11471146
}
11481147

11491148
m_MenuScreen = MAINSCREEN;
@@ -1528,8 +1527,7 @@ void MainMenuGUI::Update()
15281527
if (anEvent.GetControl() == m_pModManagerBackButton)
15291528
{
15301529
// Save settings
1531-
Writer writer("Base.rte/Settings.ini");
1532-
g_SettingsMan.Save(writer);
1530+
g_SettingsMan.UpdateSettingsFile();
15331531

15341532
// Hide all screens, the appropriate screen will reappear on next update
15351533
HideAllScreens();

0 commit comments

Comments
 (0)