shithub: choc

Download patch

ref: 65ed2a3208db93eef0f25f5d9c046c77cb7eb980
parent: aff2bd33f46df242be24e9f75e9ef1a2a6d9184f
author: Simon Howard <[email protected]>
date: Mon Feb 4 17:43:11 EST 2008

Update chocolate-setup to the new screen mode config system.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 1042

--- a/setup/configfile.c
+++ b/setup/configfile.c
@@ -254,7 +254,8 @@
     {"fullscreen",                  &fullscreen, DEFAULT_INT, 0, 0},
     {"aspect_ratio_correct",        &aspect_ratio_correct, DEFAULT_INT, 0, 0},
     {"startup_delay",               &startup_delay, DEFAULT_INT, 0, 0},
-    {"screenmultiply",              &screenmultiply, DEFAULT_INT, 0, 0},
+    {"screen_width",                &screen_width, DEFAULT_INT, 0, 0},
+    {"screen_height",               &screen_height, DEFAULT_INT, 0, 0},
     {"grabmouse",                   &grabmouse, DEFAULT_INT, 0, 0},
     {"novert",                      &novert, DEFAULT_INT, 0, 0},
     {"mouse_acceleration",          &mouse_acceleration, DEFAULT_FLOAT, 0, 0},
--- a/setup/display.c
+++ b/setup/display.c
@@ -27,44 +27,50 @@
 
 typedef struct 
 {
-    char *description;
-    char *description_4_3;
-    int screenmultiply;
-    txt_radiobutton_t *widget;
-} vidmode_t;
+    int w, h;
+} screen_mode_t;
 
-enum
-{
-    RATIO_CORRECT_NONE,
-    RATIO_CORRECT_LETTERBOX,
-    RATIO_CORRECT_STRETCH,
-    NUM_RATIO_CORRECT,
-};
+// List of aspect ratio-uncorrected modes
 
-static vidmode_t modes[] = 
+static screen_mode_t screen_modes_unscaled[] = 
 {
-    { "320x200",  "320x240",  1, NULL },
-    { "960x600",  "960x720",  3, NULL },
-    { "640x400",  "640x480",  2, NULL },
-    { "1280x800", "1280x960", 4, NULL },
-    { "1600x1000", "1600x1200", 5, NULL },
-    { NULL,       NULL,       0, NULL },
+    { 320,  200 },
+    { 640,  400 },
+    { 960,  600 },
+    { 1280, 800 },
+    { 1600, 1000 },
+    { 0, 0},
 };
 
-static char *aspect_ratio_strings[] =
+// List of aspect ratio-corrected modes
+
+static screen_mode_t screen_modes_scaled[] = 
 {
-    "Disabled",
-    "Letterbox mode",
-    "Stretch to 4:3",
+    { 256,  200 },
+    { 320,  240 },
+    { 512,  400 },
+    { 640,  480 },
+    { 800,  600 },
+    { 960,  720 },
+    { 1024, 800 },
+    { 1280, 960 },
+    { 1280, 1000 },
+    { 1600, 1200 },
+    { 0, 0},
 };
 
+// List of fullscreen modes generated at runtime
+
+static screen_mode_t *screen_modes_fullscreen = NULL;
+
 static int vidmode = 0;
 
 char *video_driver = "";
 int autoadjust_video_settings = 1;
-int aspect_ratio_correct = RATIO_CORRECT_NONE;
+int aspect_ratio_correct = 1;
 int fullscreen = 1;
-int screenmultiply = 1;
+int screen_width = 320;
+int screen_height = 200;
 int startup_delay = 0;
 int show_endoom = 1;
 
@@ -103,81 +109,182 @@
 
 #endif
 
-// Given the video settings (fullscreen, screenmultiply, etc), find the
-// current video mode
+static void ModeSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(mode))
+{
+    TXT_CAST_ARG(screen_mode_t, mode);
 
-static void SetCurrentMode(void)
+    screen_width = mode->w;
+    screen_height = mode->h;
+}
+
+static int GoodFullscreenMode(screen_mode_t *mode)
 {
-    int i;
+    int w, h;
 
-    vidmode = 0;
+    w = mode->w;
+    h = mode->h;
 
-    for (i=0; modes[i].description != NULL; ++i)
+    // 320x200 and 640x400 are always good
+
+    if ((w == 320 && h == 200) || (w == 640 && h == 400))
     {
-        if (screenmultiply == modes[i].screenmultiply)
-        {
-            vidmode = i;
-            break;
-        }
+        return 1;
     }
+
+    return w >= 640 && h >= 480;
 }
 
