sdl12-compat: video: Added SDL12COMPAT_MAX_VIDMODE hint to clamp max reported resolution.

From 40dff443364acf998c6cc0d9d45f3a152aba9b05 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sun, 18 Sep 2022 18:01:02 -0400
Subject: [PATCH] video: Added SDL12COMPAT_MAX_VIDMODE hint to clamp max
 reported resolution.

---
 README.md          | 12 ++++++++++++
 src/SDL12_compat.c | 27 +++++++++++++++++++++------
 2 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index fc5e47516..201740d72 100644
--- a/README.md
+++ b/README.md
@@ -228,6 +228,18 @@ The available options are:
   will create the window at the originally-requested size. If this variable
   isn't specified, it defaults to 1.0 (no scaling).
 
+- SDL12COMPAT_MAX_VIDMODE: (checked during SDL_Init)
+  This is a string in the form of `WxH`, where `W` is the maximum width
+  and `H` is the maximum height (for example: `640x480`). The list of valid
+  resolutions that will be reported by SDL_ListModes and SDL_VideoModeOK will
+  not include any dimensions that are wider or taller than these sizes. A size
+  of zero will be ignored, so for `0x480` a resolution of 1920x480 would be
+  accepted). If not specified, or set to `0x0`, no resolution clamping is done.
+  This is for old software-rendered games that might always choose the largest
+  resolution offered, but never conceived of 4K displays. In these cases, it
+  might be better for them to use a smaller resolution and let sdl12-compat
+  scale their output up with the GPU.
+
 - SDL_MOUSE_RELATIVE_SCALING: (checked during SDL_SetVideoMode)
   If enabled, relative mouse motion is scaled when the application is
   running at a non-native resolution.  This may be required with some
diff --git a/src/SDL12_compat.c b/src/SDL12_compat.c
index 6ec6fb971..0787ac3d5 100644
--- a/src/SDL12_compat.c
+++ b/src/SDL12_compat.c
@@ -1970,11 +1970,15 @@ VidModeSizeGreater(SDL12_Rect *mode1, SDL12_Rect *mode2)
 }
 
 static int
-AddVidModeToList(VideoModeList *vmode, SDL12_Rect *mode)
+AddVidModeToList(VideoModeList *vmode, SDL12_Rect *mode, const Uint16 maxw, const Uint16 maxh)
 {
     void *ptr = NULL;
     int i;
 
+    if ( (maxw && (mode->w > maxw)) || (maxh && (mode->h > maxh)) ) {
+        return 0;   /* clamp this one out as too big. */
+    }
+
     /* make sure we don't have this one already (with a different refresh rate, etc). */
     for (i = 0; i < vmode->nummodes; i++) {
         if ((vmode->modeslist12[i].w == mode->w) && (vmode->modeslist12[i].h == mode->h)) {
@@ -2038,21 +2042,32 @@ static int
 Init12VidModes(void)
 {
     const int total = SDL20_GetNumDisplayModes(VideoDisplayIndex);
+    const char *maxmodestr;
     VideoModeList *vmode = NULL;
     void *ptr = NULL;
     int i, j;
     SDL12_Rect prev_mode = { 0, 0, 0, 0 }, current_mode = { 0, 0, 0, 0 };
     /* We only want to enable fake modes if OpenGL Logical Scaling is enabled. */
     const SDL_bool use_fake_modes = SDL12Compat_GetHintBoolean("SDL12COMPAT_OPENGL_SCALING", SDL_TRUE);
-
-    WantOpenGLScaling = use_fake_modes;
+    Uint16 maxw = 0;
+    Uint16 maxh = 0;
 
     if (VideoModesCount > 0) {
         return 0;  /* already did this. */
     }
 
+    WantOpenGLScaling = use_fake_modes;
+
     SDL_assert(VideoModes == NULL);
 
+    maxmodestr = SDL12Compat_GetHint("SDL12COMPAT_MAX_VIDMODE");
+    if (maxmodestr) {
+        unsigned int w, h;
+        SDL_sscanf(maxmodestr, "%ux%u", &w, &h);
+        maxw = (Uint16) SDL_clamp(w, 0, 0xFFFF);
+        maxh = (Uint16) SDL_clamp(h, 0, 0xFFFF);
+    }
+
     for (i = 0; i < total; ++i) {
         SDL_DisplayMode mode;
 
@@ -2098,14 +2113,14 @@ Init12VidModes(void)
         if (use_fake_modes) {
             for (j = 0; j < (int) SDL_arraysize(fake_modes); ++j) {
                 if (VidModeSizeGreater(&prev_mode, &fake_modes[j]) && VidModeSizeGreater(&fake_modes[j], &current_mode)) {
-                    if (AddVidModeToList(vmode, &fake_modes[j])) {
+                    if (AddVidModeToList(vmode, &fake_modes[j], maxw, maxh)) {
                         return SDL20_OutOfMemory();
                     }
                 }
             }
         }
 
-        if (AddVidModeToList(vmode, &current_mode)) {
+        if (AddVidModeToList(vmode, &current_mode, maxw, maxh)) {
             return SDL20_OutOfMemory();
         }
 
@@ -2117,7 +2132,7 @@ Init12VidModes(void)
     if (use_fake_modes) {
         for (i = 0; i < (int) SDL_arraysize(fake_modes); ++i) {
             if (VidModeSizeGreater(&prev_mode, &fake_modes[i])) {
-                if (AddVidModeToList(vmode, &fake_modes[i])) {
+                if (AddVidModeToList(vmode, &fake_modes[i], maxw, maxh)) {
                     return SDL20_OutOfMemory();
                 }
             }