From 20cd7621c3092fcf7e217feb7dfef9b1b28ffdaa Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 17:52:46 +0100 Subject: [PATCH 01/24] delet numVidModes wasnt doing anything --- src/sdl/i_video.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index ebb8d7685..4a8d2e4c5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -86,10 +86,6 @@ // maximum number of windowed modes (see windowedModes[][]) #define MAXWINMODES (22) -/** \brief -*/ -static INT32 numVidModes = -1; - /** \brief */ static char vidModeName[33][32]; // allow 33 different modes @@ -1456,10 +1452,7 @@ void I_SetPalette(RGBA_t *palette) // return number of fullscreen + X11 modes INT32 VID_NumModes(void) { - if (USE_FULLSCREEN && numVidModes != -1) - return numVidModes - firstEntry; - else - return MAXWINMODES; + return MAXWINMODES; } const char *VID_GetModeName(INT32 modeNum) -- 2.54.0 From c3d02090e40feb014a974a5772368861e79f013a Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 18:34:00 +0100 Subject: [PATCH 02/24] WIP: remove hardcoded resolutions much thanks dsda-doom for most of the code for this TODO: - resolution menu needs to refresh if the list changes - clean up - handle custom resolutions more sane - figure out the best maximum resolution list size the menu can display --- src/sdl/i_video.c | 257 +++++++++++++++++++++++++++++++++------------- 1 file changed, 186 insertions(+), 71 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 4a8d2e4c5..d0c8ad9f3 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -84,11 +84,22 @@ #endif // maximum number of windowed modes (see windowedModes[][]) -#define MAXWINMODES (22) +#define MAXWINMODES (33) -/** \brief -*/ -static char vidModeName[33][32]; // allow 33 different modes +static void I_FillScreenResolutionsList(void); + +typedef struct +{ + char *name; + INT32 w; + INT32 h; +} video_mode_t; + +static video_mode_t windowedModes[MAXWINMODES] = {{NULL, 0, 0}}; + +#define CUSTOMMODENUM 9999 +static INT32 custom_width = 0; +static INT32 custom_height = 0; rendermode_t rendermode = render_none; @@ -135,9 +146,6 @@ static SDL_bool disable_mouse = SDL_FALSE; #define MOUSE_MENU false //(!disable_mouse && cv_usemouse.value && menuactive && !USE_FULLSCREEN) #define MOUSEBUTTONS_MAX MOUSEBUTTONS -// first entry in the modelist which is not bigger than MAXVIDWIDTHxMAXVIDHEIGHT -static INT32 firstEntry = 0; - // Total mouse motion X/Y offsets static INT32 mousemovex = 0, mousemovey = 0; @@ -158,37 +166,6 @@ static SDL_Texture *texture = NULL; static SDL_bool havefocus = SDL_TRUE; static const char *fallback_resolution_name = "Fallback"; -// windowed video modes from which to choose from. -static INT32 windowedModes[MAXWINMODES][2] = -{ - {2560,1440}, // 1.66 - {1920,1200}, // 1.60,6.00 - {1920,1080}, // 1.66 - {1680,1050}, // 1.60,5.25 - {1600,1200}, // 1.33 - {1600, 900}, // 1.66 - {1366, 768}, // 1.66 - {1440, 900}, // 1.60,4.50 - {1280,1024}, // 1.33? - {1280, 960}, // 1.33,4.00 - {1280, 800}, // 1.60,4.00 - {1280, 720}, // 1.66 - {1152, 864}, // 1.33,3.60 - {1024, 768}, // 1.33,3.20 - { 960, 600}, // 1.33,3.20 - { 800, 600}, // 1.33,2.50 - { 735, 415}, // 1.33,2.50 - { 640, 480}, // 1.33,2.00 - { 640, 400}, // 1.60,2.00 - { 500, 300}, // 1.33 - { 320, 240}, // 1.33,1.00 - { 320, 200}, // 1.60,1.00 -}; - -#define CUSTOMMODENUM 9999 -static INT32 custom_width = 0; -static INT32 custom_height = 0; - static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); static void Impl_SetWindowIcon(void); @@ -513,11 +490,18 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) return; } - if (windowmoved && rendermode == render_opengl) + if (windowmoved) { - I_CheckDesktopRes(); + I_FillScreenResolutionsList(); + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + I_CheckDesktopRes(); #ifdef USE_FBO_OGL - I_DownSample(); + I_DownSample(); +#endif + } #endif } @@ -533,7 +517,8 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (!firsttimeonmouse) { - if (cv_usemouse.value) I_StartupMouse(); + if (cv_usemouse.value) + I_StartupMouse(); } } else if (!mousefocus && !kbfocus) @@ -1138,7 +1123,11 @@ static void VID_Command_ModeList_f(void) for (i = 0; i < MAXWINMODES; i++) { - CONS_Printf("%2d: %dx%d\n", i, windowedModes[i][0], windowedModes[i][1]); + // not a valid mode + if (!windowedModes[i].w || !windowedModes[i].h) + continue; + + CONS_Printf("%2d: %dx%d\n", i, windowedModes[i].w, windowedModes[i].h); } } @@ -1449,6 +1438,145 @@ void I_SetPalette(RGBA_t *palette) } } + +// make sure the canonical resolutions are always available +static const struct { + const int w, h; +} canonicals[] = { + {1920, 1200}, // 16:10 + {1280, 800}, // 16:10 + { 960, 600}, // 16:10 + { 640, 400}, // 16:10 + { 320, 200}, // Vanilla Doom +}; +static const int num_canonicals = sizeof(canonicals)/sizeof(*canonicals); + +// [FG] sort resolutions by width first and height second +static int cmp_resolutions (const void *a, const void *b) +{ + const char *const *sa = (const char *const *) a; + const char *const *sb = (const char *const *) b; + + int wa, wb, ha, hb; + + if (sscanf(*sa, "%dx%d", &wa, &ha) != 2) wa = ha = 0; + if (sscanf(*sb, "%dx%d", &wb, &hb) != 2) wb = hb = 0; + + return (wa == wb) ? hb - ha : wb - wa; +} + +static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_index, int *list_size) +{ + int i; + char mode_name[256]; + + snprintf(mode_name, sizeof(mode_name), "%dx%d", mode->w, mode->h); + + for(i = 0; i < *list_size; i++) + if (!strcmp(mode_name, windowedModes[i].name)) + return; + + windowedModes[*list_size].name = strdup(mode_name); + windowedModes[*list_size].w = mode->w; + windowedModes[*list_size].h = mode->h; + + if (mode->w == custom_width && mode->h == custom_height) + *current_resolution_index = *list_size; + + (*list_size)++; +} + +// +// I_FillScreenResolutionsList +// Get all the supported screen resolutions +// and fill the list with them +// +static void I_FillScreenResolutionsList(void) +{ + int currentDisplayIndex = -1; + static int oldDisplayIndex = -1; + SDL_DisplayMode mode; + int i, list_size, current_resolution_index; + int count = 0; + char desired_resolution[256]; + + if (currentDisplayIndex < 0) + currentDisplayIndex = SDL_GetWindowDisplayIndex(window); + + // didnt change screen, no need to redo the list + if (currentDisplayIndex == oldDisplayIndex) + { + return; + } + + oldDisplayIndex = currentDisplayIndex; + + // No valid index + if (currentDisplayIndex < 0) + { + return; + } + + // Don't call SDL_ListModes if SDL has not been initialized + count = SDL_GetNumDisplayModes(currentDisplayIndex); + + list_size = 0; + current_resolution_index = -1; + + // on success, SDL_GetNumDisplayModes() always returns at least 1 + if (count > 0) + { + // -2 for the desired resolution and for NULL + count = min(count, MAXWINMODES - 2 - num_canonicals); + + for (i = count - 1 + num_canonicals; i >= 0; i--) + { + // make sure the canonical resolutions are always available + if (i > count - 1) + { + // no hard-coded resolutions for mode-changing fullscreen + //if (exclusive_fullscreen) + //continue; + + mode.w = canonicals[i - count].w; + mode.h = canonicals[i - count].h; + } + else + { + SDL_GetDisplayMode(currentDisplayIndex, i, &mode); + } + + I_AppendResolution(&mode, ¤t_resolution_index, &list_size); + } + + windowedModes[list_size].name = NULL; + } + + snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_width, custom_height); + + // [FG] if the desired resolution not in the list, append it + if (current_resolution_index == -1) + { + windowedModes[list_size].name = strdup(desired_resolution); + list_size++; + } + + // [FG] sort the list + SDL_qsort(windowedModes, list_size, sizeof(*windowedModes), cmp_resolutions); + + // [FG] find the desired resolution again + for (i = 0; i < list_size; i++) + { + if (!strcmp(desired_resolution, windowedModes[i].name)) + { + current_resolution_index = i; + break; + } + } + + windowedModes[list_size].name = NULL; +} + // return number of fullscreen + X11 modes INT32 VID_NumModes(void) { @@ -1465,20 +1593,20 @@ const char *VID_GetModeName(INT32 modeNum) if (modeNum > MAXWINMODES) return NULL; - sprintf(&vidModeName[modeNum][0], "%dx%d", - windowedModes[modeNum][0], - windowedModes[modeNum][1]); + I_FillScreenResolutionsList(); - return &vidModeName[modeNum][0]; + return windowedModes[modeNum].name; } INT32 VID_GetModeForSize(INT32 w, INT32 h) { int i; + I_FillScreenResolutionsList(); + for (i = 0; i < MAXWINMODES; i++) { - if (windowedModes[i][0] == w && windowedModes[i][1] == h) + if (windowedModes[i].w == w && windowedModes[i].h == h) { return i; } @@ -1529,10 +1657,12 @@ INT32 VID_SetMode(INT32 modeNum) { vid.recalc = true; + I_FillScreenResolutionsList(); + if (modeNum >= 0 && modeNum < MAXWINMODES) { - vid.width = windowedModes[modeNum][0]; - vid.height = windowedModes[modeNum][1]; + vid.width = windowedModes[modeNum].w; + vid.height = windowedModes[modeNum].h; vid.modenum = modeNum; } else if (modeNum == CUSTOMMODENUM && custom_width && custom_height) @@ -1542,25 +1672,6 @@ INT32 VID_SetMode(INT32 modeNum) vid.height = custom_height; vid.modenum = modeNum; } - else - { - // just set the desktop resolution as a fallback - SDL_DisplayMode mode; - SDL_GetWindowDisplayMode(window, &mode); - - if (mode.w >= 2048) - { - vid.width = 1920; - vid.height = 1200; - } - else - { - vid.width = mode.w; - vid.height = mode.h; - } - - vid.modenum = -1; - } SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); @@ -1685,6 +1796,9 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) return SDL_FALSE; } + // be sure to fill the resolution list the moment we have a window + I_FillScreenResolutionsList(); + return Impl_CreateContext(); } @@ -1871,8 +1985,6 @@ void I_StartupGraphics(void) usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); - VID_Command_ModeList_f(); - #ifdef HWRENDER if (rendermode == render_opengl) { @@ -1896,6 +2008,9 @@ void I_StartupGraphics(void) vid.height = BASEVIDHEIGHT; // BitsPerPixel is the SDL interface's vid.recalc = true; // Set up the console stufff + // be sure to print AFTER window creation + VID_Command_ModeList_f(); + #ifdef HAVE_TTF I_ShutdownTTF(); #endif -- 2.54.0 From ccc453e0b0437a378557a4d9406ee854fd6d0cea Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 18:51:58 +0100 Subject: [PATCH 03/24] fix windowmoved never resetting --- src/sdl/i_video.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index d0c8ad9f3..698244f1d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -503,6 +503,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) #endif } #endif + windowmoved = SDL_FALSE; } if (mousefocus && kbfocus) -- 2.54.0 From 3058d365f32ad9bcf4be17990bcbf20aa0ed1ab9 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 18:52:53 +0100 Subject: [PATCH 04/24] no need to call I_FillScreenResolutionsList everywhere its fine after startup, and when we move our window --- src/sdl/i_video.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 698244f1d..868aee3cd 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1594,8 +1594,6 @@ const char *VID_GetModeName(INT32 modeNum) if (modeNum > MAXWINMODES) return NULL; - I_FillScreenResolutionsList(); - return windowedModes[modeNum].name; } @@ -1603,8 +1601,6 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) { int i; - I_FillScreenResolutionsList(); - for (i = 0; i < MAXWINMODES; i++) { if (windowedModes[i].w == w && windowedModes[i].h == h) @@ -1658,8 +1654,6 @@ INT32 VID_SetMode(INT32 modeNum) { vid.recalc = true; - I_FillScreenResolutionsList(); - if (modeNum >= 0 && modeNum < MAXWINMODES) { vid.width = windowedModes[modeNum].w; -- 2.54.0 From a730dfd21272078794c37cdf9211d44b958ad5a6 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 18:53:26 +0100 Subject: [PATCH 05/24] fix checking for if display changed --- src/sdl/i_video.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 868aee3cd..f8f840a1d 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1501,8 +1501,13 @@ static void I_FillScreenResolutionsList(void) int count = 0; char desired_resolution[256]; + currentDisplayIndex = SDL_GetWindowDisplayIndex(window); + + // No valid index if (currentDisplayIndex < 0) - currentDisplayIndex = SDL_GetWindowDisplayIndex(window); + { + return; + } // didnt change screen, no need to redo the list if (currentDisplayIndex == oldDisplayIndex) @@ -1512,12 +1517,6 @@ static void I_FillScreenResolutionsList(void) oldDisplayIndex = currentDisplayIndex; - // No valid index - if (currentDisplayIndex < 0) - { - return; - } - // Don't call SDL_ListModes if SDL has not been initialized count = SDL_GetNumDisplayModes(currentDisplayIndex); -- 2.54.0 From 406dbf333d5ecfb6f13a68ff9af458f064572d82 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 18:54:20 +0100 Subject: [PATCH 06/24] use a video_mode_t thing for our custom resolution perhaps we may merge it into windowedmodes? not sure but this works for now --- src/sdl/i_video.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index f8f840a1d..3ccdd1ca3 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -86,6 +86,9 @@ // maximum number of windowed modes (see windowedModes[][]) #define MAXWINMODES (33) +// detect our custom resolution +#define CUSTOMMODENUM 9999 + static void I_FillScreenResolutionsList(void); typedef struct @@ -96,10 +99,7 @@ typedef struct } video_mode_t; static video_mode_t windowedModes[MAXWINMODES] = {{NULL, 0, 0}}; - -#define CUSTOMMODENUM 9999 -static INT32 custom_width = 0; -static INT32 custom_height = 0; +static video_mode_t customMode = {NULL, 0, 0}; rendermode_t rendermode = render_none; @@ -492,6 +492,8 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (windowmoved) { + // if we say moved our game window to a different screen + // refetch our resolutions I_FillScreenResolutionsList(); #ifdef HWRENDER @@ -1473,7 +1475,7 @@ static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_in snprintf(mode_name, sizeof(mode_name), "%dx%d", mode->w, mode->h); - for(i = 0; i < *list_size; i++) + for (i = 0; i < *list_size; i++) if (!strcmp(mode_name, windowedModes[i].name)) return; @@ -1481,7 +1483,7 @@ static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_in windowedModes[*list_size].w = mode->w; windowedModes[*list_size].h = mode->h; - if (mode->w == custom_width && mode->h == custom_height) + if (mode->w == customMode.w && mode->h == customMode.h) *current_resolution_index = *list_size; (*list_size)++; @@ -1552,7 +1554,7 @@ static void I_FillScreenResolutionsList(void) windowedModes[list_size].name = NULL; } - snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_width, custom_height); + snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", customMode.w, customMode.h); // [FG] if the desired resolution not in the list, append it if (current_resolution_index == -1) @@ -1614,8 +1616,8 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) if ((w >= BASEVIDWIDTH && h >= BASEVIDHEIGHT) && (rendermode == render_opengl || (w <= MAXVIDWIDTH && h <= MAXVIDHEIGHT))) { - custom_width = w; - custom_height = h; + customMode.w = w; + customMode.h = h; return CUSTOMMODENUM; } @@ -1659,11 +1661,11 @@ INT32 VID_SetMode(INT32 modeNum) vid.height = windowedModes[modeNum].h; vid.modenum = modeNum; } - else if (modeNum == CUSTOMMODENUM && custom_width && custom_height) + else if (modeNum == CUSTOMMODENUM && customMode.w && customMode.h) { // at this point these values are assumed to be okay - vid.width = custom_width; - vid.height = custom_height; + vid.width = customMode.w; + vid.height = customMode.h; vid.modenum = modeNum; } -- 2.54.0 From 6915077e0f9331e810ec3462ee654d0426b96365 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 19:05:11 +0100 Subject: [PATCH 07/24] refresh the video menu list if our resolution list changes if you move the gamewindow to a different display, the video menu will now upadate to the new resolutions --- src/m_menu.c | 3 +-- src/m_menu.h | 2 ++ src/sdl/i_video.c | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 09a0c6350..6cb9137a3 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -282,7 +282,6 @@ static void M_SetupMultiHandler(INT32 choice); // Options // Split into multiple parts due to size -static void M_VideoModeMenu(INT32 choice); static void M_Setup1PControlsMenu(void); static void M_Setup2PControlsMenu(void); static void M_Setup3PControlsMenu(void); @@ -9441,7 +9440,7 @@ static void M_ResetControls(INT32 choice) static modedesc_t modedescs[MAXMODEDESCS]; -static void M_VideoModeMenu(INT32 choice) +void M_VideoModeMenu(INT32 choice) { INT32 i, j, vdup, nummodes, width, height; const char *desc; diff --git a/src/m_menu.h b/src/m_menu.h index de4f3b983..dc0cad1b9 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -231,6 +231,8 @@ extern menu_t *currentMenu; extern menu_t MainDef; extern menu_t SP_LoadDef; +extern menu_t OP_VideoModeDef; +void M_VideoModeMenu(INT32 choice); // Call upon joystick hotplug void M_SetupJoystickMenu(INT32 choice); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 3ccdd1ca3..dcd2a01e3 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -100,6 +100,7 @@ typedef struct static video_mode_t windowedModes[MAXWINMODES] = {{NULL, 0, 0}}; static video_mode_t customMode = {NULL, 0, 0}; +static const char *fallback_resolution_name = "Fallback"; rendermode_t rendermode = render_none; @@ -164,7 +165,6 @@ SDL_Window *window = NULL; SDL_Renderer *renderer = NULL; static SDL_Texture *texture = NULL; static SDL_bool havefocus = SDL_TRUE; -static const char *fallback_resolution_name = "Fallback"; static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); static void Impl_SetWindowIcon(void); @@ -1577,6 +1577,11 @@ static void I_FillScreenResolutionsList(void) } windowedModes[list_size].name = NULL; + + // be sure to update the video menu + if (menuactive && + currentMenu == &OP_VideoModeDef) + M_VideoModeMenu(0); } // return number of fullscreen + X11 modes -- 2.54.0 From 517723f9c1e081cdbc232d1ebc0f67b8a6dadd55 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 20:16:18 +0100 Subject: [PATCH 08/24] handle custom res differently + make VID_NumModes return actual vidmodes custom resolutions now will be put into the resolution list which means they are selectable from the menu --- src/i_video.h | 1 + src/screen.c | 4 +- src/sdl/i_video.c | 126 +++++++++++++++++++++++++--------------------- 3 files changed, 73 insertions(+), 58 deletions(-) diff --git a/src/i_video.h b/src/i_video.h index 852645c30..3a80bbf02 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -95,6 +95,7 @@ INT32 VID_SetMode(INT32 modenum); */ const char *VID_GetModeName(INT32 modenum); +void VID_RefreshModeList(void); void VID_PrepareModeList(void); /** \brief can video system do fullscreen diff --git a/src/screen.c b/src/screen.c index cae7d2479..b8e7ae35d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -42,8 +42,8 @@ INT32 setmodeneeded; // video mode change needed if > 0 (the mode number to set static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; //added : 03-02-98: default screen mode, as loaded/saved in config -consvar_t cv_scr_width = {"scr_width", "1280", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_scr_width = {"scr_width", "1280", CV_SAVE|CV_CALL, CV_Unsigned, VID_RefreshModeList, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE|CV_CALL, CV_Unsigned, VID_RefreshModeList, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; consvar_t cv_frameskip = {"frameskip", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index dcd2a01e3..e63b822e2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -86,10 +86,7 @@ // maximum number of windowed modes (see windowedModes[][]) #define MAXWINMODES (33) -// detect our custom resolution -#define CUSTOMMODENUM 9999 - -static void I_FillScreenResolutionsList(void); +static void I_FillScreenResolutionsList(boolean force); typedef struct { @@ -99,8 +96,8 @@ typedef struct } video_mode_t; static video_mode_t windowedModes[MAXWINMODES] = {{NULL, 0, 0}}; -static video_mode_t customMode = {NULL, 0, 0}; static const char *fallback_resolution_name = "Fallback"; +static int vid_nummodes; rendermode_t rendermode = render_none; @@ -494,7 +491,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) { // if we say moved our game window to a different screen // refetch our resolutions - I_FillScreenResolutionsList(); + I_FillScreenResolutionsList(false); #ifdef HWRENDER if (rendermode == render_opengl) @@ -1124,12 +1121,8 @@ static void VID_Command_ModeList_f(void) "Under opengl, fullscreen only supports native desktop resolution.\n" "Under software, the mode is stretched up to desktop resolution.\n"); - for (i = 0; i < MAXWINMODES; i++) + for (i = 0; i < vid_nummodes; i++) { - // not a valid mode - if (!windowedModes[i].w || !windowedModes[i].h) - continue; - CONS_Printf("%2d: %dx%d\n", i, windowedModes[i].w, windowedModes[i].h); } } @@ -1468,7 +1461,7 @@ static int cmp_resolutions (const void *a, const void *b) return (wa == wb) ? hb - ha : wb - wa; } -static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_index, int *list_size) +static void I_AppendResolution(SDL_DisplayMode *mode, int *list_size) { int i; char mode_name[256]; @@ -1483,9 +1476,6 @@ static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_in windowedModes[*list_size].w = mode->w; windowedModes[*list_size].h = mode->h; - if (mode->w == customMode.w && mode->h == customMode.h) - *current_resolution_index = *list_size; - (*list_size)++; } @@ -1494,12 +1484,12 @@ static void I_AppendResolution(SDL_DisplayMode *mode, int *current_resolution_in // Get all the supported screen resolutions // and fill the list with them // -static void I_FillScreenResolutionsList(void) +static void I_FillScreenResolutionsList(boolean force) { int currentDisplayIndex = -1; static int oldDisplayIndex = -1; SDL_DisplayMode mode; - int i, list_size, current_resolution_index; + int i, list_size; int count = 0; char desired_resolution[256]; @@ -1512,7 +1502,7 @@ static void I_FillScreenResolutionsList(void) } // didnt change screen, no need to redo the list - if (currentDisplayIndex == oldDisplayIndex) + if (!force && currentDisplayIndex == oldDisplayIndex) { return; } @@ -1523,7 +1513,6 @@ static void I_FillScreenResolutionsList(void) count = SDL_GetNumDisplayModes(currentDisplayIndex); list_size = 0; - current_resolution_index = -1; // on success, SDL_GetNumDisplayModes() always returns at least 1 if (count > 0) @@ -1548,35 +1537,47 @@ static void I_FillScreenResolutionsList(void) SDL_GetDisplayMode(currentDisplayIndex, i, &mode); } - I_AppendResolution(&mode, ¤t_resolution_index, &list_size); + I_AppendResolution(&mode, &list_size); } windowedModes[list_size].name = NULL; } - snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", customMode.w, customMode.h); + INT32 custom_w = cv_scr_width.value; + INT32 custom_h = cv_scr_height.value; + boolean needcustom = true; - // [FG] if the desired resolution not in the list, append it - if (current_resolution_index == -1) + // make sure those are valid + if ((custom_w >= BASEVIDWIDTH && custom_h >= BASEVIDHEIGHT) && + (custom_w <= MAXVIDWIDTH && custom_h <= MAXVIDHEIGHT)) { - windowedModes[list_size].name = strdup(desired_resolution); - list_size++; + for (i = 0; i < list_size; i++) + { + if (windowedModes[i].w == custom_w && windowedModes[i].h == custom_h) + { + needcustom = false; + break; + } + } + + // did not find mode from list, make custom resolution if the values somewhat make sense + if (needcustom) + { + snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_w, custom_h); + + // [FG] if the desired resolution not in the list, append it + windowedModes[list_size].name = strdup(desired_resolution); + windowedModes[list_size].w = custom_w; + windowedModes[list_size].h = custom_h; + list_size++; + } } // [FG] sort the list SDL_qsort(windowedModes, list_size, sizeof(*windowedModes), cmp_resolutions); - // [FG] find the desired resolution again - for (i = 0; i < list_size; i++) - { - if (!strcmp(desired_resolution, windowedModes[i].name)) - { - current_resolution_index = i; - break; - } - } - windowedModes[list_size].name = NULL; + vid_nummodes = list_size; // be sure to update the video menu if (menuactive && @@ -1587,7 +1588,8 @@ static void I_FillScreenResolutionsList(void) // return number of fullscreen + X11 modes INT32 VID_NumModes(void) { - return MAXWINMODES; + //return MAXWINMODES; + return vid_nummodes; } const char *VID_GetModeName(INT32 modeNum) @@ -1597,7 +1599,7 @@ const char *VID_GetModeName(INT32 modeNum) return fallback_resolution_name; } - if (modeNum > MAXWINMODES) + if (modeNum > vid_nummodes) return NULL; return windowedModes[modeNum].name; @@ -1607,7 +1609,7 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) { int i; - for (i = 0; i < MAXWINMODES; i++) + for (i = 0; i < vid_nummodes; i++) { if (windowedModes[i].w == w && windowedModes[i].h == h) { @@ -1615,20 +1617,20 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) } } - // did not find mode from list, make custom resolution if the values somewhat make sense - // opengl mode does not mind about max resolution defined in screen.h - // if not using opengl, check against the maximum as well - if ((w >= BASEVIDWIDTH && h >= BASEVIDHEIGHT) && - (rendermode == render_opengl || (w <= MAXVIDWIDTH && h <= MAXVIDHEIGHT))) - { - customMode.w = w; - customMode.h = h; - return CUSTOMMODENUM; - } - return -1; } +void VID_RefreshModeList(void) +{ + INT32 custom_w = cv_scr_width.value; + INT32 custom_h = cv_scr_height.value; + + // make sure those are valid + if ((custom_w >= BASEVIDWIDTH && custom_h >= BASEVIDHEIGHT) && + (custom_w <= MAXVIDWIDTH && custom_h <= MAXVIDHEIGHT)) + I_FillScreenResolutionsList(true); +} + void VID_PrepareModeList(void) { // Under SDL2, we just use the windowed modes list, and scale in windowed fullscreen. @@ -1660,18 +1662,30 @@ INT32 VID_SetMode(INT32 modeNum) { vid.recalc = true; - if (modeNum >= 0 && modeNum < MAXWINMODES) + if (modeNum >= 0 && modeNum < vid_nummodes) { vid.width = windowedModes[modeNum].w; vid.height = windowedModes[modeNum].h; vid.modenum = modeNum; } - else if (modeNum == CUSTOMMODENUM && customMode.w && customMode.h) + else { - // at this point these values are assumed to be okay - vid.width = customMode.w; - vid.height = customMode.h; - vid.modenum = modeNum; + // just set the desktop resolution as a fallback + SDL_DisplayMode mode; + SDL_GetWindowDisplayMode(window, &mode); + + if (mode.w >= 2048) + { + vid.width = 1920; + vid.height = 1200; + } + else + { + vid.width = mode.w; + vid.height = mode.h; + } + + vid.modenum = -1; } SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); @@ -1798,7 +1812,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) } // be sure to fill the resolution list the moment we have a window - I_FillScreenResolutionsList(); + I_FillScreenResolutionsList(false); return Impl_CreateContext(); } -- 2.54.0 From 48f2d0ff8319938e8deed2c4b0e11f1d25523aa4 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 20:21:21 +0100 Subject: [PATCH 09/24] make sure our custom res fits within MAXVIDMODES 33 are alot so this probably will never be the case (i hope) --- src/sdl/i_video.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index e63b822e2..4cd486f87 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1434,7 +1434,6 @@ void I_SetPalette(RGBA_t *palette) } } - // make sure the canonical resolutions are always available static const struct { const int w, h; @@ -1563,13 +1562,18 @@ static void I_FillScreenResolutionsList(boolean force) // did not find mode from list, make custom resolution if the values somewhat make sense if (needcustom) { - snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_w, custom_h); + if (list_size < MAXWINMODES) + { + snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_w, custom_h); - // [FG] if the desired resolution not in the list, append it - windowedModes[list_size].name = strdup(desired_resolution); - windowedModes[list_size].w = custom_w; - windowedModes[list_size].h = custom_h; - list_size++; + // [FG] if the desired resolution not in the list, append it + windowedModes[list_size].name = strdup(desired_resolution); + windowedModes[list_size].w = custom_w; + windowedModes[list_size].h = custom_h; + list_size++; + } + else + CONS_Alert(CONS_ERROR, "Could not set custom resolution!\n"); } } -- 2.54.0 From 44df85d6a4015f0a236a816f3de834f959c6d93d Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 20:41:14 +0100 Subject: [PATCH 10/24] reduce the scope of this --- src/sdl/i_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 4cd486f87..4df2c54d5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1544,12 +1544,13 @@ static void I_FillScreenResolutionsList(boolean force) INT32 custom_w = cv_scr_width.value; INT32 custom_h = cv_scr_height.value; - boolean needcustom = true; // make sure those are valid if ((custom_w >= BASEVIDWIDTH && custom_h >= BASEVIDHEIGHT) && (custom_w <= MAXVIDWIDTH && custom_h <= MAXVIDHEIGHT)) { + boolean needcustom = true; + for (i = 0; i < list_size; i++) { if (windowedModes[i].w == custom_w && windowedModes[i].h == custom_h) @@ -1702,7 +1703,6 @@ INT32 VID_SetMode(INT32 modeNum) return SDL_TRUE; } - static SDL_bool Impl_CreateContext(void) { // Renderer-specific stuff -- 2.54.0 From 20950b698fd29e3834b7bfa00fb44f8ce4e59912 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 20:25:57 +0100 Subject: [PATCH 11/24] make sure the default 320x200 mode exists --- src/sdl/i_video.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 4df2c54d5..d36fa0eea 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -90,14 +90,14 @@ static void I_FillScreenResolutionsList(boolean force); typedef struct { - char *name; + const char *name; INT32 w; INT32 h; } video_mode_t; -static video_mode_t windowedModes[MAXWINMODES] = {{NULL, 0, 0}}; +static video_mode_t windowedModes[MAXWINMODES]; static const char *fallback_resolution_name = "Fallback"; -static int vid_nummodes; +static int vid_nummodes = 0; rendermode_t rendermode = render_none; @@ -1721,6 +1721,9 @@ static SDL_bool Impl_CreateContext(void) SDL_GL_MakeCurrent(window, sdlglcontext); + // be sure to fill the resolution list the moment we have a window + I_FillScreenResolutionsList(false); + return SDL_TRUE; } #endif @@ -1763,6 +1766,9 @@ static SDL_bool Impl_CreateContext(void) SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); + // be sure to fill the resolution list the moment we have a window + I_FillScreenResolutionsList(false); + return SDL_TRUE; } @@ -1815,9 +1821,6 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) return SDL_FALSE; } - // be sure to fill the resolution list the moment we have a window - I_FillScreenResolutionsList(false); - return Impl_CreateContext(); } @@ -2020,6 +2023,12 @@ void I_StartupGraphics(void) // Fury: we do window initialization after GL setup to allow // SDL_GL_LoadLibrary to work well on Windows + // make sure the default mode exists + windowedModes[0].name = "320x200"; + windowedModes[0].w = 320; + windowedModes[0].h = 200; + vid_nummodes = 1; + // Create window VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); -- 2.54.0 From 23735121ff31e967c71b9acb614e6a228ff05809 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 20:38:03 +0100 Subject: [PATCH 12/24] raise MAXWINMODES to 128 YES WINDOWS THANKS VERY MUCH SUPER COOL OF YOU --- src/sdl/i_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index d36fa0eea..cb1d0010a 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -84,7 +84,7 @@ #endif // maximum number of windowed modes (see windowedModes[][]) -#define MAXWINMODES (33) +#define MAXWINMODES (128) static void I_FillScreenResolutionsList(boolean force); -- 2.54.0 From b6edc90553a49f933e6ba4f1509add8363819c48 Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 9 Nov 2025 22:20:47 +0100 Subject: [PATCH 13/24] mark resolutions listed above the current dektop resolution in red as they lead to visual errors in openglmode without fbo support --- src/i_video.h | 1 + src/m_menu.c | 32 ++++++++++++++++++++++++++++---- src/sdl/i_video.c | 13 +++++++++---- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/i_video.h b/src/i_video.h index 3a80bbf02..c18b5a765 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -140,6 +140,7 @@ void I_EndRead(void); UINT32 I_GetRefreshRate(void); +boolean I_CheckAboveDesktopRes(INT32 width, INT32 height); boolean I_CheckNativeRes(void); void I_SetBorderlessWindow(void); diff --git a/src/m_menu.c b/src/m_menu.c index 6cb9137a3..90aa7e866 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9501,6 +9501,9 @@ void M_VideoModeMenu(INT32 choice) if (SCR_IsAspectCorrect(width, height)) modedescs[vidm_nummodes].goodratio = 1; + if (I_CheckAboveDesktopRes(width, height)) + modedescs[vidm_nummodes].goodratio = 2; + vidm_nummodes++; } } @@ -9692,7 +9695,11 @@ static void M_DrawVideoMode(void) V_DrawString(row, col, highlightflags|MENUCAPS, modedescs[i].desc); // Show multiples of 320x200 as green. else - V_DrawString(row, col, ((modedescs[i].goodratio) ? recommendedflags : 0)|MENUCAPS, modedescs[i].desc); + { + const UINT8 goodratio = modedescs[i].goodratio; + const INT32 goodflag = ((goodratio == 1) ? recommendedflags : (goodratio == 2) ? warningflags : 0); + V_DrawString(row, col, goodflag|MENUCAPS, modedescs[i].desc); + } col += 8; if ((i % vidm_column_size) == (vidm_column_size-1)) @@ -9732,9 +9739,26 @@ static void M_DrawVideoMode(void) V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 138, recommendedflags|MENUCAPS, "Marked modes are recommended."); V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 146, - highlightflags|MENUCAPS, "Other modes may have visual errors."); - V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 158, - highlightflags|MENUCAPS, "Larger modes may have performance issues."); + warningflags|MENUCAPS, "Marked modes are above Desktop resolution"); + + if (rendermode == render_opengl) + { +#ifdef USE_FBO_OGL + if (!cv_glframebuffer.value) +#endif + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 154, + warningflags|MENUCAPS, "and will have visual errors in OpenGL mode."); + + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 166, + highlightflags|MENUCAPS, "Other modes may have visual errors."); + } + else + { + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 154, + highlightflags|MENUCAPS, "Other modes may have visual errors."); + V_DrawCenteredString(BASEVIDWIDTH/2, OP_VideoModeDef.y + 166, + highlightflags|MENUCAPS, "Larger modes may have performance issues."); + } } // Draw the cursor for the VidMode menu diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index cb1d0010a..6d3084c28 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -489,18 +489,18 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (windowmoved) { + I_CheckDesktopRes(); + // if we say moved our game window to a different screen // refetch our resolutions I_FillScreenResolutionsList(false); - #ifdef HWRENDER +#ifdef USE_FBO_OGL if (rendermode == render_opengl) { - I_CheckDesktopRes(); -#ifdef USE_FBO_OGL I_DownSample(); -#endif } +#endif #endif windowmoved = SDL_FALSE; } @@ -1177,6 +1177,11 @@ boolean I_CheckNativeRes(void) return (vid.width == desktopwidth && vid.height == desktopheight); } +boolean I_CheckAboveDesktopRes(INT32 width, INT32 height) +{ + return (width > desktopwidth || height > desktopheight); +} + #ifdef USE_FBO_OGL void RefreshOGLSDLSurface(void) -- 2.54.0 From fa66b879656933e8c00ba5990cce0baf09726a9b Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 04:16:11 +0100 Subject: [PATCH 14/24] cmp_resolutions: compare by numbers directly instead by comparing it with strings --- src/sdl/i_video.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 598b420fb..962b69da2 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1531,17 +1531,12 @@ static const struct { static const int num_canonicals = sizeof(canonicals)/sizeof(*canonicals); // [FG] sort resolutions by width first and height second -static int cmp_resolutions (const void *a, const void *b) +static int cmp_resolutions(const void *a, const void *b) { - const char *const *sa = (const char *const *) a; - const char *const *sb = (const char *const *) b; + const video_mode_t *ma = (const video_mode_t *) a; + const video_mode_t *mb = (const video_mode_t *) b; - int wa, wb, ha, hb; - - if (sscanf(*sa, "%dx%d", &wa, &ha) != 2) wa = ha = 0; - if (sscanf(*sb, "%dx%d", &wb, &hb) != 2) wb = hb = 0; - - return (wa == wb) ? hb - ha : wb - wa; + return (ma->w == mb->w) ? mb->h - ma->h : mb->w - ma->w; } static void I_AppendResolution(SDL_DisplayMode *mode, int *list_size) -- 2.54.0 From d6bbb2c1b3004d37aaa2f3e3c0d6f024e7901dea Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 04:22:29 +0100 Subject: [PATCH 15/24] use static buffer for windowedModes names no need to worry about memory management here :chaosleep: --- src/sdl/i_video.c | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 962b69da2..56a2d1eb5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -90,14 +90,14 @@ static void I_FillScreenResolutionsList(boolean force); typedef struct { - const char *name; + char name[10]; INT32 w; INT32 h; } video_mode_t; -static video_mode_t windowedModes[MAXWINMODES]; +static video_mode_t windowedModes[MAXWINMODES] = {{"320x200", 320, 200}}; // make sure the default mode exists static const char *fallback_resolution_name = "Fallback"; -static int vid_nummodes = 0; +static int vid_nummodes = 1; rendermode_t rendermode = render_none; @@ -1542,15 +1542,15 @@ static int cmp_resolutions(const void *a, const void *b) static void I_AppendResolution(SDL_DisplayMode *mode, int *list_size) { int i; - char mode_name[256]; - - snprintf(mode_name, sizeof(mode_name), "%dx%d", mode->w, mode->h); for (i = 0; i < *list_size; i++) - if (!strcmp(mode_name, windowedModes[i].name)) + if (windowedModes[i].w == mode->w + && windowedModes[i].h == mode->h) return; - windowedModes[*list_size].name = strdup(mode_name); + snprintf(windowedModes[*list_size].name, + sizeof(windowedModes[*list_size].name), + "%dx%d", mode->w, mode->h); windowedModes[*list_size].w = mode->w; windowedModes[*list_size].h = mode->h; @@ -1567,9 +1567,9 @@ static void I_FillScreenResolutionsList(boolean force) int currentDisplayIndex = -1; static int oldDisplayIndex = -1; SDL_DisplayMode mode; - int i, list_size; + int i = 0, list_size = 0; int count = 0; - char desired_resolution[256]; + char custom_resolution[10]; currentDisplayIndex = SDL_GetWindowDisplayIndex(window); @@ -1618,7 +1618,7 @@ static void I_FillScreenResolutionsList(boolean force) I_AppendResolution(&mode, &list_size); } - windowedModes[list_size].name = NULL; + windowedModes[list_size].name[0] = '\0'; } INT32 custom_w = cv_scr_width.value; @@ -1644,10 +1644,12 @@ static void I_FillScreenResolutionsList(boolean force) { if (list_size < MAXWINMODES) { - snprintf(desired_resolution, sizeof(desired_resolution), "%dx%d", custom_w, custom_h); + snprintf(custom_resolution, sizeof(custom_resolution), "%dx%d", custom_w, custom_h); // [FG] if the desired resolution not in the list, append it - windowedModes[list_size].name = strdup(desired_resolution); + snprintf(windowedModes[list_size].name, + sizeof(windowedModes[list_size].name), + "%dx%d", custom_w, custom_h); windowedModes[list_size].w = custom_w; windowedModes[list_size].h = custom_h; list_size++; @@ -1660,7 +1662,7 @@ static void I_FillScreenResolutionsList(boolean force) // [FG] sort the list SDL_qsort(windowedModes, list_size, sizeof(*windowedModes), cmp_resolutions); - windowedModes[list_size].name = NULL; + windowedModes[list_size].name[0] = '\0'; vid_nummodes = list_size; // be sure to update the video menu @@ -2104,12 +2106,6 @@ void I_StartupGraphics(void) // Fury: we do window initialization after GL setup to allow // SDL_GL_LoadLibrary to work well on Windows - // make sure the default mode exists - windowedModes[0].name = "320x200"; - windowedModes[0].w = 320; - windowedModes[0].h = 200; - vid_nummodes = 1; - // Create window VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); -- 2.54.0 From 6fd14f0a803d56ab54e397277138f4eddc310997 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 04:24:28 +0100 Subject: [PATCH 16/24] M_VideoModeMenu: remove old video mode dupe check --- src/m_menu.c | 62 ++++++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 45 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 112c481a4..813db7459 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9416,7 +9416,7 @@ static modedesc_t modedescs[MAXMODEDESCS]; void M_VideoModeMenu(INT32 choice) { - INT32 i, j, vdup, nummodes, width, height; + INT32 i, nummodes, width, height; const char *desc; (void)choice; @@ -9430,57 +9430,30 @@ void M_VideoModeMenu(INT32 choice) nummodes = VID_NumModes(); // DOS does not skip mode 0, because mode 0 is ALWAYS present - i = 0; - for (; i < nummodes && vidm_nummodes < MAXMODEDESCS; i++) + for (i = 0; i < nummodes && vidm_nummodes < MAXMODEDESCS; i++) { desc = VID_GetModeName(i); - if (desc) - { - vdup = 0; - // when a resolution exists both under VGA and VESA, keep the - // VESA mode, which is always a higher modenum - for (j = 0; j < vidm_nummodes; j++) - { - if (fastcmp(modedescs[j].desc, desc)) - { - // mode(0): 320x200 is always standard VGA, not vesa - if (modedescs[j].modenum) - { - modedescs[j].modenum = i; - vdup = 1; + if (!desc) + continue; - if (i == vid.modenum) - vidm_selected = j; - } - else - vdup = 1; + modedescs[vidm_nummodes].modenum = i; + modedescs[vidm_nummodes].desc = desc; - break; - } - } + if (i == vid.modenum) + vidm_selected = vidm_nummodes; - if (!vdup) - { - modedescs[vidm_nummodes].modenum = i; - modedescs[vidm_nummodes].desc = desc; + // Pull out the width and height + sscanf(desc, "%u%*c%u", &width, &height); - if (i == vid.modenum) - vidm_selected = vidm_nummodes; + // Show resolutions above desktop res as red. + if (I_CheckAboveDesktopRes(width, height)) + modedescs[vidm_nummodes].goodratio = 2; + // Show multiples of 320x200 as green. + else if (SCR_IsAspectCorrect(width, height)) + modedescs[vidm_nummodes].goodratio = 1; - // Pull out the width and height - sscanf(desc, "%u%*c%u", &width, &height); - - // Show multiples of 320x200 as green. - if (SCR_IsAspectCorrect(width, height)) - modedescs[vidm_nummodes].goodratio = 1; - - if (I_CheckAboveDesktopRes(width, height)) - modedescs[vidm_nummodes].goodratio = 2; - - vidm_nummodes++; - } - } + vidm_nummodes++; } vidm_column_size = (vidm_nummodes+2) / 3; @@ -9697,7 +9670,6 @@ static void M_DrawVideoMode(void) va("Wait %d second%s", testtime, (testtime > 1) ? "s" : "")); M_CentreText(OP_VideoModeDef.y + 158, "or press ESC to return"); - } else { -- 2.54.0 From d074f375cad6fabd335562a75344fc51b391659f Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 04:24:49 +0100 Subject: [PATCH 17/24] M_VideoModeMenu: make sure red marked modes take precedence --- src/m_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/m_menu.c b/src/m_menu.c index 813db7459..4c6c5b97c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9644,7 +9644,7 @@ static void M_DrawVideoMode(void) else { const UINT8 goodratio = modedescs[i].goodratio; - const INT32 goodflag = ((goodratio == 1) ? recommendedflags : (goodratio == 2) ? warningflags : 0); + const INT32 goodflag = ((goodratio == 2) ? warningflags : (goodratio == 1) ? recommendedflags : 0); V_DrawString(row, col, goodflag|MENUCAPS, modedescs[i].desc); } -- 2.54.0 From b5bb2b42bfad9d52a669baddf2e69ef9a4e02c8e Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 04:46:21 +0100 Subject: [PATCH 18/24] I_FillScreenResolutionsList: shrink list if it is too large we check against MAXMODEDESCS, which is the maximum of modes the videomode can list just in case we really get a display with a fuckton of resolutions, which most likely wont ever be the case though this just removes the smallest modes from the list (accounting for the canonicals), to keep things simple --- src/m_menu.c | 3 --- src/m_menu.h | 3 +++ src/sdl/i_video.c | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/m_menu.c b/src/m_menu.c index 4c6c5b97c..86553c7e9 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -9409,9 +9409,6 @@ static void M_ResetControls(INT32 choice) // =============== //added : 30-01-98: -#define MAXCOLUMNMODES 12 //max modes displayed in one column -#define MAXMODEDESCS (MAXCOLUMNMODES*3) - static modedesc_t modedescs[MAXMODEDESCS]; void M_VideoModeMenu(INT32 choice) diff --git a/src/m_menu.h b/src/m_menu.h index 2e7cedbbb..5bc957541 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -221,6 +221,9 @@ extern menu_t *currentMenu; extern menu_t MainDef; extern menu_t SP_LoadDef; + +#define MAXCOLUMNMODES 12 //max modes displayed in one column +#define MAXMODEDESCS (MAXCOLUMNMODES*3) extern menu_t OP_VideoModeDef; void M_VideoModeMenu(INT32 choice); diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 56a2d1eb5..905770951 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1557,6 +1557,18 @@ static void I_AppendResolution(SDL_DisplayMode *mode, int *list_size) (*list_size)++; } +// small helper to check if a video mode is canonical +static boolean IsModeCanonical(int w, int h) +{ + for (int i = 0; i < num_canonicals; i++) + { + if (canonicals[i].w == w && canonicals[i].h == h) + return true; + } + + return false; +} + // // I_FillScreenResolutionsList // Get all the supported screen resolutions @@ -1603,10 +1615,6 @@ static void I_FillScreenResolutionsList(boolean force) // make sure the canonical resolutions are always available if (i > count - 1) { - // no hard-coded resolutions for mode-changing fullscreen - //if (exclusive_fullscreen) - //continue; - mode.w = canonicals[i - count].w; mode.h = canonicals[i - count].h; } @@ -1662,6 +1670,30 @@ static void I_FillScreenResolutionsList(boolean force) // [FG] sort the list SDL_qsort(windowedModes, list_size, sizeof(*windowedModes), cmp_resolutions); + // if we have more video modes than we can list + // try to shrink the list, lowest resolutions first + // whilst keeping the canonicals + if (list_size > MAXMODEDESCS) + { + // list is sorted from largest to smallest, so start at the end + for (i = list_size - 1; i >= 0 && list_size > MAXMODEDESCS; i--) + { + if (IsModeCanonical(windowedModes[i].w, windowedModes[i].h)) + continue; + + // Should we like, instead prioritize checking for non aspect correct resolutions to remove? + + // we gotta shift everything + // due to canonicals we cant just shrink the list + for (int k = i; k < list_size - 1; k++) + { + windowedModes[k] = windowedModes[k + 1]; + } + + list_size--; + } + } + windowedModes[list_size].name[0] = '\0'; vid_nummodes = list_size; -- 2.54.0 From c312380944605193cd5ff9ff8e047b5564384723 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 18 Nov 2025 05:08:46 +0100 Subject: [PATCH 19/24] check if our desired screen res already is in the videomode list before deciding to rebuild the whole list when changing the resolution cvars --- src/sdl/i_video.c | 77 ++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 905770951..5a38114bc 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1569,6 +1569,29 @@ static boolean IsModeCanonical(int w, int h) return false; } +// check if our desired resolution already is in the videomode list +static int IsCustomResolutionInList(int list_size) +{ + INT32 custom_w = cv_scr_width.value; + INT32 custom_h = cv_scr_height.value; + + // invalid resolution + // dont even attempt to add it + if (custom_w < BASEVIDWIDTH || custom_w > MAXVIDWIDTH + || custom_h < BASEVIDHEIGHT || custom_h > MAXVIDHEIGHT) + return -1; + + for (int i = 0; i < list_size; i++) + { + if (windowedModes[i].w == custom_w && windowedModes[i].h == custom_h) + { + return 1; + } + } + + return 0; +} + // // I_FillScreenResolutionsList // Get all the supported screen resolutions @@ -1629,43 +1652,28 @@ static void I_FillScreenResolutionsList(boolean force) windowedModes[list_size].name[0] = '\0'; } - INT32 custom_w = cv_scr_width.value; - INT32 custom_h = cv_scr_height.value; + const int customresinlist = IsCustomResolutionInList(list_size); - // make sure those are valid - if ((custom_w >= BASEVIDWIDTH && custom_h >= BASEVIDHEIGHT) && - (custom_w <= MAXVIDWIDTH && custom_h <= MAXVIDHEIGHT)) + if (customresinlist == 0) { - boolean needcustom = true; - - for (i = 0; i < list_size; i++) - { - if (windowedModes[i].w == custom_w && windowedModes[i].h == custom_h) - { - needcustom = false; - break; - } - } - // did not find mode from list, make custom resolution if the values somewhat make sense - if (needcustom) + if (list_size < MAXWINMODES) { - if (list_size < MAXWINMODES) - { - snprintf(custom_resolution, sizeof(custom_resolution), "%dx%d", custom_w, custom_h); + snprintf(custom_resolution, sizeof(custom_resolution), "%dx%d", cv_scr_width.value, cv_scr_height.value); - // [FG] if the desired resolution not in the list, append it - snprintf(windowedModes[list_size].name, - sizeof(windowedModes[list_size].name), - "%dx%d", custom_w, custom_h); - windowedModes[list_size].w = custom_w; - windowedModes[list_size].h = custom_h; - list_size++; - } - else - CONS_Alert(CONS_ERROR, "Could not set custom resolution!\n"); + // [FG] if the desired resolution not in the list, append it + snprintf(windowedModes[list_size].name, + sizeof(windowedModes[list_size].name), + "%dx%d", cv_scr_width.value, cv_scr_height.value); + windowedModes[list_size].w = cv_scr_width.value; + windowedModes[list_size].h = cv_scr_height.value; + list_size++; } + else + CONS_Alert(CONS_ERROR, "Could not set custom resolution!\n"); } + else if (customresinlist == -1) + CONS_Alert(CONS_ERROR, "Could not set custom resolution!\n"); // [FG] sort the list SDL_qsort(windowedModes, list_size, sizeof(*windowedModes), cmp_resolutions); @@ -1706,7 +1714,6 @@ static void I_FillScreenResolutionsList(boolean force) // return number of fullscreen + X11 modes INT32 VID_NumModes(void) { - //return MAXWINMODES; return vid_nummodes; } @@ -1740,12 +1747,8 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) void VID_RefreshModeList(void) { - INT32 custom_w = cv_scr_width.value; - INT32 custom_h = cv_scr_height.value; - - // make sure those are valid - if ((custom_w >= BASEVIDWIDTH && custom_h >= BASEVIDHEIGHT) && - (custom_w <= MAXVIDWIDTH && custom_h <= MAXVIDHEIGHT)) + // check if we even need to rebuild the list + if (IsCustomResolutionInList(vid_nummodes) == 0) I_FillScreenResolutionsList(true); } -- 2.54.0 From 1fb6c6309795f78fd837d25ccb2fda03cf6456f5 Mon Sep 17 00:00:00 2001 From: Alug Date: Fri, 21 Nov 2025 14:44:49 +0100 Subject: [PATCH 20/24] fix dedi compile --- src/dedicated/i_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c index 8227233a8..4ade52c5f 100644 --- a/src/dedicated/i_video.c +++ b/src/dedicated/i_video.c @@ -122,6 +122,10 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h) return -1; } +void VID_RefreshModeList(void) +{ +} + void VID_PrepareModeList(void) { } -- 2.54.0 From 8a8cbffd128493647aa90c713b59155819a4a2eb Mon Sep 17 00:00:00 2001 From: Alug Date: Sun, 23 Nov 2025 23:21:37 +0100 Subject: [PATCH 21/24] I_CheckDesktopRes: use SDL_GetCurrentDisplayMode instead of SDL_GetDesktopDisplayMode, as the former only returns the display mode from when the window was created, which might not reflect the actual current desktop mode. Maybe fixes some resolutions being incorrectly reported asa having visual issues --- src/sdl/i_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 5a38114bc..b5ce0d4d5 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1241,7 +1241,7 @@ static void I_CheckDesktopRes(void) return; } - if (SDL_GetDesktopDisplayMode(currentDisplayIndex, &curmode) != 0) + if (SDL_GetCurrentDisplayMode(currentDisplayIndex, &curmode) != 0) { return; } -- 2.54.0 From a05413d925f1df856c4e27b64482c8beb78f884f Mon Sep 17 00:00:00 2001 From: Alug Date: Mon, 24 Nov 2025 20:49:09 +0100 Subject: [PATCH 22/24] fix erronous "Could not set custom resolution" warning on startup the cvars may have not been initialised yet to anything just return -2 and ignore --- src/sdl/i_video.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index b5ce0d4d5..ef7f439b0 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -1575,6 +1575,10 @@ static int IsCustomResolutionInList(int list_size) INT32 custom_w = cv_scr_width.value; INT32 custom_h = cv_scr_height.value; + // startup + if (!custom_w || !custom_h) + return -2; + // invalid resolution // dont even attempt to add it if (custom_w < BASEVIDWIDTH || custom_w > MAXVIDWIDTH -- 2.54.0 From 9bea6eddbdbfdcc06e4c16c4ce9d2f9491759663 Mon Sep 17 00:00:00 2001 From: Alug Date: Sat, 27 Dec 2025 15:09:30 +0100 Subject: [PATCH 23/24] fix dedi build missing I_CheckAboveDesktopRes --- src/dedicated/i_video.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/dedicated/i_video.c b/src/dedicated/i_video.c index d253a7572..062c459ed 100644 --- a/src/dedicated/i_video.c +++ b/src/dedicated/i_video.c @@ -129,6 +129,13 @@ INT32 VID_SetMode(INT32 modeNum) return true; } +boolean I_CheckAboveDesktopRes(INT32 width, INT32 height) +{ + (void)width; + (void)height; + return false; +} + void I_StartupGraphics(void) { } -- 2.54.0 From 467ecf822448bf7b39e3f8222d6de0fdc68de297 Mon Sep 17 00:00:00 2001 From: Alug Date: Tue, 3 Feb 2026 22:02:01 +0100 Subject: [PATCH 24/24] fix adding bogus resolutions into the resolution list when setting a new defaultres CV_SetValue will call the callbacks each, which means when it sets the width, the height cvar will not be updated yet, which most definitely will not be in the modelist, so it will add it regardless --- src/screen.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/screen.c b/src/screen.c index 5f52b8d97..a0e884bc1 100644 --- a/src/screen.c +++ b/src/screen.c @@ -315,8 +315,9 @@ void SCR_CheckDefaultMode(void) void SCR_SetDefaultMode(void) { // remember the default screen size - CV_SetValue(&cv_scr_width, vid.width); - CV_SetValue(&cv_scr_height, vid.height); + CV_StealthSetValue(&cv_scr_width, vid.width); + CV_StealthSetValue(&cv_scr_height, vid.height); + VID_RefreshModeList(); // probably not needed but justin käs } // Change fullscreen on/off according to cv_fullscreen -- 2.54.0