diff options
Diffstat (limited to 'src/setup')
29 files changed, 4501 insertions, 0 deletions
diff --git a/src/setup/.gitignore b/src/setup/.gitignore new file mode 100644 index 00000000..d7e732ad --- /dev/null +++ b/src/setup/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +.deps +*.rc +chocolate-doom +chocolate-server +*.exe diff --git a/src/setup/Makefile.am b/src/setup/Makefile.am new file mode 100644 index 00000000..a39a1812 --- /dev/null +++ b/src/setup/Makefile.am @@ -0,0 +1,26 @@ + +AM_CFLAGS = @SDL_CFLAGS@ -I../../textscreen -I.. -DINSTALL_DIR="\"$(gamesdir)\"" + +noinst_LIBRARIES = libsetup.a + +SOURCE_FILES = \ + compatibility.c compatibility.h \ + display.c display.h \ + joystick.c joystick.h \ + keyboard.c keyboard.h \ + mainmenu.c \ + mode.c mode.h \ + mouse.c mouse.h \ + multiplayer.c multiplayer.h \ + sound.c sound.h \ + execute.c execute.h \ + txt_joybinput.c txt_joybinput.h \ + txt_keyinput.c txt_keyinput.h \ + txt_mouseinput.c txt_mouseinput.h + +libsetup_a_SOURCES = $(SOURCE_FILES) + +EXTRA_DIST= \ + setup_icon.c \ + setup-manifest.xml + diff --git a/src/setup/compatibility.c b/src/setup/compatibility.c new file mode 100644 index 00000000..722088e8 --- /dev/null +++ b/src/setup/compatibility.c @@ -0,0 +1,57 @@ +// 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. +// + +// Sound control menu + +#include <stdlib.h> + +#include "m_config.h" +#include "textscreen.h" +#include "mode.h" + +#include "compatibility.h" + +int vanilla_savegame_limit = 1; +int vanilla_demo_limit = 1; + +void CompatibilitySettings(void) +{ + txt_window_t *window; + + window = TXT_NewWindow("Compatibility"); + + TXT_AddWidgets(window, + TXT_NewCheckBox("Vanilla savegame limit", + &vanilla_savegame_limit), + TXT_NewCheckBox("Vanilla demo limit", + &vanilla_demo_limit), + NULL); +} + +void BindCompatibilityVariables(void) +{ + if (gamemission == doom) + { + M_BindVariable("vanilla_savegame_limit", &vanilla_savegame_limit); + M_BindVariable("vanilla_demo_limit", &vanilla_demo_limit); + } +} + diff --git a/src/setup/compatibility.h b/src/setup/compatibility.h new file mode 100644 index 00000000..386a4798 --- /dev/null +++ b/src/setup/compatibility.h @@ -0,0 +1,29 @@ +// 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. +// + +#ifndef SETUP_COMPATIBILITY_H +#define SETUP_COMPATIBILITY_H + +void CompatibilitySettings(void); +void BindCompatibilityVariables(void); + +#endif /* #ifndef SETUP_COMPATIBILITY_H */ + diff --git a/src/setup/display.c b/src/setup/display.c new file mode 100644 index 00000000..ce576795 --- /dev/null +++ b/src/setup/display.c @@ -0,0 +1,478 @@ +// 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> + +#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 + { +#ifdef _WIN32 + // 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); + + 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; +} + +#ifdef _WIN32 + +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, 40, 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. + +#ifdef _WIN32 + { + 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); + } + +} + diff --git a/src/setup/display.h b/src/setup/display.h new file mode 100644 index 00000000..2c17d8c4 --- /dev/null +++ b/src/setup/display.h @@ -0,0 +1,30 @@ +// 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. +// + +#ifndef SETUP_DISPLAY_H +#define SETUP_DISPLAY_H + +void ConfigDisplay(void); +void SetDisplayDriver(void); +void BindDisplayVariables(void); + +#endif /* #ifndef SETUP_DISPLAY_H */ + diff --git a/src/setup/execute.c b/src/setup/execute.c new file mode 100644 index 00000000..9846cd20 --- /dev/null +++ b/src/setup/execute.c @@ -0,0 +1,290 @@ +// 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. +// + +// Code for invoking Doom + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <sys/types.h> + +#ifndef _WIN32 + #include <sys/wait.h> + #include <unistd.h> +#else + #include <process.h> +#endif + +#include "textscreen.h" + +#include "config.h" +#include "execute.h" +#include "m_argv.h" +#include "m_config.h" + +#ifdef _WIN32 +#define DOOM_BINARY PACKAGE_TARNAME ".exe" +#else +#define DOOM_BINARY INSTALL_DIR "/" PACKAGE_TARNAME +#endif + +#ifdef _WIN32 +#define DIR_SEPARATOR '\\' +#define PATH_SEPARATOR ';' +#else +#define DIR_SEPARATOR '/' +#define PATH_SEPARATOR ':' +#endif + +struct execute_context_s +{ + char *response_file; + FILE *stream; +}; + +// Returns the path to a temporary file of the given name, stored +// inside the system temporary directory. + +static char *TempFile(char *s) +{ + char *result; + char *tempdir; + +#ifdef _WIN32 + + // Check the TEMP environment variable to find the location. + + tempdir = getenv("TEMP"); + + if (tempdir == NULL) + { + tempdir = "."; + } +#else + // In Unix, just use /tmp. + + tempdir = "/tmp"; +#endif + + result = malloc(strlen(tempdir) + strlen(s) + 2); + sprintf(result, "%s%c%s", tempdir, DIR_SEPARATOR, s); + + return result; +} + +execute_context_t *NewExecuteContext(void) +{ + execute_context_t *result; + + result = malloc(sizeof(execute_context_t)); + + result->response_file = TempFile("chocolat.rsp"); + result->stream = fopen(result->response_file, "w"); + + if (result->stream == NULL) + { + fprintf(stderr, "Error opening response file\n"); + exit(-1); + } + + return result; +} + +void AddConfigParameters(execute_context_t *context) +{ + int p; + + p = M_CheckParm("-config"); + + if (p > 0) + { + AddCmdLineParameter(context, "-config \"%s\"", myargv[p + 1]); + } + + p = M_CheckParm("-extraconfig"); + + if (p > 0) + { + AddCmdLineParameter(context, "-extraconfig \"%s\"", myargv[p + 1]); + } +} + +void AddCmdLineParameter(execute_context_t *context, char *s, ...) +{ + va_list args; + + va_start(args, s); + + vfprintf(context->stream, s, args); + fprintf(context->stream, "\n"); +} + +#ifdef _WIN32 + +static int ExecuteCommand(const char **argv) +{ + return _spawnv(_P_WAIT, argv[0], argv); +} + +#else + +static int ExecuteCommand(const char **argv) +{ + pid_t childpid; + int result; + + childpid = fork(); + + if (childpid == 0) + { + // This is the child. Execute the command. + + execv(argv[0], (char **) argv); + + exit(-1); + } + else + { + // This is the parent. Wait for the child to finish, and return + // the status code. + + waitpid(childpid, &result, 0); + + if (WIFEXITED(result)) + { + return WEXITSTATUS(result); + } + else + { + return -1; + } + } +} + +#endif + +int ExecuteDoom(execute_context_t *context) +{ + const char *argv[3]; + char *response_file_arg; + int result; + + fclose(context->stream); + + // Build the command line + + response_file_arg = malloc(strlen(context->response_file) + 2); + sprintf(response_file_arg, "@%s", context->response_file); + + argv[0] = DOOM_BINARY; + argv[1] = response_file_arg; + argv[2] = NULL; + + // Run Doom + + result = ExecuteCommand(argv); + + free(response_file_arg); + + // Destroy context + remove(context->response_file); + free(context->response_file); + free(context); + + return result; +} + +static void TestCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) +{ + execute_context_t *exec; + char *main_cfg; + char *extra_cfg; + txt_window_t *testwindow; + txt_label_t *label; + + testwindow = TXT_NewWindow("Starting Doom"); + + label = TXT_NewLabel("Starting Doom to test the\n" + "settings. Please wait."); + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + TXT_AddWidget(testwindow, label); + TXT_DrawDesktop(); + + // Save temporary configuration files with the current configuration + + main_cfg = TempFile("tmp.cfg"); + extra_cfg = TempFile("extratmp.cfg"); + + M_SaveDefaultsAlternate(main_cfg, extra_cfg); + + // Run with the -testcontrols parameter + + exec = NewExecuteContext(); + AddCmdLineParameter(exec, "-testcontrols"); + AddCmdLineParameter(exec, "-config %s", main_cfg); + AddCmdLineParameter(exec, "-extraconfig %s", extra_cfg); + ExecuteDoom(exec); + + TXT_CloseWindow(testwindow); + + // Delete the temporary config files + + remove(main_cfg); + remove(extra_cfg); + free(main_cfg); + free(extra_cfg); +} + +txt_window_action_t *TestConfigAction(void) +{ + txt_window_action_t *test_action; + + test_action = TXT_NewWindowAction('t', "Test"); + TXT_SignalConnect(test_action, "pressed", TestCallback, NULL); + + return test_action; +} + +// Invokes Doom to find which IWADs are installed. +// This is a cheap hack to avoid duplication of the complicated install +// path searching code inside Doom. + +int FindInstalledIWADs(void) +{ + execute_context_t *context; + int result; + + context = NewExecuteContext(); + AddCmdLineParameter(context, "-findiwads"); + result = ExecuteDoom(context); + + if (result < 0) + { + return 0; + } + else + { + return result; + } +} + diff --git a/src/setup/execute.h b/src/setup/execute.h new file mode 100644 index 00000000..24711a16 --- /dev/null +++ b/src/setup/execute.h @@ -0,0 +1,45 @@ +// 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. +// + +#ifndef TESTCONFIG_H +#define TESTCONFIG_H + +#include "textscreen.h" + +typedef struct execute_context_s execute_context_t; + +#define IWAD_DOOM2 (1 << 0) /* doom2.wad */ +#define IWAD_PLUTONIA (1 << 1) /* plutonia.wad */ +#define IWAD_TNT (1 << 2) /* tnt.wad */ +#define IWAD_DOOM (1 << 3) /* doom.wad */ +#define IWAD_DOOM1 (1 << 4) /* doom1.wad */ +#define IWAD_CHEX (1 << 5) /* chex.wad */ + +execute_context_t *NewExecuteContext(void); +void AddCmdLineParameter(execute_context_t *context, char *s, ...); +void AddConfigParameters(execute_context_t *context); +int ExecuteDoom(execute_context_t *context); +int FindInstalledIWADs(void); + +txt_window_action_t *TestConfigAction(void); + +#endif /* #ifndef TESTCONFIG_H */ + diff --git a/src/setup/joystick.c b/src/setup/joystick.c new file mode 100644 index 00000000..3d2b713b --- /dev/null +++ b/src/setup/joystick.c @@ -0,0 +1,449 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2007 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 <stdio.h> +#include <stdlib.h> + +#include "doomtype.h" +#include "m_config.h" +#include "m_controls.h" +#include "textscreen.h" + +#include "joystick.h" +#include "mode.h" +#include "txt_joybinput.h" + +typedef enum +{ + CALIBRATE_CENTER, + CALIBRATE_LEFT, + CALIBRATE_UP, +} calibration_stage_t; + +// SDL joystick successfully initialised? + +static int joystick_initted = 0; + +// Joystick enable/disable + +static int usejoystick = 0; + +// Joystick to use, as an SDL joystick index: + +int joystick_index = -1; + +// Which joystick axis to use for horizontal movement, and whether to +// invert the direction: + +static int joystick_x_axis = 0; +static int joystick_x_invert = 0; + +// Which joystick axis to use for vertical movement, and whether to +// invert the direction: + +static int joystick_y_axis = 1; +static int joystick_y_invert = 0; + +static txt_button_t *joystick_button; + +static int *all_joystick_buttons[] = { + &joybstraferight, &joybstrafeleft, &joybfire, &joybspeed, + &joybuse, &joybstrafe, &joybjump +}; + +// +// Calibration +// + +static txt_window_t *calibration_window; +static txt_label_t *calibration_label; +static calibration_stage_t calibrate_stage; +static SDL_Joystick **all_joysticks = NULL; + +// Set the label showing the name of the currently selected joystick + +static void SetJoystickButtonLabel(void) +{ + char *name; + + name = "None set"; + + if (joystick_initted + && joystick_index >= 0 && joystick_index < SDL_NumJoysticks()) + { + name = (char *) SDL_JoystickName(joystick_index); + } + + TXT_SetButtonLabel(joystick_button, name); +} + +// Try to open all joysticks visible to SDL. + +static int OpenAllJoysticks(void) +{ + int i; + int num_joysticks; + int result; + + if (!joystick_initted) + { + return 0; + } + + // SDL_JoystickOpen() all joysticks. + + num_joysticks = SDL_NumJoysticks(); + + all_joysticks = malloc(sizeof(SDL_Joystick *) * num_joysticks); + + result = 0; + + for (i=0; i<num_joysticks; ++i) + { + all_joysticks[i] = SDL_JoystickOpen(i); + + // If any joystick is successfully opened, return true. + + if (all_joysticks[i] != NULL) + { + result = 1; + } + } + + // Success? Turn on joystick events. + + if (result) + { + SDL_JoystickEventState(SDL_ENABLE); + } + else + { + free(all_joysticks); + all_joysticks = NULL; + } + + return result; +} + +// Close all the joysticks opened with OpenAllJoysticks() + +static void CloseAllJoysticks(void) +{ + int i; + int num_joysticks; + + num_joysticks = SDL_NumJoysticks(); + + for (i=0; i<num_joysticks; ++i) + { + if (all_joysticks[i] != NULL) + { + SDL_JoystickClose(all_joysticks[i]); + } + } + + SDL_JoystickEventState(SDL_DISABLE); + + free(all_joysticks); + all_joysticks = NULL; +} + +static void SetCalibrationLabel(void) +{ + char *message = "???"; + + switch (calibrate_stage) + { + case CALIBRATE_CENTER: + message = "Move the joystick to the\n" + "center, and press a button."; + break; + case CALIBRATE_UP: + message = "Move the joystick up,\n" + "and press a button."; + break; + case CALIBRATE_LEFT: + message = "Move the joystick to the\n" + "left, and press a button."; + break; + } + + TXT_SetLabel(calibration_label, message); +} + +static void CalibrateAxis(int *axis_index, int *axis_invert) +{ + SDL_Joystick *joystick; + int best_axis; + int best_value; + int best_invert; + Sint16 axis_value; + int i; + + joystick = all_joysticks[joystick_index]; + + // Check all axes to find which axis has the largest value. We test + // for one axis at a time, so eg. when we prompt to push the joystick + // left, whichever axis has the largest value is the left axis. + + best_axis = 0; + best_value = 0; + best_invert = 0; + + for (i=0; i<SDL_JoystickNumAxes(joystick); ++i) + { + axis_value = SDL_JoystickGetAxis(joystick, i); + + if (abs(axis_value) > best_value) + { + best_value = abs(axis_value); + best_invert = axis_value > 0; + best_axis = i; + } + } + + // Save the best values we have found + + *axis_index = best_axis; + *axis_invert = best_invert; +} + +static int CalibrationEventCallback(SDL_Event *event, void *user_data) +{ + if (event->type == SDL_JOYBUTTONDOWN + && (joystick_index == -1 || event->jbutton.which == joystick_index)) + { + switch (calibrate_stage) + { + case CALIBRATE_CENTER: + // Centering stage selects which joystick to use. + joystick_index = event->jbutton.which; + break; + + case CALIBRATE_LEFT: + CalibrateAxis(&joystick_x_axis, &joystick_x_invert); + break; + + case CALIBRATE_UP: + CalibrateAxis(&joystick_y_axis, &joystick_y_invert); + break; + } + + if (calibrate_stage == CALIBRATE_UP) + { + // Final stage; close the window + + TXT_CloseWindow(calibration_window); + } + else + { + // Advance to the next calibration stage + + ++calibrate_stage; + SetCalibrationLabel(); + } + + return 1; + } + + return 0; +} + +static void NoJoystick(void) +{ + txt_window_t *window; + + window = TXT_NewWindow(NULL); + + TXT_AddWidget(window, + TXT_NewLabel("No joysticks could be opened.\n\n" + "Try configuring your joystick from within\n" + "your OS first.")); + + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowEscapeAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + + joystick_index = -1; + SetJoystickButtonLabel(); +} + +static void CalibrateWindowClosed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + CloseAllJoysticks(); + TXT_SDL_SetEventCallback(NULL, NULL); + SetJoystickButtonLabel(); +} + +static void CalibrateJoystick(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + calibrate_stage = CALIBRATE_CENTER; + + // Try to open all available joysticks. If none are opened successfully, + // bomb out with an error. + + if (!OpenAllJoysticks()) + { + NoJoystick(); + return; + } + + calibration_window = TXT_NewWindow("Joystick calibration"); + + TXT_AddWidgets(calibration_window, + TXT_NewLabel("Please follow the following instructions\n" + "in order to calibrate your joystick."), + TXT_NewStrut(0, 1), + calibration_label = TXT_NewLabel("zzz"), + TXT_NewStrut(0, 1), + NULL); + + TXT_SetWindowAction(calibration_window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(calibration_window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(calibration_window)); + TXT_SetWindowAction(calibration_window, TXT_HORIZ_RIGHT, NULL); + + TXT_SetWidgetAlign(calibration_label, TXT_HORIZ_CENTER); + TXT_SDL_SetEventCallback(CalibrationEventCallback, NULL); + + TXT_SignalConnect(calibration_window, "closed", CalibrateWindowClosed, NULL); + + // Start calibration + + joystick_index = -1; + calibrate_stage = CALIBRATE_CENTER; + + SetCalibrationLabel(); +} + +void JoyButtonSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) +{ + TXT_CAST_ARG(int, variable); + unsigned int i; + + // Only allow a button to be bound to one action at a time. If + // we assign a key that another action is using, set that other action + // to -1. + + for (i=0; i<arrlen(all_joystick_buttons); ++i) + { + if (variable != all_joystick_buttons[i] + && *variable == *all_joystick_buttons[i]) + { + *all_joystick_buttons[i] = -1; + } + } +} + + +// +// GUI +// + +static void JoystickWindowClosed(TXT_UNCAST_ARG(window), TXT_UNCAST_ARG(unused)) +{ + if (joystick_initted) + { + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); + joystick_initted = 0; + } +} + +static void AddJoystickControl(txt_table_t *table, char *label, int *var) +{ + txt_joystick_input_t *joy_input; + + joy_input = TXT_NewJoystickInput(var); + + TXT_AddWidget(table, TXT_NewLabel(label)); + TXT_AddWidget(table, joy_input); + + TXT_SignalConnect(joy_input, "set", JoyButtonSetCallback, var); +} + +void ConfigJoystick(void) +{ + txt_window_t *window; + txt_table_t *button_table; + txt_table_t *joystick_table; + + if (!joystick_initted) + { + joystick_initted = SDL_Init(SDL_INIT_JOYSTICK) >= 0; + } + + window = TXT_NewWindow("Joystick configuration"); + + TXT_AddWidgets(window, + TXT_NewCheckBox("Enable joystick", &usejoystick), + joystick_table = TXT_NewTable(2), + TXT_NewSeparator("Joystick buttons"), + button_table = TXT_NewTable(2), + NULL); + + TXT_SetColumnWidths(joystick_table, 20, 15); + + TXT_AddWidgets(joystick_table, + TXT_NewLabel("Current joystick"), + joystick_button = TXT_NewButton("zzzz"), + NULL); + + TXT_SetColumnWidths(button_table, 20, 15); + + AddJoystickControl(button_table, "Fire/Attack", &joybfire); + AddJoystickControl(button_table, "Use", &joybuse); + + // High values of joybspeed are used to activate the "always run mode" + // trick in Vanilla Doom. If this has been enabled, not only is the + // joybspeed value meaningless, but the control itself is useless. + + if (joybspeed < 20) + { + AddJoystickControl(button_table, "Speed", &joybspeed); + } + + AddJoystickControl(button_table, "Strafe", &joybstrafe); + + AddJoystickControl(button_table, "Strafe Left", &joybstrafeleft); + AddJoystickControl(button_table, "Strafe Right", &joybstraferight); + + if (gamemission == hexen) + { + AddJoystickControl(button_table, "Jump", &joybjump); + } + + TXT_SignalConnect(joystick_button, "pressed", CalibrateJoystick, NULL); + TXT_SignalConnect(window, "closed", JoystickWindowClosed, NULL); + + SetJoystickButtonLabel(); +} + +void BindJoystickVariables(void) +{ + M_BindVariable("use_joystick", &usejoystick); + M_BindVariable("joystick_index", &joystick_index); + M_BindVariable("joystick_x_axis", &joystick_x_axis); + M_BindVariable("joystick_y_axis", &joystick_y_axis); + M_BindVariable("joystick_x_invert", &joystick_x_invert); + M_BindVariable("joystick_y_invert", &joystick_y_invert); +} + diff --git a/src/setup/joystick.h b/src/setup/joystick.h new file mode 100644 index 00000000..b6dd09b9 --- /dev/null +++ b/src/setup/joystick.h @@ -0,0 +1,31 @@ +// 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. +// + +#ifndef SETUP_JOYSTICK_H +#define SETUP_JOYSTICK_H + +extern int joystick_index; + +void ConfigJoystick(void); +void BindJoystickVariables(void); + +#endif /* #ifndef SETUP_JOYSTICK_H */ + diff --git a/src/setup/keyboard.c b/src/setup/keyboard.c new file mode 100644 index 00000000..22fc8a02 --- /dev/null +++ b/src/setup/keyboard.c @@ -0,0 +1,199 @@ +// 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 "textscreen.h" +#include "doomtype.h" +#include "m_config.h" +#include "m_controls.h" + +#include "execute.h" +#include "txt_keyinput.h" + +#include "mode.h" +#include "joystick.h" +#include "keyboard.h" + +static int vanilla_keyboard_mapping = 1; + +static int always_run = 0; + +static int *allkeys[] = { + &key_left, &key_right, &key_up, &key_down, + &key_strafeleft, &key_straferight, &key_strafe, + &key_jump, &key_fire, &key_use, &key_speed, + &key_flyup, &key_flydown, &key_flycenter, + &key_lookup, &key_lookdown, &key_lookcenter, + &key_invleft, &key_invright, &key_useartifact +}; + +static void UpdateJoybSpeed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(var)) +{ + if (always_run) + { + /* + <Janizdreg> if you want to pick one for chocolate doom to use, + pick 29, since that is the most universal one that + also works with heretic, hexen and strife =P + + NB. This choice also works with original, ultimate and final exes. + */ + + joybspeed = 29; + } + else + { + joybspeed = 0; + } +} + +// Callback invoked when a key control is set + +static void KeySetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) +{ + TXT_CAST_ARG(int, variable); + unsigned int i; + + for (i=0; i<arrlen(allkeys); ++i) + { + if (*variable == *allkeys[i] && allkeys[i] != variable) + { + // A different key has the same value. Clear the existing + // value. This ensures that no two keys can have the same + // value. + + *allkeys[i] = 0; + } + } +} + +static void AddKeyControl(txt_table_t *table, char *name, int *var) +{ + txt_key_input_t *key_input; + + TXT_AddWidget(table, TXT_NewLabel(name)); + key_input = TXT_NewKeyInput(var); + TXT_AddWidget(table, key_input); + TXT_SignalConnect(key_input, "set", KeySetCallback, var); +} + +static void ConfigExtraKeys(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + txt_table_t *view_table; + txt_table_t *fly_table; + txt_table_t *inv_table; + + window = TXT_NewWindow("Extra keyboard controls"); + + TXT_AddWidgets(window, + TXT_NewSeparator("View"), + view_table = TXT_NewTable(2), + TXT_NewSeparator("Flying"), + fly_table = TXT_NewTable(2), + TXT_NewSeparator("Inventory"), + inv_table = TXT_NewTable(2), + NULL); + + TXT_SetColumnWidths(view_table, 25, 12); + + AddKeyControl(view_table, "Look up", &key_lookup); + AddKeyControl(view_table, "Look down", &key_lookdown); + AddKeyControl(view_table, "Center view", &key_lookcenter); + + TXT_SetColumnWidths(fly_table, 25, 12); + + AddKeyControl(fly_table, "Fly up", &key_flyup); + AddKeyControl(fly_table, "Fly down", &key_flydown); + AddKeyControl(fly_table, "Fly center", &key_flycenter); + + TXT_SetColumnWidths(inv_table, 25, 12); + + AddKeyControl(inv_table, "Inventory left", &key_invleft); + AddKeyControl(inv_table, "Inventory right", &key_invright); + AddKeyControl(inv_table, "Use artifact", &key_useartifact); +} + +void ConfigKeyboard(void) +{ + txt_window_t *window; + txt_table_t *movement_table; + txt_table_t *action_table; + txt_checkbox_t *run_control; + + always_run = joybspeed >= 20; + + window = TXT_NewWindow("Keyboard configuration"); + + TXT_AddWidgets(window, + TXT_NewSeparator("Movement"), + movement_table = TXT_NewTable(4), + + TXT_NewSeparator("Action"), + action_table = TXT_NewTable(4), + NULL); + + // Look up/down, inventory and flying controls are only in Heretic/Hexen + // and are kept in a separate window to conserve space. + + if (gamemission == heretic || gamemission == hexen) + { + TXT_AddWidget(window, TXT_NewButton2("More controls...", + ConfigExtraKeys, + NULL)); + } + + TXT_AddWidgets(window, + TXT_NewSeparator("Misc."), + run_control = TXT_NewCheckBox("Always run", &always_run), + TXT_NewInvertedCheckBox("Use native keyboard mapping", + &vanilla_keyboard_mapping), + NULL); + + TXT_SetColumnWidths(movement_table, 15, 4, 15, 4); + + TXT_SignalConnect(run_control, "changed", UpdateJoybSpeed, NULL); + + AddKeyControl(movement_table, "Move Forward", &key_up); + AddKeyControl(movement_table, " Strafe Left", &key_strafeleft); + AddKeyControl(movement_table, "Move Backward", &key_down); + AddKeyControl(movement_table, " Strafe Right", &key_straferight); + AddKeyControl(movement_table, "Turn Left", &key_left); + AddKeyControl(movement_table, " Speed On", &key_speed); + AddKeyControl(movement_table, "Turn Right", &key_right); + AddKeyControl(movement_table, " Strafe On", &key_strafe); + + if (gamemission == hexen) + { + AddKeyControl(movement_table, "Jump", &key_jump); + } + + TXT_SetColumnWidths(action_table, 15, 4, 15, 4); + + AddKeyControl(action_table, "Fire/Attack", &key_fire); + AddKeyControl(action_table, " Use", &key_use); + + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); +} + +void BindKeyboardVariables(void) +{ + M_BindVariable("vanilla_keyboard_mapping", &vanilla_keyboard_mapping); +} + diff --git a/src/setup/keyboard.h b/src/setup/keyboard.h new file mode 100644 index 00000000..12059bf8 --- /dev/null +++ b/src/setup/keyboard.h @@ -0,0 +1,29 @@ +// 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. +// + +#ifndef SETUP_KEYBOARD_H +#define SETUP_KEYBOARD_H + +void ConfigKeyboard(void); +void BindKeyboardVariables(void); + +#endif /* #ifndef SETUP_KEYBOARD_H */ + diff --git a/src/setup/mainmenu.c b/src/setup/mainmenu.c new file mode 100644 index 00000000..90bda7de --- /dev/null +++ b/src/setup/mainmenu.c @@ -0,0 +1,257 @@ +// 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> + +#include "config.h" +#include "textscreen.h" + +#include "execute.h" + +#include "m_argv.h" +#include "m_config.h" + +#include "setup_icon.c" +#include "mode.h" + +#include "compatibility.h" +#include "display.h" +#include "joystick.h" +#include "keyboard.h" +#include "mouse.h" +#include "multiplayer.h" +#include "sound.h" + +static void DoQuit(void *widget, void *dosave) +{ + if (dosave != NULL) + { + M_SaveDefaults(); + } + + exit(0); +} + +static void QuitConfirm(void *unused1, void *unused2) +{ + txt_window_t *window; + txt_label_t *label; + txt_button_t *yes_button; + txt_button_t *no_button; + + window = TXT_NewWindow(NULL); + + TXT_AddWidgets(window, + label = TXT_NewLabel("Exiting setup.\nSave settings?"), + TXT_NewStrut(24, 0), + yes_button = TXT_NewButton2(" Yes ", DoQuit, DoQuit), + no_button = TXT_NewButton2(" No ", DoQuit, NULL), + NULL); + + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + TXT_SetWidgetAlign(yes_button, TXT_HORIZ_CENTER); + TXT_SetWidgetAlign(no_button, TXT_HORIZ_CENTER); + + // Only an "abort" button in the middle. + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); +} + +static void LaunchDoom(void *unused1, void *unused2) +{ + execute_context_t *exec; + + // Save configuration first + + M_SaveDefaults(); + + // Shut down textscreen GUI + + TXT_Shutdown(); + + // Launch Doom + + exec = NewExecuteContext(); + AddConfigParameters(exec); + ExecuteDoom(exec); + + exit(0); +} + +static txt_button_t *GetLaunchButton(void) +{ + char *label; + + switch (gamemission) + { + case doom: + label = "Save parameters and launch DOOM"; + break; + case heretic: + label = "Save parameters and launch Heretic"; + break; + case hexen: + label = "Save parameters and launch Hexen"; + break; + default: + label = "Save parameters and launch game"; + break; + } + + return TXT_NewButton2(label, LaunchDoom, NULL); +} + +void MainMenu(void) +{ + txt_window_t *window; + txt_window_action_t *quit_action; + + window = TXT_NewWindow("Main Menu"); + + TXT_AddWidgets(window, + TXT_NewButton2("Configure Display", + (TxtWidgetSignalFunc) ConfigDisplay, NULL), + TXT_NewButton2("Configure Sound", + (TxtWidgetSignalFunc) ConfigSound, NULL), + TXT_NewButton2("Configure Keyboard", + (TxtWidgetSignalFunc) ConfigKeyboard, NULL), + TXT_NewButton2("Configure Mouse", + (TxtWidgetSignalFunc) ConfigMouse, NULL), + TXT_NewButton2("Configure Joystick", + (TxtWidgetSignalFunc) ConfigJoystick, NULL), + NULL); + + // The compatibility window is only appropriate for Doom. + + if (gamemission == doom) + { + txt_button_t *button; + + button = TXT_NewButton2("Compatibility", + (TxtWidgetSignalFunc) CompatibilitySettings, + NULL); + + TXT_AddWidget(window, button); + } + + TXT_AddWidgets(window, + GetLaunchButton(), + TXT_NewStrut(0, 1), + TXT_NewButton2("Start a Network Game", + (TxtWidgetSignalFunc) StartMultiGame, NULL), + TXT_NewButton2("Join a Network Game", + (TxtWidgetSignalFunc) JoinMultiGame, NULL), + TXT_NewButton2("Multiplayer Configuration", + (TxtWidgetSignalFunc) MultiplayerConfig, NULL), + NULL); + + quit_action = TXT_NewWindowAction(KEY_ESCAPE, "Quit"); + TXT_SignalConnect(quit_action, "pressed", QuitConfirm, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, quit_action); +} + +static void InitConfig(void) +{ + InitBindings(); + + SetChatMacroDefaults(); + SetPlayerNameDefault(); + + M_SetConfigDir(); + M_LoadDefaults(); +} + +// +// Application icon +// + +static void SetIcon(void) +{ + SDL_Surface *surface; + Uint8 *mask; + int i; + + // Generate the mask + + mask = malloc(setup_icon_w * setup_icon_h / 8); + memset(mask, 0, setup_icon_w * setup_icon_h / 8); + + for (i=0; i<setup_icon_w * setup_icon_h; ++i) + { + if (setup_icon_data[i * 3] != 0x00 + || setup_icon_data[i * 3 + 1] != 0x00 + || setup_icon_data[i * 3 + 2] != 0x00) + { + mask[i / 8] |= 1 << (7 - i % 8); + } + } + + + surface = SDL_CreateRGBSurfaceFrom(setup_icon_data, + setup_icon_w, + setup_icon_h, + 24, + setup_icon_w * 3, + 0xff << 0, + 0xff << 8, + 0xff << 16, + 0); + + SDL_WM_SetIcon(surface, mask); + SDL_FreeSurface(surface); + free(mask); +} + +// +// Initialise and run the textscreen GUI. +// + +static void RunGUI(void) +{ + SetDisplayDriver(); + + if (!TXT_Init()) + { + fprintf(stderr, "Failed to initialise GUI\n"); + exit(-1); + } + + TXT_SetDesktopTitle(PACKAGE_NAME " Setup ver " PACKAGE_VERSION); + SetIcon(); + + TXT_GUIMainLoop(); +} + +static void MissionSet(void) +{ + InitConfig(); + MainMenu(); +} + +void D_DoomMain(void) +{ + SetupMission(MissionSet); + RunGUI(); +} + diff --git a/src/setup/mode.c b/src/setup/mode.c new file mode 100644 index 00000000..d5a396ac --- /dev/null +++ b/src/setup/mode.c @@ -0,0 +1,269 @@ +// 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 <string.h> + +#include "config.h" +#include "textscreen.h" + +#include "doomtype.h" +#include "d_mode.h" +#include "d_iwad.h" +#include "i_system.h" +#include "m_argv.h" +#include "m_config.h" +#include "m_controls.h" + +#include "compatibility.h" +#include "display.h" +#include "joystick.h" +#include "keyboard.h" +#include "mouse.h" +#include "multiplayer.h" +#include "sound.h" + +#include "mode.h" + +GameMission_t gamemission; + +typedef struct +{ + char *label; + GameMission_t mission; + int mask; + char *name; + char *config_file; + char *extra_config_file; +} mission_config_t; + +// Default mission to fall back on, if no IWADs are found at all: + +#define DEFAULT_MISSION (&mission_configs[0]) + +static mission_config_t mission_configs[] = +{ + { + "Doom", + doom, + IWAD_MASK_DOOM, + "doom", + "default.cfg", + PROGRAM_PREFIX "doom.cfg" + }, + { + "Heretic", + heretic, + IWAD_MASK_HERETIC, + "heretic", + "heretic.cfg", + PROGRAM_PREFIX "heretic.cfg" + }, + { + "Hexen", + hexen, + IWAD_MASK_HEXEN, + "hexen", + "hexen.cfg", + PROGRAM_PREFIX "hexen.cfg" + } +}; + +static GameSelectCallback game_selected_callback; + +// Miscellaneous variables that aren't used in setup. + +static int showMessages = 1; +static int screenblocks = 9; +static int detailLevel = 0; +static char *savedir = NULL; + +static void BindMiscVariables(void) +{ + M_BindVariable("screenblocks", &screenblocks); + + if (gamemission == doom) + { + M_BindVariable("detaillevel", &detailLevel); + M_BindVariable("show_messages", &showMessages); + } + + if (gamemission == hexen) + { + M_BindVariable("savedir", &savedir); + M_BindVariable("messageson", &showMessages); + } +} + +// +// Initialise all configuration file bindings. +// + +void InitBindings(void) +{ + // Keyboard, mouse, joystick controls + + M_BindBaseControls(); + + if (gamemission == heretic || gamemission == hexen) + { + M_BindHereticControls(); + } + + if (gamemission == hexen) + { + M_BindHexenControls(); + } + + // All other variables + + BindCompatibilityVariables(); + BindDisplayVariables(); + BindJoystickVariables(); + BindKeyboardVariables(); + BindMouseVariables(); + BindSoundVariables(); + BindMiscVariables(); + BindMultiplayerVariables(); +} + +static void SetMission(mission_config_t *config) +{ + gamemission = config->mission; + M_SetConfigFilenames(config->config_file, config->extra_config_file); +} + +static mission_config_t *GetMissionForName(char *name) +{ + int i; + + for (i=0; i<arrlen(mission_configs); ++i) + { + if (!strcmp(mission_configs[i].name, name)) + { + return &mission_configs[i]; + } + } + + return NULL; +} + +static void GameSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(config)) +{ + TXT_CAST_ARG(mission_config_t, config); + + SetMission(config); + game_selected_callback(); +} + +static void OpenGameSelectDialog(GameSelectCallback callback) +{ + mission_config_t *mission; + txt_window_t *window; + iwad_t **iwads; + int num_games; + int i; + + window = TXT_NewWindow("Select game"); + + TXT_AddWidget(window, TXT_NewLabel("Select a game to configure:\n")); + num_games = 0; + + // Add a button for each game. + + for (i=0; i<arrlen(mission_configs); ++i) + { + // Do we have any IWADs for this game installed? + // If so, add a button. + + iwads = D_FindAllIWADs(mission_configs[i].mask); + + if (iwads[0] != NULL) + { + mission = &mission_configs[i]; + TXT_AddWidget(window, TXT_NewButton2(mission_configs[i].label, + GameSelected, + &mission_configs[i])); + ++num_games; + } + + free(iwads); + } + + TXT_AddWidget(window, TXT_NewStrut(0, 1)); + + // No IWADs found at all? Fall back to doom, then. + + if (num_games == 0) + { + TXT_CloseWindow(window); + SetMission(DEFAULT_MISSION); + callback(); + return; + } + + // Only one game? Use that game, and don't bother with a dialog. + + if (num_games == 1) + { + TXT_CloseWindow(window); + SetMission(mission); + callback(); + return; + } + + game_selected_callback = callback; +} + +void SetupMission(GameSelectCallback callback) +{ + mission_config_t *config; + char *mission_name; + int p; + + //! + // @arg <game> + // + // Specify the game to configure the settings for. Valid + // values are 'doom', 'heretic' and 'hexen'. + // + + p = M_CheckParm("-game"); + + if (p > 0) + { + mission_name = myargv[p + 1]; + + config = GetMissionForName(mission_name); + + if (config == NULL) + { + I_Error("Invalid parameter - '%s'", mission_name); + } + + SetMission(config); + callback(); + } + else + { + OpenGameSelectDialog(callback); + } +} + diff --git a/src/setup/mode.h b/src/setup/mode.h new file mode 100644 index 00000000..a78a5bc2 --- /dev/null +++ b/src/setup/mode.h @@ -0,0 +1,34 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2008 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. +// + +#ifndef SETUP_MODE_H +#define SETUP_MODE_H + +#include "d_mode.h" + +typedef void (*GameSelectCallback)(void); +extern GameMission_t gamemission; + +void SetupMission(GameSelectCallback callback); +void InitBindings(void); + +#endif /* #ifndef SETUP_MODE_H */ + diff --git a/src/setup/mouse.c b/src/setup/mouse.c new file mode 100644 index 00000000..d464261f --- /dev/null +++ b/src/setup/mouse.c @@ -0,0 +1,164 @@ +// 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 "textscreen.h" +#include "doomtype.h" +#include "m_config.h" +#include "m_controls.h" + +#include "execute.h" +#include "txt_mouseinput.h" + +#include "mode.h" +#include "mouse.h" + +static int usemouse = 1; + +static int novert = 0; +static int mouseSensitivity = 5; +static float mouse_acceleration = 1.0; +static int mouse_threshold = 10; +static int grabmouse = 1; + +static int *all_mouse_buttons[] = { + &mousebfire, + &mousebstrafe, + &mousebforward, + &mousebstrafeleft, + &mousebstraferight, + &mousebbackward, + &mousebuse, + &mousebjump +}; + +static void MouseSetCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(variable)) +{ + TXT_CAST_ARG(int, variable); + unsigned int i; + + // Check if the same mouse button is used for a different action + // If so, set the other action(s) to -1 (unset) + + for (i=0; i<arrlen(all_mouse_buttons); ++i) + { + if (*all_mouse_buttons[i] == *variable + && all_mouse_buttons[i] != variable) + { + *all_mouse_buttons[i] = -1; + } + } +} + +static void AddMouseControl(txt_table_t *table, char *label, int *var) +{ + txt_mouse_input_t *mouse_input; + + TXT_AddWidget(table, TXT_NewLabel(label)); + + mouse_input = TXT_NewMouseInput(var); + TXT_AddWidget(table, mouse_input); + + TXT_SignalConnect(mouse_input, "set", MouseSetCallback, var); +} + +static void ConfigExtraButtons(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + txt_window_t *window; + txt_table_t *buttons_table; + + window = TXT_NewWindow("Additional mouse buttons"); + + TXT_AddWidgets(window, + buttons_table = TXT_NewTable(2), + NULL); + + TXT_SetColumnWidths(buttons_table, 29, 5); + + AddMouseControl(buttons_table, "Move backward", &mousebbackward); + AddMouseControl(buttons_table, "Use", &mousebuse); + AddMouseControl(buttons_table, "Strafe left", &mousebstrafeleft); + AddMouseControl(buttons_table, "Strafe right", &mousebstraferight); + + if (gamemission == hexen) + { + AddMouseControl(buttons_table, "Jump", &mousebjump); + } +} + +void ConfigMouse(void) +{ + txt_window_t *window; + txt_table_t *motion_table; + txt_table_t *buttons_table; + + window = TXT_NewWindow("Mouse configuration"); + + TXT_AddWidgets(window, + TXT_NewCheckBox("Enable mouse", &usemouse), + TXT_NewInvertedCheckBox("Allow vertical mouse movement", + &novert), + TXT_NewCheckBox("Grab mouse in windowed mode", + &grabmouse), + TXT_NewCheckBox("Double click acts as \"use\"", + &dclick_use), + + TXT_NewSeparator("Mouse motion"), + motion_table = TXT_NewTable(2), + + TXT_NewSeparator("Buttons"), + buttons_table = TXT_NewTable(2), + TXT_NewButton2("More controls...", + ConfigExtraButtons, + NULL), + NULL); + + TXT_SetColumnWidths(motion_table, 27, 5); + + TXT_AddWidgets(motion_table, + TXT_NewLabel("Speed"), + TXT_NewSpinControl(&mouseSensitivity, 1, 256), + TXT_NewLabel("Acceleration"), + TXT_NewFloatSpinControl(&mouse_acceleration, 1.0, 5.0), + TXT_NewLabel("Acceleration threshold"), + TXT_NewSpinControl(&mouse_threshold, 0, 32), + NULL); + + TXT_SetColumnWidths(buttons_table, 27, 5); + + AddMouseControl(buttons_table, "Fire/Attack", &mousebfire); + AddMouseControl(buttons_table, "Move forward", &mousebforward); + AddMouseControl(buttons_table, "Strafe on", &mousebstrafe); + + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, TestConfigAction()); +} + +void BindMouseVariables(void) +{ + M_BindVariable("use_mouse", &usemouse); + M_BindVariable("novert", &novert); + M_BindVariable("mouse_sensitivity", &mouseSensitivity); + M_BindVariable("mouse_acceleration", &mouse_acceleration); + M_BindVariable("mouse_threshold", &mouse_threshold); + M_BindVariable("grabmouse", &grabmouse); +} + diff --git a/src/setup/mouse.h b/src/setup/mouse.h new file mode 100644 index 00000000..cdaa541a --- /dev/null +++ b/src/setup/mouse.h @@ -0,0 +1,29 @@ +// 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. +// + +#ifndef SETUP_MOUSE_H +#define SETUP_MOUSE_H + +void ConfigMouse(void); +void BindMouseVariables(void); + +#endif /* #ifndef SETUP_MOUSE_H */ + diff --git a/src/setup/multiplayer.c b/src/setup/multiplayer.c new file mode 100644 index 00000000..86455a8a --- /dev/null +++ b/src/setup/multiplayer.c @@ -0,0 +1,766 @@ +// 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "doom/d_englsh.h" +#include "textscreen.h" +#include "doomtype.h" + +#include "execute.h" + +#include "multiplayer.h" +#include "m_config.h" + +#define NUM_WADS 10 +#define NUM_EXTRA_PARAMS 10 + +typedef struct +{ + char *filename; + char *description; + int mask; +} iwad_t; + +typedef enum +{ + WARP_DOOM1, + WARP_DOOM2, +} warptype_t; + +static iwad_t iwads[] = +{ + { "doom.wad", "Doom", IWAD_DOOM }, + { "doom2.wad", "Doom 2", IWAD_DOOM2 }, + { "tnt.wad", "Final Doom: TNT: Evilution", IWAD_TNT }, + { "plutonia.wad", "Final Doom: The Plutonia Experiment", IWAD_PLUTONIA }, + { "doom1.wad", "Doom shareware", IWAD_DOOM1 }, + { "chex.wad", "Chex Quest", IWAD_CHEX }, +}; + +// Array of IWADs found to be installed + +static char *found_iwads[6]; + +// Index of the currently selected IWAD + +static int found_iwad_selected; + +// Filename to pass to '-iwad'. + +static char *iwadfile; + +static char *skills[] = +{ + "I'm too young to die!", + "Hey, not too rough.", + "Hurt me plenty.", + "Ultra-violence", + "NIGHTMARE!", +}; + +static char *chex_skills[] = +{ + "Easy does it", + "Not so sticky", + "Gobs of goo", + "Extreme ooze", + "SUPER SLIMEY!" +}; + +static char *gamemodes[] = +{ + "Co-operative", + "Deathmatch", + "Deathmatch 2.0", +}; + +static char *net_player_name; +static char *chat_macros[10]; + +static char *wads[NUM_WADS]; +static char *extra_params[NUM_EXTRA_PARAMS]; +static int skill = 2; +static int nomonsters = 0; +static int deathmatch = 0; +static int fast = 0; +static int respawn = 0; +static int udpport = 2342; +static int timer = 0; + +static txt_dropdown_list_t *skillbutton; +static txt_button_t *warpbutton; +static warptype_t warptype = WARP_DOOM2; +static int warpepisode = 1; +static int warpmap = 1; + +// Address to connect to when joining a game + +static char *connect_address = NULL; + +// Find an IWAD from its description + +static iwad_t *GetIWADForDescription(char *description) +{ + unsigned int i; + + for (i=0; i<arrlen(iwads); ++i) + { + if (!strcmp(iwads[i].description, description)) + { + return &iwads[i]; + } + } + + return NULL; +} + +static iwad_t *GetCurrentIWAD(void) +{ + return GetIWADForDescription(found_iwads[found_iwad_selected]); +} + + +static void AddWADs(execute_context_t *exec) +{ + int have_wads = 0; + int i; + + for (i=0; i<NUM_WADS; ++i) + { + if (wads[i] != NULL && strlen(wads[i]) > 0) + { + if (!have_wads) + { + AddCmdLineParameter(exec, "-file"); + } + + AddCmdLineParameter(exec, "\"%s\"", wads[i]); + } + } +} + +static void AddExtraParameters(execute_context_t *exec) +{ + int i; + + for (i=0; i<NUM_EXTRA_PARAMS; ++i) + { + if (extra_params[i] != NULL && strlen(extra_params[i]) > 0) + { + AddCmdLineParameter(exec, extra_params[i]); + } + } +} + +static void AddIWADParameter(execute_context_t *exec) +{ + if (iwadfile != NULL) + { + AddCmdLineParameter(exec, "-iwad %s", iwadfile); + } +} + +static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) +{ + execute_context_t *exec; + + exec = NewExecuteContext(); + + // Extra parameters come first, before all others; this way, + // they can override any of the options set in the dialog. + + AddExtraParameters(exec); + + AddIWADParameter(exec); + AddCmdLineParameter(exec, "-server"); + AddCmdLineParameter(exec, "-skill %i", skill + 1); + + if (nomonsters) + { + AddCmdLineParameter(exec, "-nomonsters"); + } + + if (fast) + { + AddCmdLineParameter(exec, "-fast"); + } + + if (respawn) + { + AddCmdLineParameter(exec, "-respawn"); + } + + if (deathmatch == 1) + { + AddCmdLineParameter(exec, "-deathmatch"); + } + else if (deathmatch == 2) + { + AddCmdLineParameter(exec, "-altdeath"); + } + + if (timer > 0) + { + AddCmdLineParameter(exec, "-timer %i", timer); + } + + if (warptype == WARP_DOOM1) + { + // TODO: select IWAD based on warp type + AddCmdLineParameter(exec, "-warp %i %i", warpepisode, warpmap); + } + else if (warptype == WARP_DOOM2) + { + AddCmdLineParameter(exec, "-warp %i", warpmap); + } + + AddCmdLineParameter(exec, "-port %i", udpport); + + AddWADs(exec); + + TXT_Shutdown(); + + M_SaveDefaults(); + AddConfigParameters(exec); + + ExecuteDoom(exec); + + exit(0); +} + +static void UpdateWarpButton(void) +{ + char buf[10]; + + if (warptype == WARP_DOOM1) + { + sprintf(buf, "E%iM%i", warpepisode, warpmap); + } + else if (warptype == WARP_DOOM2) + { + sprintf(buf, "MAP%02i", warpmap); + } + + TXT_SetButtonLabel(warpbutton, buf); +} + +static void UpdateSkillButton(void) +{ + iwad_t *iwad = GetCurrentIWAD(); + + if (iwad->mask == IWAD_CHEX) + { + skillbutton->values = chex_skills; + } + else + { + skillbutton->values = skills; + } +} + +static void SetDoom1Warp(TXT_UNCAST_ARG(widget), void *val) +{ + int l; + + l = (int) val; + + warpepisode = l / 10; + warpmap = l % 10; + + UpdateWarpButton(); +} + +static void SetDoom2Warp(TXT_UNCAST_ARG(widget), void *val) +{ + int l; + + l = (int) val; + + warpmap = l; + + UpdateWarpButton(); +} + +static void CloseLevelSelectDialog(TXT_UNCAST_ARG(button), TXT_UNCAST_ARG(window)) +{ + TXT_CAST_ARG(txt_window_t, window); + + TXT_CloseWindow(window); +} + +static void LevelSelectDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) +{ + txt_window_t *window; + txt_table_t *table; + txt_button_t *button; + iwad_t *iwad; + char buf[10]; + int x, y; + int l; + int i; + + window = TXT_NewWindow("Select level"); + + table = TXT_NewTable(4); + + TXT_AddWidget(window, table); + + if (warptype == WARP_DOOM1) + { + // ExMy levels + + iwad = GetCurrentIWAD(); + + for (i=0; i<4 * 9; ++i) + { + x = (i % 4) + 1; + y = (i / 4) + 1; + + // chex.wad only has E1M1-E1M5. + + if (iwad->mask == IWAD_CHEX && (x > 1 || y > 5)) + { + continue; + } + + // doom1.wad only has E1 + + if (iwad->mask == IWAD_DOOM1 && x > 1) + { + continue; + } + + sprintf(buf, " E%iM%i ", x, y); + button = TXT_NewButton(buf); + TXT_SignalConnect(button, "pressed", + SetDoom1Warp, (void *) (x * 10 + y)); + TXT_SignalConnect(button, "pressed", + CloseLevelSelectDialog, window); + TXT_AddWidget(table, button); + + if (warpepisode == x && warpmap == y) + { + TXT_SelectWidget(table, button); + } + } + } + else + { + for (i=0; i<32; ++i) + { + x = i % 4; + y = i / 4; + + l = x * 8 + y + 1; + + sprintf(buf, " MAP%02i ", l); + button = TXT_NewButton(buf); + TXT_SignalConnect(button, "pressed", + SetDoom2Warp, (void *) l); + TXT_SignalConnect(button, "pressed", + CloseLevelSelectDialog, window); + TXT_AddWidget(table, button); + + if (warpmap == l) + { + TXT_SelectWidget(table, button); + } + } + } +} + +static void IWADSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + iwad_t *iwad; + + // Find the iwad_t selected + + iwad = GetCurrentIWAD(); + + // Update iwadfile + + iwadfile = iwad->filename; +} + +// Called when the IWAD button is changed, to update warptype. + +static void UpdateWarpType(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + warptype_t new_warptype; + iwad_t *iwad; + + // Get the selected IWAD + + iwad = GetIWADForDescription(found_iwads[found_iwad_selected]); + + // Find the new warp type + + if (iwad->mask & (IWAD_DOOM | IWAD_DOOM1 | IWAD_CHEX)) + { + new_warptype = WARP_DOOM1; + } + else + { + new_warptype = WARP_DOOM2; + } + + // Reset to E1M1 / MAP01 when the warp type is changed. + + if (new_warptype != warptype) + { + warpepisode = 1; + warpmap = 1; + } + + warptype = new_warptype; + + UpdateWarpButton(); + UpdateSkillButton(); +} + +static txt_widget_t *IWADSelector(void) +{ + txt_dropdown_list_t *dropdown; + txt_widget_t *result; + int installed_iwads; + int num_iwads; + unsigned int i; + + // Find out what WADs are installed + + installed_iwads = FindInstalledIWADs(); + + // Build a list of the descriptions for all installed IWADs + + num_iwads = 0; + + for (i=0; i<arrlen(iwads); ++i) + { + if (installed_iwads & iwads[i].mask) + { + found_iwads[num_iwads] = iwads[i].description; + ++num_iwads; + } + } + + // If no IWADs are found, provide Doom 2 as an option, but + // we're probably screwed. + + if (num_iwads == 0) + { + found_iwads[0] = "Doom 2"; + num_iwads = 1; + } + + // Build a dropdown list of IWADs + + if (num_iwads < 2) + { + // We have only one IWAD. Show as a label. + + result = (txt_widget_t *) TXT_NewLabel(found_iwads[0]); + } + else + { + // Dropdown list allowing IWAD to be selected. + + dropdown = TXT_NewDropdownList(&found_iwad_selected, + found_iwads, num_iwads); + + TXT_SignalConnect(dropdown, "changed", IWADSelected, NULL); + + result = (txt_widget_t *) dropdown; + } + + // Select first in the list. + + found_iwad_selected = 0; + IWADSelected(NULL, NULL); + + return result; +} + +static txt_window_action_t *StartGameAction(void) +{ + txt_window_action_t *action; + + action = TXT_NewWindowAction(KEY_F10, "Start"); + TXT_SignalConnect(action, "pressed", StartGame, NULL); + + return action; +} + +static void OpenWadsWindow(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) +{ + txt_window_t *window; + int i; + + window = TXT_NewWindow("Add WADs"); + + for (i=0; i<NUM_WADS; ++i) + { + TXT_AddWidget(window, TXT_NewInputBox(&wads[i], 60)); + } +} + +static void OpenExtraParamsWindow(TXT_UNCAST_ARG(widget), + TXT_UNCAST_ARG(user_data)) +{ + txt_window_t *window; + int i; + + window = TXT_NewWindow("Extra command line parameters"); + + for (i=0; i<NUM_EXTRA_PARAMS; ++i) + { + TXT_AddWidget(window, TXT_NewInputBox(&extra_params[i], 70)); + } +} + +static txt_window_action_t *WadWindowAction(void) +{ + txt_window_action_t *action; + + action = TXT_NewWindowAction('w', "Add WADs"); + TXT_SignalConnect(action, "pressed", OpenWadsWindow, NULL); + + return action; +} + +void StartMultiGame(void) +{ + txt_window_t *window; + txt_table_t *gameopt_table; + txt_table_t *advanced_table; + txt_widget_t *iwad_selector; + + window = TXT_NewWindow("Start multiplayer game"); + + TXT_AddWidgets(window, + gameopt_table = TXT_NewTable(2), + TXT_NewSeparator("Monster options"), + TXT_NewInvertedCheckBox("Monsters enabled", &nomonsters), + TXT_NewCheckBox("Fast monsters", &fast), + TXT_NewCheckBox("Respawning monsters", &respawn), + TXT_NewSeparator("Advanced"), + advanced_table = TXT_NewTable(2), + TXT_NewButton2("Add extra parameters...", + OpenExtraParamsWindow, NULL), + NULL); + + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction()); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, StartGameAction()); + + TXT_SetColumnWidths(gameopt_table, 12, 12); + + TXT_AddWidgets(gameopt_table, + TXT_NewLabel("Game"), + iwad_selector = IWADSelector(), + TXT_NewLabel("Skill"), + skillbutton = TXT_NewDropdownList(&skill, skills, 5), + TXT_NewLabel("Game type"), + TXT_NewDropdownList(&deathmatch, gamemodes, 3), + TXT_NewLabel("Level warp"), + warpbutton = TXT_NewButton2("????", LevelSelectDialog, NULL), + TXT_NewLabel("Time limit"), + TXT_NewHorizBox(TXT_NewIntInputBox(&timer, 2), + TXT_NewLabel("minutes"), + NULL), + NULL); + + TXT_SetColumnWidths(advanced_table, 12, 12); + + TXT_SignalConnect(iwad_selector, "changed", UpdateWarpType, NULL); + + TXT_AddWidgets(advanced_table, + TXT_NewLabel("UDP port"), + TXT_NewIntInputBox(&udpport, 5), + NULL); + + UpdateWarpType(NULL, NULL); + UpdateWarpButton(); +} + +static void DoJoinGame(void *unused1, void *unused2) +{ + execute_context_t *exec; + + exec = NewExecuteContext(); + + AddCmdLineParameter(exec, "-connect %s", connect_address); + + // Extra parameters come first, so that they can be used to override + // the other parameters. + + AddExtraParameters(exec); + AddIWADParameter(exec); + AddWADs(exec); + + TXT_Shutdown(); + + M_SaveDefaults(); + + AddConfigParameters(exec); + + ExecuteDoom(exec); + + exit(0); +} + +static txt_window_action_t *JoinGameAction(void) +{ + txt_window_action_t *action; + + action = TXT_NewWindowAction(KEY_F10, "Connect"); + TXT_SignalConnect(action, "pressed", DoJoinGame, NULL); + + return action; +} + +void JoinMultiGame(void) +{ + txt_window_t *window; + txt_table_t *gameopt_table; + + window = TXT_NewWindow("Join multiplayer game"); + + TXT_AddWidgets(window, + gameopt_table = TXT_NewTable(2), + TXT_NewStrut(0, 1), + TXT_NewButton2("Add extra parameters...", OpenExtraParamsWindow, NULL), + // TXT_NewButton2("Add WADs...", OpenWadsWindow, NULL), + NULL); + + TXT_SetColumnWidths(gameopt_table, 12, 12); + + TXT_AddWidgets(gameopt_table, + TXT_NewLabel("Game"), + IWADSelector(), + TXT_NewLabel("Server address "), + TXT_NewInputBox(&connect_address, 40), + NULL); + + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, WadWindowAction()); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, JoinGameAction()); +} + +void SetChatMacroDefaults(void) +{ + int i; + char *defaults[] = + { + HUSTR_CHATMACRO1, + HUSTR_CHATMACRO2, + HUSTR_CHATMACRO3, + HUSTR_CHATMACRO4, + HUSTR_CHATMACRO5, + HUSTR_CHATMACRO6, + HUSTR_CHATMACRO7, + HUSTR_CHATMACRO8, + HUSTR_CHATMACRO9, + HUSTR_CHATMACRO0, + }; + + // If the chat macros have not been set, initialise with defaults. + + for (i=0; i<10; ++i) + { + if (chat_macros[i] == NULL) + { + chat_macros[i] = strdup(defaults[i]); + } + } +} + +void SetPlayerNameDefault(void) +{ + if (net_player_name == NULL) + { + net_player_name = getenv("USER"); + } + + if (net_player_name == NULL) + { + net_player_name = getenv("USERNAME"); + } + + if (net_player_name == NULL) + { + net_player_name = "player"; + } +} + +void MultiplayerConfig(void) +{ + txt_window_t *window; + txt_label_t *label; + txt_table_t *table; + char buf[10]; + int i; + + window = TXT_NewWindow("Multiplayer Configuration"); + + TXT_AddWidgets(window, + TXT_NewStrut(0, 1), + TXT_NewHorizBox(TXT_NewLabel("Player name: "), + TXT_NewInputBox(&net_player_name, 25), + NULL), + TXT_NewStrut(0, 1), + TXT_NewSeparator("Chat macros"), + NULL); + + table = TXT_NewTable(2); + + for (i=0; i<10; ++i) + { + sprintf(buf, "#%i ", i + 1); + + label = TXT_NewLabel(buf); + TXT_SetFGColor(label, TXT_COLOR_BRIGHT_CYAN); + + TXT_AddWidgets(table, + label, + TXT_NewInputBox(&chat_macros[(i + 1) % 10], 40), + NULL); + } + + TXT_AddWidget(window, table); +} + +void BindMultiplayerVariables(void) +{ + char buf[15]; + int i; + +#ifdef FEATURE_MULTIPLAYER + M_BindVariable("player_name", &net_player_name); +#endif + + for (i=0; i<10; ++i) + { + sprintf(buf, "chatmacro%i", i); + M_BindVariable(buf, &chat_macros[i]); + } +} + diff --git a/src/setup/multiplayer.h b/src/setup/multiplayer.h new file mode 100644 index 00000000..7490bc3c --- /dev/null +++ b/src/setup/multiplayer.h @@ -0,0 +1,35 @@ +// 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. +// + +#ifndef SETUP_MULTIPLAYER_H +#define SETUP_MULTIPLAYER_H + +void StartMultiGame(void); +void JoinMultiGame(void); +void MultiplayerConfig(void); + +void SetChatMacroDefaults(void); +void SetPlayerNameDefault(void); + +void BindMultiplayerVariables(void); + +#endif /* #ifndef SETUP_MULTIPLAYER_H */ + diff --git a/src/setup/setup-manifest.xml b/src/setup/setup-manifest.xml new file mode 100644 index 00000000..74dd5493 --- /dev/null +++ b/src/setup/setup-manifest.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> + <!-- The "name" field in this tag should be the same as the executable's + name --> + <assemblyIdentity version="1.1.1.0" processorArchitecture="*" + name="chocolate-setup" type="win32"/> + <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> + <security> + <requestedPrivileges> + <!-- Hi Vista! We don't require elevated privileges. Thanks! --> + <requestedExecutionLevel level="asInvoker"/> + </requestedPrivileges> + </security> + </trustInfo> +</assembly> + diff --git a/src/setup/setup_icon.c b/src/setup/setup_icon.c new file mode 100644 index 00000000..1c18c56f --- /dev/null +++ b/src/setup/setup_icon.c @@ -0,0 +1,262 @@ +static int setup_icon_w = 32; +static int setup_icon_h = 32; + +static unsigned char setup_icon_data[] = { + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xa2,0x86,0x73, + 0xa9,0x8d,0x7a, 0xbc,0x9f,0x8c, 0xda,0xba,0xa0, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0xbe,0x8e,0x68, 0xd7,0xb9,0xa5, 0xeb,0xd8,0xcd, 0xd3,0xbf,0xae, + 0xbe,0xa1,0x8d, 0xeb,0xd8,0xcd, 0xc2,0x9d,0x86, 0x95,0x5d,0x38, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x78,0x7a,0x77, 0x78,0x7a,0x77, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x78,0x7a,0x77, 0x78,0x7a,0x77, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x9f,0x82,0x6a, + 0xc5,0x9e,0x81, 0xd1,0xb2,0x98, 0xd4,0xac,0x8e, 0xeb,0xd8,0xcd, + 0xc4,0x9b,0x79, 0xad,0x71,0x45, 0xd4,0xac,0x8e, 0xb9,0x93,0x76, + 0xa1,0x75,0x56, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x78,0x7a,0x77, 0x6d,0x6f,0x6c, 0xcb,0xce,0xca, + 0x51,0x52,0x50, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x5b,0x5d,0x5a, + 0xca,0xcc,0xc9, 0x77,0x79,0x76, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0xda,0xb4,0x9c, 0xd3,0xa3,0x83, + 0xaf,0x91,0x78, 0xa7,0x83,0x6d, 0xc4,0xa7,0x93, 0xee,0xe2,0xd5, + 0xeb,0xd8,0xcd, 0x8c,0x60,0x3d, 0x92,0x6f,0x59, 0xd0,0xa7,0x84, + 0x84,0x54,0x33, 0xba,0x83,0x5b, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x78,0x7a,0x77, 0xa0,0xa2,0x9f, 0xdf,0xe1,0xde, + 0x58,0x5a,0x58, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x64,0x65,0x63, + 0xdd,0xdf,0xdc, 0xa8,0xaa,0xa7, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0xd4,0xb5,0x9b, 0xc3,0x8c,0x63, 0xc4,0x94,0x6e, + 0x98,0x66,0x45, 0x78,0x50,0x2d, 0xd7,0xb9,0xa5, 0xee,0xdc,0xd1, + 0xc4,0x9b,0x79, 0xb6,0x80,0x58, 0x65,0x45,0x26, 0xb6,0x79,0x4d, + 0xcf,0xa5,0x83, 0x9a,0x6e,0x50, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x82,0x83,0x81, 0xbb,0xbd,0xba, 0xde,0xe0,0xdd, + 0x58,0x5a,0x58, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x64,0x65,0x63, + 0xdc,0xde,0xdb, 0xc4,0xc6,0xc3, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x9e,0x7b,0x65, 0xbc,0x8c,0x67, 0xaa,0x7d,0x5e, 0xa1,0x75,0x56, + 0x89,0x5f,0x41, 0xc4,0xa7,0x93, 0xb7,0x88,0x63, 0x90,0x6c,0x51, + 0x79,0x4b,0x2b, 0x8c,0x5b,0x34, 0x76,0x4e,0x31, 0x7f,0x50,0x30, + 0xcf,0xa5,0x83, 0xd4,0xac,0x8e, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x77,0x79,0x76, 0xd2,0xd4,0xd1, 0xde,0xe0,0xdd, + 0x64,0x65,0x63, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x68,0x69,0x67, + 0xdb,0xdd,0xda, 0xda,0xdc,0xd9, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xd8,0xb8,0x9e, + 0xd4,0xac,0x8e, 0xc5,0x9e,0x81, 0xab,0x7e,0x5f, 0x9c,0x6f,0x4b, + 0xbe,0xa1,0x8d, 0x8c,0x60,0x3d, 0x6e,0x47,0x2b, 0x87,0x5e,0x40, + 0x5a,0x3b,0x23, 0x68,0x42,0x26, 0x65,0x40,0x23, 0x53,0x36,0x22, + 0x7e,0x55,0x38, 0xce,0x9f,0x7e, 0xc3,0x8c,0x63, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x77,0x79,0x76, 0xe1,0xe4,0xe0, 0xe1,0xe4,0xe0, + 0xc4,0xc6,0xc3, 0x83,0x85,0x82, 0x8c,0x8d,0x8a, 0xd2,0xd4,0xd1, + 0xee,0xdc,0xd1, 0xe1,0xe4,0xe0, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xcb,0x9a,0x74, + 0xb6,0x80,0x58, 0x8c,0x60,0x3d, 0x76,0x4e,0x31, 0x88,0x57,0x31, + 0x83,0x53,0x33, 0x84,0x54,0x33, 0x95,0x5d,0x38, 0x79,0x4b,0x2b, + 0x5c,0x38,0x22, 0x84,0x54,0x33, 0x55,0x37,0x1e, 0x96,0x6b,0x4d, + 0xb4,0x7f,0x5c, 0xba,0x83,0x5b, 0xb8,0x7b,0x4f, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x9a,0x9b,0x98, 0xd9,0xdb,0xd7, + 0xe1,0xe4,0xe0, 0xde,0xe0,0xdd, 0xdd,0xdf,0xdc, 0xe0,0xe2,0xdf, + 0xda,0xdc,0xd9, 0xa3,0xa5,0xa1, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xc0,0x89,0x60, + 0x89,0x5f,0x41, 0x84,0x54,0x33, 0x84,0x54,0x33, 0x8a,0x5a,0x39, + 0x8f,0x5d,0x37, 0x78,0x50,0x2d, 0x8c,0x5b,0x34, 0x5a,0x3b,0x23, + 0x5e,0x3f,0x27, 0x76,0x4e,0x31, 0x97,0x64,0x3d, 0x74,0x4b,0x29, + 0x78,0x50,0x2d, 0x7b,0x4d,0x2c, 0xb6,0x80,0x58, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x64,0x65,0x63, + 0xbe,0xc1,0xbd, 0xee,0xdc,0xd1, 0xe1,0xe4,0xe0, 0xc2,0xc4,0xc1, + 0x68,0x69,0x67, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x95,0x62,0x3b, + 0x84,0x54,0x33, 0x88,0x57,0x31, 0x7e,0x6e,0x64, 0xc4,0x94,0x6e, + 0x76,0x4e,0x31, 0x90,0x6c,0x51, 0xa1,0x7c,0x60, 0x9a,0x6e,0x50, + 0x95,0x5d,0x38, 0xbc,0x7f,0x53, 0xad,0x71,0x45, 0x76,0x4e,0x31, + 0x53,0x36,0x22, 0x4b,0x2f,0x1c, 0x70,0x49,0x2c, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x51,0x52,0x50, 0xd2,0xd4,0xd1, 0xe0,0xe2,0xdf, 0x77,0x79,0x76, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x84,0x54,0x33, + 0xa3,0x86,0x6e, 0xc4,0x94,0x6e, 0x88,0x64,0x44, 0xbc,0x8c,0x67, + 0x9c,0x6f,0x4b, 0xa1,0x6d,0x45, 0x93,0x60,0x3a, 0xad,0x71,0x3f, + 0xb4,0x7f,0x5c, 0xbc,0x8c,0x67, 0xc0,0x89,0x60, 0xb3,0x76,0x4b, + 0xb8,0x7b,0x4f, 0x88,0x64,0x44, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x4a,0x4b,0x49, 0xdc,0xde,0xdb, 0xe1,0xe4,0xe0, 0x79,0x7b,0x78, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xa7,0x83,0x6d, + 0xac,0x86,0x6a, 0x76,0x4e,0x31, 0x84,0x54,0x33, 0x5c,0x38,0x22, + 0x57,0x38,0x20, 0x6c,0x46,0x29, 0x95,0x62,0x3b, 0xa3,0x6e,0x41, + 0xb3,0x76,0x4b, 0xb8,0x7b,0x4f, 0x9d,0x64,0x3f, 0x7e,0x4f,0x2f, + 0x63,0x3e,0x27, 0x95,0x62,0x3b, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x51,0x52,0x50, 0xdd,0xdf,0xdc, 0xe0,0xe2,0xdf, 0x82,0x83,0x81, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xb6,0x80,0x58, + 0x98,0x74,0x59, 0x67,0x41,0x25, 0x4b,0x35,0x25, 0x81,0x52,0x31, + 0x76,0x4e,0x31, 0x7b,0x4d,0x2c, 0x7e,0x4f,0x2f, 0x84,0x54,0x33, + 0x8f,0x5d,0x37, 0x95,0x5d,0x38, 0x78,0x50,0x2d, 0x65,0x45,0x26, + 0x65,0x40,0x23, 0x7e,0x4f,0x2f, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x55,0x56,0x54, 0xee,0xdc,0xd1, 0xde,0xe0,0xdd, 0x8c,0x8d,0x8a, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xb4,0x7f,0x5c, + 0x86,0x56,0x35, 0x8c,0x60,0x3d, 0x89,0x5f,0x41, 0x63,0x44,0x2b, + 0x57,0x38,0x20, 0x86,0x56,0x35, 0x88,0x57,0x31, 0x95,0x5d,0x38, + 0x97,0x64,0x3d, 0x63,0x3e,0x27, 0x50,0x33,0x20, 0x78,0x50,0x2d, + 0x78,0x50,0x2d, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x58,0x5a,0x58, 0xe0,0xe2,0xdf, 0xde,0xe0,0xdd, 0x8c,0x8d,0x8a, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x86,0x56,0x35, 0x63,0x3e,0x27, 0xa8,0x6d,0x42, 0x50,0x33,0x20, + 0x63,0x3e,0x27, 0x74,0x4b,0x29, 0x53,0x36,0x22, 0x78,0x50,0x2d, + 0x42,0x30,0x14, 0x4d,0x3e,0x15, 0x4d,0x3e,0x15, 0x7c,0x5b,0x29, + 0x8a,0x71,0x27, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x64,0x65,0x63, 0xe1,0xe4,0xe0, 0xe1,0xe4,0xe0, 0x91,0x93,0x90, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x6e,0x47,0x2b, 0x65,0x45,0x26, 0x5d,0x42,0x22, 0x65,0x45,0x26, + 0x78,0x50,0x2d, 0x5d,0x42,0x22, 0x5e,0x3f,0x27, 0x4d,0x3e,0x15, + 0x4d,0x3e,0x15, 0x67,0x58,0x21, 0x4f,0x44,0x19, 0x5f,0x51,0x19, + 0x8a,0x76,0x2a, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x68,0x69,0x67, 0xdf,0xe1,0xde, 0xe0,0xe2,0xdf, 0x9a,0x9b,0x98, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x8a,0x71,0x27, 0x53,0x46,0x15, + 0x53,0x46,0x15, 0x67,0x58,0x21, 0x58,0x4c,0x1b, 0x5b,0x4f,0x1d, + 0x5b,0x4f,0x1d, 0x67,0x58,0x21, 0x5b,0x4f,0x1d, 0x8a,0x71,0x27, + 0x8c,0x77,0x24, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x70,0x72,0x6f, 0xe1,0xe4,0xe0, 0xe1,0xe4,0xe0, 0x9a,0x9b,0x98, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0xac,0x93,0x39, 0x7e,0x66,0x23, + 0x69,0x5a,0x1b, 0x6b,0x5b,0x1d, 0x67,0x58,0x21, 0x53,0x46,0x15, + 0x4d,0x3e,0x15, 0x9f,0x88,0x35, 0xb7,0x9c,0x3b, 0xac,0x93,0x39, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x77,0x79,0x76, 0xdf,0xe1,0xde, 0xe0,0xe2,0xdf, 0xa3,0xa5,0xa1, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0xb1,0x97,0x36, 0x6f,0x5f,0x21, + 0x7e,0x66,0x23, 0x8c,0x77,0x24, 0x84,0x70,0x24, 0x78,0x67,0x22, + 0x8e,0x79,0x26, 0x8a,0x71,0x27, 0xb7,0x9c,0x3b, 0x9b,0x84,0x29, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x82,0x83,0x81, 0xe1,0xe4,0xe0, 0xe1,0xe4,0xe0, 0xa8,0xaa,0xa7, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0xac,0x93,0x39, 0x89,0x75,0x29, + 0x7e,0x66,0x23, 0x75,0x64,0x1f, 0x94,0x7e,0x2b, 0x7e,0x66,0x23, + 0x9f,0x88,0x35, 0xb6,0x9d,0x4a, 0xb6,0x9d,0x4a, 0xc4,0xa8,0x3f, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x82,0x83,0x81, 0xe0,0xe2,0xdf, 0xde,0xe0,0xdd, 0xab,0xad,0xaa, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x80,0x6d,0x28, + 0xac,0x93,0x39, 0x97,0x82,0x36, 0xac,0x94,0x41, 0xac,0x93,0x39, + 0x97,0x82,0x36, 0xa2,0x8a,0x30, 0xbd,0xa3,0x48, 0x8a,0x71,0x27, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x77,0x79,0x76, 0xe0,0xe2,0xdf, 0xd8,0xda,0xd6, 0xab,0xad,0xaa, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xae,0x95,0x33, + 0x7e,0x66,0x23, 0x9f,0x88,0x35, 0x9f,0x88,0x35, 0x7e,0x66,0x23, + 0x8a,0x71,0x27, 0xaf,0x96,0x3c, 0xbd,0xa2,0x41, 0x8a,0x76,0x2a, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x68,0x69,0x67, + 0xc2,0xc4,0xc1, 0xe0,0xe2,0xdf, 0xdf,0xe1,0xde, 0xbe,0xc1,0xbd, + 0x5f,0x61,0x5e, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xaf,0x96,0x3c, + 0x87,0x73,0x27, 0xb2,0x99,0x3f, 0x6f,0x5f,0x21, 0xa8,0x90,0x36, + 0x97,0x82,0x36, 0x9f,0x88,0x35, 0xb7,0x9c,0x3b, 0x8c,0x77,0x24, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0xa3,0xa5,0xa1, 0xeb,0xd8,0xcd, + 0xe0,0xe2,0xdf, 0xee,0xdc,0xd1, 0xdf,0xe1,0xde, 0xe1,0xe4,0xe0, + 0xda,0xdc,0xd9, 0x9a,0x9b,0x98, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0xb2,0x99,0x3f, + 0xaf,0x96,0x3c, 0x96,0x80,0x2d, 0xbd,0xa3,0x48, 0x97,0x82,0x36, + 0xb6,0x9d,0x4a, 0xb8,0xa0,0x4c, 0xc1,0xa7,0x4c, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x78,0x7a,0x77, 0xdf,0xe1,0xde, 0xe0,0xe2,0xdf, + 0xd2,0xd4,0xd1, 0x8c,0x8d,0x8a, 0x82,0x83,0x81, 0xc7,0xc9,0xc6, + 0xe1,0xe4,0xe0, 0xe1,0xe4,0xe0, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x96,0x80,0x2d, 0xb5,0x9c,0x49, 0xb2,0x99,0x3f, 0xb2,0x9a,0x47, + 0xb0,0x97,0x3d, 0xc1,0xa7,0x4c, 0x96,0x80,0x2d, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x78,0x7a,0x77, 0xd9,0xdb,0xd7, 0xda,0xdc,0xd9, + 0x68,0x69,0x67, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x64,0x65,0x63, + 0xdd,0xdf,0xdc, 0xd2,0xd4,0xd1, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x9c,0x85,0x2b, 0xaa,0x91,0x2f, 0xb1,0x97,0x36, 0xa2,0x8a,0x30, + 0x7e,0x66,0x23, 0xb1,0x97,0x36, 0xb4,0x99,0x30, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x79,0x7b,0x78, 0xc4,0xc6,0xc3, 0xd9,0xdb,0xd7, + 0x64,0x65,0x63, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x55,0x56,0x54, + 0xdf,0xe1,0xde, 0xbb,0xbd,0xba, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x9f,0x88,0x35, 0xb8,0x9e,0x44, 0x8a,0x71,0x27, 0xa6,0x8f,0x3c, + 0xbd,0xa3,0x48, 0x96,0x80,0x2d, 0x9f,0x88,0x35, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x82,0x83,0x81, 0xa8,0xaa,0xa7, 0xdf,0xe1,0xde, + 0x64,0x65,0x63, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x58,0x5a,0x58, + 0xee,0xdc,0xd1, 0xa0,0xa2,0x9f, 0x78,0x7a,0x77, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0xb0,0x97,0x3d, 0xb7,0x9c,0x3b, 0xac,0x94,0x41, 0xb2,0x99,0x3f, + 0xb6,0x9b,0x32, 0xb7,0x9c,0x3b, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x77,0x79,0x76, 0x77,0x79,0x76, 0xca,0xcc,0xc9, + 0x5b,0x5d,0x5a, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x51,0x52,0x50, + 0xcb,0xce,0xca, 0x68,0x69,0x67, 0x79,0x7b,0x78, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0xbd,0xa2,0x41, 0xa6,0x8f,0x3c, 0xb0,0x97,0x3d, 0xb2,0x9a,0x47, + 0xac,0x93,0x39, 0x9f,0x88,0x35, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x77,0x79,0x76, 0x78,0x7a,0x77, + 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, + 0x82,0x83,0x81, 0x79,0x7b,0x78, 0x00,0x00,0x00, 0x00,0x00,0x00, + +}; diff --git a/src/setup/sound.c b/src/setup/sound.c new file mode 100644 index 00000000..0361ac62 --- /dev/null +++ b/src/setup/sound.c @@ -0,0 +1,241 @@ +// 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. +// + +// Sound control menu + +#include <stdlib.h> + +#include "textscreen.h" +#include "m_config.h" + +#include "i_sound.h" +#include "mode.h" +#include "sound.h" + +typedef enum +{ + SFXMODE_DISABLED, + SFXMODE_DIGITAL, + SFXMODE_PCSPEAKER, + NUM_SFXMODES +} sfxmode_t; + +static char *sfxmode_strings[] = +{ + "Disabled", + "Digital", + "PC speaker" +}; + +typedef enum +{ + MUSICMODE_DISABLED, + MUSICMODE_MIDI, + MUSICMODE_CD, + NUM_MUSICMODES +} musicmode_t; + +static char *musicmode_strings[] = +{ + "Disabled", + "MIDI", + "CD audio" +}; + +// Disable MIDI music on OSX: there are problems with the native +// MIDI code in SDL_mixer. + +#ifdef __MACOSX__ +#define DEFAULT_MUSIC_DEVICE SNDDEVICE_NONE +#else +#define DEFAULT_MUSIC_DEVICE SNDDEVICE_SB +#endif + +// Config file variables: + +int snd_sfxdevice = SNDDEVICE_SB; +int snd_musicdevice = DEFAULT_MUSIC_DEVICE; +int snd_samplerate = 22050; + +static int numChannels = 8; +static int sfxVolume = 15; +static int musicVolume = 15; +static int use_libsamplerate = 0; + +// DOS specific variables: these are unused but should be maintained +// so that the config file can be shared between chocolate +// doom and doom.exe + +static int snd_sbport = 0; +static int snd_sbirq = 0; +static int snd_sbdma = 0; +static int snd_mport = 0; + +// GUI variables: + +static int snd_sfxmode; +static int snd_musicmode; + +static void UpdateSndDevices(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) +{ + switch (snd_sfxmode) + { + case SFXMODE_DISABLED: + snd_sfxdevice = SNDDEVICE_NONE; + break; + case SFXMODE_PCSPEAKER: + snd_sfxdevice = SNDDEVICE_PCSPEAKER; + break; + case SFXMODE_DIGITAL: + snd_sfxdevice = SNDDEVICE_SB; + break; + } + + switch (snd_musicmode) + { + case MUSICMODE_DISABLED: + snd_musicdevice = SNDDEVICE_NONE; + break; + case MUSICMODE_MIDI: + snd_musicdevice = SNDDEVICE_SB; + break; + case MUSICMODE_CD: + break; + } +} + +void ConfigSound(void) +{ + txt_window_t *window; + txt_table_t *sfx_table; + txt_table_t *music_table; + txt_dropdown_list_t *sfx_mode_control; + txt_dropdown_list_t *music_mode_control; + int num_sfx_modes, num_music_modes; + + // Work out what sfx mode we are currently using: + + if (snd_sfxdevice == SNDDEVICE_PCSPEAKER) + { + snd_sfxmode = SFXMODE_PCSPEAKER; + } + else if (snd_sfxdevice >= SNDDEVICE_SB) + { + snd_sfxmode = SFXMODE_DIGITAL; + } + else + { + snd_sfxmode = SFXMODE_DISABLED; + } + + // Is music enabled? + + if (snd_musicdevice == SNDDEVICE_NONE) + { + snd_musicmode = MUSICMODE_DISABLED; + } + else if (snd_musicmode == SNDDEVICE_CD) + { + snd_musicmode = MUSICMODE_CD; + } + else + { + snd_musicmode = MUSICMODE_MIDI; + } + + // Doom has PC speaker sound effects, but others do not: + + if (gamemission == doom) + { + num_sfx_modes = NUM_SFXMODES; + } + else + { + num_sfx_modes = NUM_SFXMODES - 1; + } + + // Hexen has CD audio; others do not. + + if (gamemission == hexen) + { + num_music_modes = NUM_MUSICMODES; + } + else + { + num_music_modes = NUM_MUSICMODES - 1; + } + + // Build the window + + window = TXT_NewWindow("Sound configuration"); + + TXT_AddWidgets(window, + TXT_NewSeparator("Sound effects"), + sfx_table = TXT_NewTable(2), + TXT_NewSeparator("Music"), + music_table = TXT_NewTable(2), + NULL); + + TXT_SetColumnWidths(sfx_table, 20, 5); + + TXT_AddWidgets(sfx_table, + TXT_NewLabel("Sound effects"), + sfx_mode_control = TXT_NewDropdownList(&snd_sfxmode, + sfxmode_strings, + num_sfx_modes), + TXT_NewLabel("Sound channels"), + TXT_NewSpinControl(&numChannels, 1, 8), + TXT_NewLabel("SFX volume"), + TXT_NewSpinControl(&sfxVolume, 0, 15), + NULL); + + TXT_SetColumnWidths(music_table, 20, 5); + + TXT_AddWidgets(music_table, + TXT_NewLabel("Music"), + music_mode_control = TXT_NewDropdownList(&snd_musicmode, + musicmode_strings, + num_music_modes), + TXT_NewLabel("Music volume"), + TXT_NewSpinControl(&musicVolume, 0, 15), + NULL); + + TXT_SignalConnect(sfx_mode_control, "changed", UpdateSndDevices, NULL); + TXT_SignalConnect(music_mode_control, "changed", UpdateSndDevices, NULL); + +} + +void BindSoundVariables(void) +{ + M_BindVariable("snd_sfxdevice", &snd_sfxdevice); + M_BindVariable("snd_musicdevice", &snd_musicdevice); + M_BindVariable("snd_channels", &numChannels); + M_BindVariable("sfx_volume", &sfxVolume); + M_BindVariable("music_volume", &musicVolume); + M_BindVariable("snd_samplerate", &snd_samplerate); + M_BindVariable("use_libsamplerate", &use_libsamplerate); + + M_BindVariable("snd_sbport", &snd_sbport); + M_BindVariable("snd_sbirq", &snd_sbirq); + M_BindVariable("snd_sbdma", &snd_sbdma); + M_BindVariable("snd_mport", &snd_mport); +} + diff --git a/src/setup/sound.h b/src/setup/sound.h new file mode 100644 index 00000000..0b183502 --- /dev/null +++ b/src/setup/sound.h @@ -0,0 +1,29 @@ +// 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. +// + +#ifndef SETUP_SOUND_H +#define SETUP_SOUND_H + +void ConfigSound(void); +void BindSoundVariables(void); + +#endif /* #ifndef SETUP_SOUND_H */ + diff --git a/src/setup/txt_joybinput.c b/src/setup/txt_joybinput.c new file mode 100644 index 00000000..1e132962 --- /dev/null +++ b/src/setup/txt_joybinput.c @@ -0,0 +1,228 @@ +// 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "SDL_joystick.h" + +#include "doomkeys.h" +#include "joystick.h" + +#include "txt_joybinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_sdl.h" +#include "txt_window.h" + +#define JOYSTICK_INPUT_WIDTH 10 + +// Called in response to SDL events when the prompt window is open: + +static int EventCallback(SDL_Event *event, TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + // Got the joystick button press? + + if (event->type == SDL_JOYBUTTONDOWN) + { + *joystick_input->variable = event->jbutton.button; + TXT_EmitSignal(joystick_input, "set"); + TXT_CloseWindow(joystick_input->prompt_window); + return 1; + } + + return 0; +} + +// When the prompt window is closed, disable the event callback function; +// we are no longer interested in receiving notification of events. + +static void PromptWindowClosed(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(joystick)) +{ + TXT_CAST_ARG(SDL_Joystick, joystick); + + SDL_JoystickClose(joystick); + TXT_SDL_SetEventCallback(NULL, NULL); + SDL_JoystickEventState(SDL_DISABLE); + SDL_QuitSubSystem(SDL_INIT_JOYSTICK); +} + +static void OpenErrorWindow(void) +{ + txt_window_t *window; + + window = TXT_NewWindow(NULL); + + TXT_AddWidget(window, TXT_NewLabel("Please configure a joystick first!")); + + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowEscapeAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); +} + +static void OpenPromptWindow(txt_joystick_input_t *joystick_input) +{ + txt_window_t *window; + txt_label_t *label; + SDL_Joystick *joystick; + + if (SDL_Init(SDL_INIT_JOYSTICK) < 0) + { + return; + } + + // Check the current joystick is valid + + joystick = SDL_JoystickOpen(joystick_index); + + if (joystick == NULL) + { + OpenErrorWindow(); + return; + } + + // Open the prompt window + + window = TXT_NewWindow(NULL); + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + + label = TXT_NewLabel("Press the new joystick button..."); + + TXT_AddWidget(window, label); + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + TXT_SDL_SetEventCallback(EventCallback, joystick_input); + TXT_SignalConnect(window, "closed", PromptWindowClosed, joystick); + joystick_input->prompt_window = window; + + SDL_JoystickEventState(SDL_ENABLE); +} + +static void TXT_JoystickInputSizeCalc(TXT_UNCAST_ARG(joystick_input)) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + // All joystickinputs are the same size. + + joystick_input->widget.w = JOYSTICK_INPUT_WIDTH; + joystick_input->widget.h = 1; +} + +static void GetJoystickButtonDescription(int button, char *buf) +{ + sprintf(buf, "BUTTON #%i", button + 1); +} + +static void TXT_JoystickInputDrawer(TXT_UNCAST_ARG(joystick_input), int selected) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + char buf[20]; + int i; + + if (*joystick_input->variable < 0) + { + strcpy(buf, "(none)"); + } + else + { + GetJoystickButtonDescription(*joystick_input->variable, buf); + } + + if (selected) + { + TXT_BGColor(TXT_COLOR_GREY, 0); + } + else + { + TXT_BGColor(TXT_COLOR_BLUE, 0); + } + + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i=strlen(buf); i<JOYSTICK_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_JoystickInputDestructor(TXT_UNCAST_ARG(joystick_input)) +{ +} + +static int TXT_JoystickInputKeyPress(TXT_UNCAST_ARG(joystick_input), int joystick) +{ + TXT_CAST_ARG(txt_joystick_input_t, joystick_input); + + if (joystick == KEY_ENTER) + { + // Open a window to prompt for the new joystick press + + OpenPromptWindow(joystick_input); + + return 1; + } + + return 0; +} + +static void TXT_JoystickInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) +{ + TXT_CAST_ARG(txt_joystick_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_JoystickInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_joystick_input_class = +{ + TXT_JoystickInputSizeCalc, + TXT_JoystickInputDrawer, + TXT_JoystickInputKeyPress, + TXT_JoystickInputDestructor, + TXT_JoystickInputMousePress, + NULL, +}; + +txt_joystick_input_t *TXT_NewJoystickInput(int *variable) +{ + txt_joystick_input_t *joystick_input; + + joystick_input = malloc(sizeof(txt_joystick_input_t)); + + TXT_InitWidget(joystick_input, &txt_joystick_input_class); + joystick_input->variable = variable; + + return joystick_input; +} + diff --git a/src/setup/txt_joybinput.h b/src/setup/txt_joybinput.h new file mode 100644 index 00000000..b2920b88 --- /dev/null +++ b/src/setup/txt_joybinput.h @@ -0,0 +1,46 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// Copyright(C) 2007 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. +// + +#ifndef TXT_JOYB_INPUT_H +#define TXT_JOYB_INPUT_H + +typedef struct txt_joystick_input_s txt_joystick_input_t; + +#include "txt_widget.h" +#include "txt_window.h" + +// +// A joystick input is like an input box. When selected, a box pops up +// allowing a joystick button to be pressed to select it. +// + +struct txt_joystick_input_s +{ + txt_widget_t widget; + int *variable; + txt_window_t *prompt_window; +}; + +txt_joystick_input_t *TXT_NewJoystickInput(int *variable); + +#endif /* #ifndef TXT_JOYB_INPUT_H */ + + diff --git a/src/setup/txt_keyinput.c b/src/setup/txt_keyinput.c new file mode 100644 index 00000000..b7e68f44 --- /dev/null +++ b/src/setup/txt_keyinput.c @@ -0,0 +1,181 @@ +// 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> + +#include "doomkeys.h" + +#include "txt_keyinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_window.h" + +#define KEY_INPUT_WIDTH 8 + +static int KeyPressCallback(txt_window_t *window, int key, + TXT_UNCAST_ARG(key_input)) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + if (key != KEY_ESCAPE) + { + // Got the key press. Save to the variable and close the window. + + *key_input->variable = key; + TXT_EmitSignal(key_input, "set"); + TXT_CloseWindow(window); + + // Re-enable key mappings now that we have the key + + TXT_EnableKeyMapping(1); + + return 1; + } + else + { + return 0; + } +} + +static void OpenPromptWindow(txt_key_input_t *key_input) +{ + txt_window_t *window; + txt_label_t *label; + + window = TXT_NewWindow(NULL); + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + + label = TXT_NewLabel("Press the new key..."); + + TXT_AddWidget(window, label); + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + + TXT_SetKeyListener(window, KeyPressCallback, key_input); + + // Disable key mappings while we prompt for the key press + + TXT_EnableKeyMapping(0); +} + +static void TXT_KeyInputSizeCalc(TXT_UNCAST_ARG(key_input)) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + // All keyinputs are the same size. + + key_input->widget.w = KEY_INPUT_WIDTH; + key_input->widget.h = 1; +} + + +static void TXT_KeyInputDrawer(TXT_UNCAST_ARG(key_input), int selected) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + char buf[20]; + int i; + + if (*key_input->variable == 0) + { + strcpy(buf, ""); + } + else + { + TXT_GetKeyDescription(*key_input->variable, buf); + } + + if (selected) + { + TXT_BGColor(TXT_COLOR_GREY, 0); + } + else + { + TXT_BGColor(TXT_COLOR_BLUE, 0); + } + + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i=strlen(buf); i<KEY_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_KeyInputDestructor(TXT_UNCAST_ARG(key_input)) +{ +} + +static int TXT_KeyInputKeyPress(TXT_UNCAST_ARG(key_input), int key) +{ + TXT_CAST_ARG(txt_key_input_t, key_input); + + if (key == KEY_ENTER) + { + // Open a window to prompt for the new key press + + OpenPromptWindow(key_input); + + return 1; + } + + return 0; +} + +static void TXT_KeyInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) +{ + TXT_CAST_ARG(txt_key_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_KeyInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_key_input_class = +{ + TXT_KeyInputSizeCalc, + TXT_KeyInputDrawer, + TXT_KeyInputKeyPress, + TXT_KeyInputDestructor, + TXT_KeyInputMousePress, + NULL, +}; + +txt_key_input_t *TXT_NewKeyInput(int *variable) +{ + txt_key_input_t *key_input; + + key_input = malloc(sizeof(txt_key_input_t)); + + TXT_InitWidget(key_input, &txt_key_input_class); + key_input->variable = variable; + + return key_input; +} + diff --git a/src/setup/txt_keyinput.h b/src/setup/txt_keyinput.h new file mode 100644 index 00000000..4952a970 --- /dev/null +++ b/src/setup/txt_keyinput.h @@ -0,0 +1,44 @@ +// 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. +// + +#ifndef TXT_KEY_INPUT_H +#define TXT_KEY_INPUT_H + +typedef struct txt_key_input_s txt_key_input_t; + +#include "txt_widget.h" + +// +// A key input is like an input box. When selected, a box pops up +// allowing a key to be selected. +// + +struct txt_key_input_s +{ + txt_widget_t widget; + int *variable; +}; + +txt_key_input_t *TXT_NewKeyInput(int *variable); + +#endif /* #ifndef TXT_KEY_INPUT_H */ + + diff --git a/src/setup/txt_mouseinput.c b/src/setup/txt_mouseinput.c new file mode 100644 index 00000000..05c89b39 --- /dev/null +++ b/src/setup/txt_mouseinput.c @@ -0,0 +1,186 @@ +// 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 <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "doomkeys.h" + +#include "txt_mouseinput.h" +#include "txt_gui.h" +#include "txt_io.h" +#include "txt_label.h" +#include "txt_window.h" + +#define MOUSE_INPUT_WIDTH 8 + +static int MousePressCallback(txt_window_t *window, + int x, int y, int b, + TXT_UNCAST_ARG(mouse_input)) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + // Got the mouse press. Save to the variable and close the window. + + *mouse_input->variable = b - TXT_MOUSE_BASE; + TXT_EmitSignal(mouse_input, "set"); + TXT_CloseWindow(window); + + return 1; +} + +static void OpenPromptWindow(txt_mouse_input_t *mouse_input) +{ + txt_window_t *window; + txt_label_t *label; + + window = TXT_NewWindow(NULL); + TXT_SetWindowAction(window, TXT_HORIZ_LEFT, NULL); + TXT_SetWindowAction(window, TXT_HORIZ_CENTER, + TXT_NewWindowAbortAction(window)); + TXT_SetWindowAction(window, TXT_HORIZ_RIGHT, NULL); + + label = TXT_NewLabel("Press the new mouse button..."); + + TXT_AddWidget(window, label); + TXT_SetWidgetAlign(label, TXT_HORIZ_CENTER); + + TXT_SetMouseListener(window, MousePressCallback, mouse_input); +} + +static void TXT_MouseInputSizeCalc(TXT_UNCAST_ARG(mouse_input)) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + // All mouseinputs are the same size. + + mouse_input->widget.w = MOUSE_INPUT_WIDTH; + mouse_input->widget.h = 1; +} + +static void GetMouseButtonDescription(int button, char *buf) +{ + switch (button) + { + case 0: + strcpy(buf, "LEFT"); + break; + case 1: + strcpy(buf, "RIGHT"); + break; + case 2: + strcpy(buf, "MID"); + break; + default: + sprintf(buf, "BUTTON #%i", button); + break; + } +} + +static void TXT_MouseInputDrawer(TXT_UNCAST_ARG(mouse_input), int selected) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + char buf[20]; + int i; + + if (*mouse_input->variable < 0) + { + strcpy(buf, "(none)"); + } + else + { + GetMouseButtonDescription(*mouse_input->variable, buf); + } + + if (selected) + { + TXT_BGColor(TXT_COLOR_GREY, 0); + } + else + { + TXT_BGColor(TXT_COLOR_BLUE, 0); + } + + TXT_FGColor(TXT_COLOR_BRIGHT_WHITE); + + TXT_DrawString(buf); + + for (i=strlen(buf); i<MOUSE_INPUT_WIDTH; ++i) + { + TXT_DrawString(" "); + } +} + +static void TXT_MouseInputDestructor(TXT_UNCAST_ARG(mouse_input)) +{ +} + +static int TXT_MouseInputKeyPress(TXT_UNCAST_ARG(mouse_input), int mouse) +{ + TXT_CAST_ARG(txt_mouse_input_t, mouse_input); + + if (mouse == KEY_ENTER) + { + // Open a window to prompt for the new mouse press + + OpenPromptWindow(mouse_input); + + return 1; + } + + return 0; +} + +static void TXT_MouseInputMousePress(TXT_UNCAST_ARG(widget), int x, int y, int b) +{ + TXT_CAST_ARG(txt_mouse_input_t, widget); + + // Clicking is like pressing enter + + if (b == TXT_MOUSE_LEFT) + { + TXT_MouseInputKeyPress(widget, KEY_ENTER); + } +} + +txt_widget_class_t txt_mouse_input_class = +{ + TXT_MouseInputSizeCalc, + TXT_MouseInputDrawer, + TXT_MouseInputKeyPress, + TXT_MouseInputDestructor, + TXT_MouseInputMousePress, + NULL, +}; + +txt_mouse_input_t *TXT_NewMouseInput(int *variable) +{ + txt_mouse_input_t *mouse_input; + + mouse_input = malloc(sizeof(txt_mouse_input_t)); + + TXT_InitWidget(mouse_input, &txt_mouse_input_class); + mouse_input->variable = variable; + + return mouse_input; +} + diff --git a/src/setup/txt_mouseinput.h b/src/setup/txt_mouseinput.h new file mode 100644 index 00000000..57c258eb --- /dev/null +++ b/src/setup/txt_mouseinput.h @@ -0,0 +1,44 @@ +// 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. +// + +#ifndef TXT_MOUSE_INPUT_H +#define TXT_MOUSE_INPUT_H + +typedef struct txt_mouse_input_s txt_mouse_input_t; + +#include "txt_widget.h" + +// +// A mouse input is like an input box. When selected, a box pops up +// allowing a mouse to be selected. +// + +struct txt_mouse_input_s +{ + txt_widget_t widget; + int *variable; +}; + +txt_mouse_input_t *TXT_NewMouseInput(int *variable); + +#endif /* #ifndef TXT_MOUSE_INPUT_H */ + + |