-static void ModeSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(mode))
+// Build screen_modes_fullscreen
+
+static void BuildFullscreenModesList(void)
 {
-    TXT_CAST_ARG(vidmode_t, mode);
+    SDL_Rect **modes;
+    screen_mode_t *m1;
+    screen_mode_t *m2;
+    screen_mode_t m;
+    int num_modes;
+    int i;
 
-    screenmultiply = mode->screenmultiply;
+    if (screen_modes_fullscreen != NULL)
+    {
+        return;
+    }
+
+    // Get a list of fullscreen modes and find out how many
+    // modes are in the list.
+
+    modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
+
+    for (num_modes=0; modes[num_modes] != NULL; ++num_modes);
+
+    // Build the screen_modes_fullscreen array
+
+    screen_modes_fullscreen = malloc(sizeof(screen_mode_t) * (num_modes + 1));
+
+    for (i=0; i<num_modes; ++i)
+    {
+        screen_modes_fullscreen[i].w = modes[i]->w;
+        screen_modes_fullscreen[i].h = modes[i]->h;
+    }
+
+    screen_modes_fullscreen[i].w = 0;
+    screen_modes_fullscreen[i].h = 0;
+
+    // Reverse the order of the modes list (smallest modes first)
+
+    for (i=0; i<num_modes / 2; ++i)
+    {
+        m1 = &screen_modes_fullscreen[i];
+        m2 = &screen_modes_fullscreen[num_modes - 1 - i];
+
+        memcpy(&m, m1, sizeof(screen_mode_t));
+        memcpy(m1, m2, sizeof(screen_mode_t));
+        memcpy(m2, &m, sizeof(screen_mode_t));
+    }
 }
 
