diff options
Diffstat (limited to 'src/setup/display.c')
-rw-r--r-- | src/setup/display.c | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/src/setup/display.c b/src/setup/display.c new file mode 100644 index 00000000..9fd0963b --- /dev/null +++ b/src/setup/display.c @@ -0,0 +1,490 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2006 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// + +#include <stdlib.h> +#include <string.h> + +#ifdef _WIN32_WCE +#include "libc_wince.h" +#endif + +#include "textscreen.h" +#include "m_config.h" +#include "mode.h" + +#include "display.h" + +typedef struct +{ + int w, h; +} screen_mode_t; + +// List of aspect ratio-uncorrected modes + +static screen_mode_t screen_modes_unscaled[] = +{ + { 320, 200 }, + { 640, 400 }, + { 960, 600 }, + { 1280, 800 }, + { 1600, 1000 }, + { 0, 0}, +}; + +// List of aspect ratio-corrected modes + +static screen_mode_t screen_modes_scaled[] = +{ + { 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; + +static char *video_driver = ""; +static int autoadjust_video_settings = 1; +static int aspect_ratio_correct = 1; +static int fullscreen = 1; +static int screen_width = 320; +static int screen_height = 200; +static int startup_delay = 1000; +static int graphical_startup = 1; +static int show_endoom = 1; +static int usegamma = 0; + +// These are the last screen width/height values that were chosen by the +// user. These are used when finding the "nearest" mode, so when +// changing the fullscreen / aspect ratio options, the setting does not +// jump around. + +static int selected_screen_width = 0, selected_screen_height; + +static int system_video_env_set; + +// Set the SDL_VIDEODRIVER environment variable + +void SetDisplayDriver(void) +{ + static int first_time = 1; + + if (first_time) + { + system_video_env_set = getenv("SDL_VIDEODRIVER") != NULL; + + first_time = 0; + } + + // Don't override the command line environment, if it has been set. + + if (system_video_env_set) + { + return; + } + + // Use the value from the configuration file, if it has been set. + + if (strcmp(video_driver, "") != 0) + { + char *env_string; + + env_string = malloc(strlen(video_driver) + 30); + sprintf(env_string, "SDL_VIDEODRIVER=%s", video_driver); + putenv(env_string); + free(env_string); + } + else + { +#if defined(_WIN32) && !defined(_WIN32_WCE) + // On Windows, use DirectX over windib by default. + + putenv("SDL_VIDEODRIVER=directx"); +#endif + } +} + +static void ModeSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(mode)) +{ + TXT_CAST_ARG(screen_mode_t, mode); + + screen_width = mode->w; + screen_height = mode->h; + + // This is now the most recently selected screen width + + selected_screen_width = screen_width; + selected_screen_height = screen_height; +} + +static int GoodFullscreenMode(screen_mode_t *mode) +{ + int w, h; + + w = mode->w; + h = mode->h; + + // 320x200 and 640x400 are always good (special case) + + if ((w == 320 && h == 200) || (w == 640 && h == 400)) + { + return 1; + } + + // Special case: 320x240 letterboxed mode is okay (but not aspect + // ratio corrected 320x240) + + if (w == 320 && h == 240 && !aspect_ratio_correct) + { + return 1; + } + + // Ignore all modes less than 640x480 + + return w >= 640 && h >= 480; +} + +// Build screen_modes_fullscreen + +static void BuildFullscreenModesList(void) +{ + SDL_Rect **modes; + screen_mode_t *m1; + screen_mode_t *m2; + screen_mode_t m; + int num_modes; + int i; + + // Free the existing modes list, if one exists + + if (screen_modes_fullscreen != NULL) + { + free(screen_modes_fullscreen); + } + + // Get a list of fullscreen modes and find out how many + // modes are in the list. + + modes = SDL_ListModes(NULL, SDL_FULLSCREEN); + + if (modes == NULL || modes == (SDL_Rect **) -1) + { + num_modes = 0; + } + else + { + 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 int FindBestMode(screen_mode_t *modes) +{ + int i; + int best_mode; + int best_mode_diff; + int diff; + + best_mode = -1; + best_mode_diff = 0; + + for (i=0; modes[i].w != 0; ++i) + { + if (fullscreen && !GoodFullscreenMode(&modes[i])) + { + continue; + } + + diff = (selected_screen_width - modes[i].w) + * (selected_screen_width - modes[i].w) + + (selected_screen_height - modes[i].h) + * (selected_screen_height - modes[i].h); + + if (best_mode == -1 || diff < best_mode_diff) + { + best_mode_diff = diff; + best_mode = i; + } + } + + 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) + { + if (screen_modes_fullscreen == NULL) + { + 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, 15, 15, 15); + + for (i=0; modes[i].w != 0; ++i) + { + // Skip bad fullscreen modes + + if (fullscreen && !GoodFullscreenMode(&modes[i])) + { + 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); + + screen_width = modes[vidmode].w; + screen_height = modes[vidmode].h; +} + +#if defined(_WIN32) && !defined(_WIN32_WCE) + +static int win32_video_driver = 0; + +static char *win32_video_drivers[] = +{ + "DirectX", + "Windows GDI", +}; + +// Restart the textscreen library. Used when the video_driver variable +// is changed. + +static void RestartTextscreen(void) +{ + TXT_Shutdown(); + + SetDisplayDriver(); + + TXT_Init(); +} + +static void SetWin32VideoDriver(void) +{ + if (!strcmp(video_driver, "windib")) + { + win32_video_driver = 1; + } + else + { + win32_video_driver = 0; + } +} + +static void UpdateVideoDriver(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(modes_table)) +{ + TXT_CAST_ARG(txt_table_t, modes_table); + char *drivers[] = + { + "", + "windib", + }; + + video_driver = drivers[win32_video_driver != 0]; + + // When the video driver is changed, we need to restart the textscreen + // library. + + RestartTextscreen(); + + // Rebuild the video modes list + + BuildFullscreenModesList(); + GenerateModesTable(NULL, modes_table); +} + +#endif + + +void ConfigDisplay(void) +{ + txt_window_t *window; + txt_table_t *modes_table; + txt_checkbox_t *fs_checkbox; + txt_checkbox_t *ar_checkbox; + + // First time in? Initialise selected_screen_{width,height} + + if (selected_screen_width == 0) + { + selected_screen_width = screen_width; + selected_screen_height = screen_height; + } + + // Open the window + + window = TXT_NewWindow("Display Configuration"); + + TXT_SetWindowPosition(window, TXT_HORIZ_CENTER, TXT_VERT_TOP, + TXT_SCREEN_W / 2, 5); + + TXT_AddWidgets(window, + fs_checkbox = TXT_NewCheckBox("Fullscreen", &fullscreen), + ar_checkbox = TXT_NewCheckBox("Correct aspect ratio", + &aspect_ratio_correct), + NULL); + + modes_table = TXT_NewTable(3); + + // On Windows, there is an extra control to change between + // the Windows GDI and DirectX video drivers. + +#if defined(_WIN32) && !defined(_WIN32_WCE) + { + txt_table_t *driver_table; + txt_dropdown_list_t *driver_list; + + driver_table = TXT_NewTable(2); + + TXT_SetColumnWidths(driver_table, 20, 0); + + TXT_AddWidgets(driver_table, + TXT_NewLabel("Video driver"), + driver_list = TXT_NewDropdownList(&win32_video_driver, + win32_video_drivers, + 2), + NULL); + + TXT_SignalConnect(driver_list, "changed", + UpdateVideoDriver, modes_table); + SetWin32VideoDriver(); + + TXT_AddWidget(window, driver_table); + } +#endif + + // Screen modes list + + TXT_AddWidgets(window, + TXT_NewSeparator("Screen mode"), + modes_table, + TXT_NewSeparator("Misc."), + NULL); + + if (gamemission == heretic || gamemission == hexen) + { + TXT_AddWidget(window, + TXT_NewCheckBox("Graphical startup", &graphical_startup)); + } + + if (gamemission == doom || gamemission == heretic) + { + TXT_AddWidget(window, + TXT_NewCheckBox("Show ENDOOM screen", &show_endoom)); + } + + TXT_SignalConnect(fs_checkbox, "changed", GenerateModesTable, modes_table); + TXT_SignalConnect(ar_checkbox, "changed", GenerateModesTable, modes_table); + + GenerateModesTable(NULL, modes_table); +} + +void BindDisplayVariables(void) +{ + M_BindVariable("autoadjust_video_settings", &autoadjust_video_settings); + M_BindVariable("aspect_ratio_correct", &aspect_ratio_correct); + M_BindVariable("fullscreen", &fullscreen); + M_BindVariable("screen_width", &screen_width); + M_BindVariable("screen_height", &screen_height); + M_BindVariable("startup_delay", &startup_delay); + M_BindVariable("video_driver", &video_driver); + M_BindVariable("usegamma", &usegamma); + + + if (gamemission == doom || gamemission == heretic) + { + M_BindVariable("show_endoom", &show_endoom); + } + + if (gamemission == heretic || gamemission == hexen) + { + M_BindVariable("graphical_startup", &graphical_startup); + } + +} + |