-static void UpdateModes(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused))
+static int FindBestMode(screen_mode_t *modes)
 {
     int i;
+    int best_mode;
+    int best_mode_diff;
+    int diff;
 
-    for (i=0; modes[i].description != NULL; ++i)
+    best_mode = -1;
+    best_mode_diff = 0;
+
+    for (i=0; modes[i].w != 0; ++i)
     {
-        if (aspect_ratio_correct == RATIO_CORRECT_NONE)
+        diff = (screen_width - modes[i].w) * (screen_width - modes[i].w) 
+             + (screen_height - modes[i].h) * (screen_height - modes[i].h);
+
+        if (best_mode == -1 || diff < best_mode_diff)
         {
-            TXT_SetRadioButtonLabel(modes[i].widget, modes[i].description);
+            best_mode_diff = diff;
+            best_mode = i;
         }
-        else
+    }
+
+    return best_mode;
+}
+
+static void GenerateModesTable(TXT_UNCAST_ARG(widget),
+                               TXT_UNCAST_ARG(modes_table))
+{
+    TXT_CAST_ARG(txt_table_t, modes_table);
+    char buf[15];
+    screen_mode_t *modes;
+    txt_radiobutton_t *rbutton;
+    int i;
+
+    // Pick which modes list to use
+
+    if (fullscreen)
+    {
+        BuildFullscreenModesList();
+        modes = screen_modes_fullscreen;
+    }
+    else if (aspect_ratio_correct) 
+    {
+        modes = screen_modes_scaled;
+    }
+    else
+    {
+        modes = screen_modes_unscaled;
+    }
+
+    // Build the table
+ 
+    TXT_ClearTable(modes_table);
+    TXT_SetColumnWidths(modes_table, 14, 14, 14);
+
+    for (i=0; modes[i].w != 0; ++i) 
+    {
+        // Skip bad fullscreen modes
+
+        if (fullscreen && !GoodFullscreenMode(&modes[i]))
         {
-            TXT_SetRadioButtonLabel(modes[i].widget, modes[i].description_4_3);
+            continue;
         }
+
+        sprintf(buf, "%ix%i", modes[i].w, modes[i].h);
+        rbutton = TXT_NewRadioButton(buf, &vidmode, i);
+        TXT_AddWidget(modes_table, rbutton);
+        TXT_SignalConnect(rbutton, "selected", ModeSelected, &modes[i]);
     }
+
+    // Find the nearest mode in the list that matches the current
+    // settings
+
+    vidmode = FindBestMode(modes);
 }
 
 void ConfigDisplay(void)
 {
     txt_window_t *window;
-    txt_table_t *ar_table;
     txt_table_t *modes_table;
-    txt_radiobutton_t *rbutton;
-    txt_dropdown_list_t *ar_dropdown;
-    int i;
+    txt_checkbox_t *fs_checkbox;
+    txt_checkbox_t *ar_checkbox;
 
-    // Find the current mode
-
-    SetCurrentMode();
-
     // Open the window
     
     window = TXT_NewWindow("Display Configuration");
 
     TXT_AddWidgets(window, 
-                   TXT_NewCheckBox("Fullscreen", &fullscreen),
-                   ar_table = TXT_NewTable(2),
-                   TXT_NewSeparator("Screen mode"),
-                   modes_table = TXT_NewTable(2),
-                   TXT_NewSeparator("Misc."),
-                   TXT_NewCheckBox("Show ENDOOM screen", &show_endoom),
+                   fs_checkbox = TXT_NewCheckBox("Fullscreen", &fullscreen),
+                   ar_checkbox = TXT_NewCheckBox("Correct aspect ratio",
+                                                 &aspect_ratio_correct),
                    NULL);
 
-    TXT_SetColumnWidths(ar_table, 25, 0);
-
 #ifdef _WIN32
     {
+        txt_table_t *driver_table;
         txt_dropdown_list_t *driver_list;
 
+        driver_table = TXT_NewTable(2);
+
+        TXT_SetColumnWidths(driver_table, 25, 0);
+
         driver_list = TXT_NewDropdownList(&win32_video_driver,
                                           win32_video_drivers,
                                           2);
@@ -185,32 +292,25 @@
         TXT_SignalConnect(driver_list, "changed", UpdateVideoDriver, NULL);
         SetWin32VideoDriver();
 
-        TXT_AddWidgets(ar_table,
+        TXT_AddWidgets(driver_table,
                        TXT_NewLabel("Video driver"),
                        driver_list,
                        NULL);
+
+        TXT_AddWidget(window, driver_table);
     }
 #endif
 
-    TXT_AddWidgets(ar_table,
-                   TXT_NewLabel("Aspect ratio correction"),
-                   ar_dropdown = TXT_NewDropdownList(&aspect_ratio_correct,
-                                                     aspect_ratio_strings,
-                                                     NUM_RATIO_CORRECT),
+    TXT_AddWidgets(window,
+                   TXT_NewSeparator("Screen mode"),
+                   modes_table = TXT_NewTable(3),
+                   TXT_NewSeparator("Misc."),
+                   TXT_NewCheckBox("Show ENDOOM screen", &show_endoom),
                    NULL);
 
-    TXT_SignalConnect(ar_dropdown, "changed", UpdateModes, NULL);
+    TXT_SignalConnect(fs_checkbox, "changed", GenerateModesTable, modes_table);
+    TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table);
 
-    TXT_SetColumnWidths(modes_table, 14, 14);
-
-    for (i=0; modes[i].description != NULL; ++i)
-    {
-        rbutton = TXT_NewRadioButton(modes[i].description, &vidmode, i);
-        modes[i].widget = rbutton;
-        TXT_AddWidget(modes_table, rbutton);
-        TXT_SignalConnect(rbutton, "selected", ModeSelected, &modes[i]);
-    }
-
-    UpdateModes(NULL, NULL);
+    GenerateModesTable(NULL, modes_table);
 }
 
--- a/setup/display.h
+++ b/setup/display.h
@@ -25,7 +25,7 @@
 extern int autoadjust_video_settings;
 extern int aspect_ratio_correct;
 extern int fullscreen;
-extern int screenmultiply;
+extern int screen_width, screen_height;
 extern int startup_delay;
 extern int show_endoom;
 extern char *video_driver;
--- a/textscreen/txt_table.c
+++ b/textscreen/txt_table.c
@@ -33,14 +33,18 @@
 #include "txt_strut.h"
 #include "txt_table.h"
 
-static void TXT_TableDestructor(TXT_UNCAST_ARG(table))
+// Remove all entries from a table
+
+void TXT_ClearTable(TXT_UNCAST_ARG(table))
 {
     TXT_CAST_ARG(txt_table_t, table);
     int i;
 
     // Free all widgets
+    // Skip over the first (num_columns) widgets in the array, as these
+    // are the column struts used to control column width
 
-    for (i=0; i<table->num_widgets; ++i)
+    for (i=table->columns; i<table->num_widgets; ++i)
     {
         if (table->widgets[i] != NULL)
         {
@@ -48,9 +52,16 @@
         }
     }
     
-    // Free table resources
+    // Shrink the table to just the column strut widgets
 
-    free(table->widgets);
+    table->num_widgets = table->columns;
+}
+
+static void TXT_TableDestructor(TXT_UNCAST_ARG(table))
+{
+    TXT_CAST_ARG(txt_table_t, table);
+
+    TXT_ClearTable(table);
 }
 
 static int TableRows(txt_table_t *table)
--- a/textscreen/txt_table.h
+++ b/textscreen/txt_table.h
@@ -53,6 +53,7 @@
 void TXT_AddWidgets(TXT_UNCAST_ARG(table), ...);
 int TXT_SelectWidget(TXT_UNCAST_ARG(table), TXT_UNCAST_ARG(widget));
 void TXT_SetColumnWidths(TXT_UNCAST_ARG(table), ...);
+void TXT_ClearTable(TXT_UNCAST_ARG(table));
 
 #endif /* #ifndef TXT_TABLE_T */