diff options
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | setup/execute.c | 40 | ||||
-rw-r--r-- | setup/execute.h | 9 | ||||
-rw-r--r-- | setup/multiplayer.c | 271 | ||||
-rw-r--r-- | src/d_iwad.c | 48 | ||||
-rw-r--r-- | src/d_iwad.h | 1 | ||||
-rw-r--r-- | src/d_main.c | 5 |
7 files changed, 306 insertions, 70 deletions
@@ -5,8 +5,6 @@ To do: - Debian/Ubuntu .deb packages, Fedora .rpm packages. - Windows NSIS installer. - MacOS X .dmg packages (should be universal binaries!) -* Smarter setup program - detect IWADs automatically and make them - selectable from a list. * Free version of the Chocolate Doom logo (from scratch, not using the Doom imp sprite), so t-shirts can be printed! * Better icon for chocolate-setup. diff --git a/setup/execute.c b/setup/execute.c index fb1ac722..8f60288b 100644 --- a/setup/execute.c +++ b/setup/execute.c @@ -26,6 +26,9 @@ #include <stdlib.h> #include <string.h> +#include <sys/types.h> +#include <sys/wait.h> + #include "textscreen.h" #include "configfile.h" @@ -96,9 +99,10 @@ void AddCmdLineParameter(execute_context_t *context, char *s, ...) fprintf(context->stream, "\n"); } -void ExecuteDoom(execute_context_t *context) +int ExecuteDoom(execute_context_t *context) { char *cmdline; + int result; fclose(context->stream); @@ -110,13 +114,22 @@ void ExecuteDoom(execute_context_t *context) sprintf(cmdline, "%s @%s", DOOM_BINARY, context->response_file); // Run the command - system(cmdline); + result = system(cmdline); free(cmdline); // Destroy context remove(context->response_file); free(context); + + if (WIFEXITED(result)) + { + return WEXITSTATUS(result); + } + else + { + return -1; + } } static void TestCallback(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(data)) @@ -174,3 +187,26 @@ txt_window_action_t *TestConfigAction(void) 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/setup/execute.h b/setup/execute.h index 8c373bf6..46301418 100644 --- a/setup/execute.h +++ b/setup/execute.h @@ -26,10 +26,17 @@ 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 */ + execute_context_t *NewExecuteContext(void); void AddCmdLineParameter(execute_context_t *context, char *s, ...); void AddConfigParameters(execute_context_t *context); -void ExecuteDoom(execute_context_t *context); +int ExecuteDoom(execute_context_t *context); +int FindInstalledIWADs(void); txt_window_action_t *TestConfigAction(void); diff --git a/setup/multiplayer.c b/setup/multiplayer.c index f55a7f8c..cd5c774b 100644 --- a/setup/multiplayer.c +++ b/setup/multiplayer.c @@ -34,12 +34,40 @@ #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 }, +}; + +// Array of IWADs found to be installed + +static char *found_iwads[5]; + +// 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!", @@ -78,6 +106,23 @@ static int warpmap = 1; static char *connect_address = NULL; +// Find an IWAD from its description + +static iwad_t *GetIWADForDescription(char *description) +{ + int i; + + for (i=0; i<sizeof(iwads) / sizeof(*iwads); ++i) + { + if (!strcmp(iwads[i].description, description)) + { + return &iwads[i];; + } + } + + return NULL; +} + static void AddWADs(execute_context_t *exec) { int have_wads = 0; @@ -115,6 +160,12 @@ static void StartGame(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) execute_context_t *exec; exec = NewExecuteContext(); + + if (iwadfile != NULL) + { + AddCmdLineParameter(exec, "-iwad %s", iwadfile); + } + AddCmdLineParameter(exec, "-server"); AddCmdLineParameter(exec, "-skill %i", skill + 1); @@ -194,7 +245,6 @@ static void SetDoom1Warp(TXT_UNCAST_ARG(widget), void *val) l = (int) val; - warptype = WARP_DOOM1; warpepisode = l / 10; warpmap = l % 10; @@ -207,7 +257,6 @@ static void SetDoom2Warp(TXT_UNCAST_ARG(widget), void *val) l = (int) val; - warptype = WARP_DOOM2; warpmap = l; UpdateWarpButton(); @@ -228,69 +277,172 @@ static void LevelSelectDialog(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(user_data)) char buf[10]; int x, y; int l; + int i; window = TXT_NewWindow("Select level"); - table = TXT_NewTable(8); + table = TXT_NewTable(4); TXT_AddWidget(window, table); - for (y=1; y<=9; ++y) + if (warptype == WARP_DOOM1) { - // MAP?? levels - - for (x=0; x<4; ++x) + // ExMy levels + + for (i=0; i<4 * 9; ++i) { - l = x * 9 + y; - - if (l > 32) + x = (i % 4) + 1; + y = (i / 4) + 1; + + 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_AddWidget(table, NULL); + TXT_SelectWidget(table, button); } - else + } + } + 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) { - 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 (warptype == WARP_DOOM2 - && warpmap == l) - { - TXT_SelectWidget(table, button); - } + TXT_SelectWidget(table, button); } } + } +} - // ExMy levels - - for (x=1; x<=4; ++x) +static void IWADSelected(TXT_UNCAST_ARG(widget), TXT_UNCAST_ARG(unused)) +{ + iwad_t *iwad; + + // Find the iwad_t selected + + iwad = GetIWADForDescription(found_iwads[found_iwad_selected]); + + // 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)) + { + 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(); +} + +static txt_widget_t *IWADSelector(void) +{ + txt_dropdown_list_t *dropdown; + int installed_iwads; + int num_iwads; + 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<sizeof(iwads) / sizeof(*iwads); ++i) + { + if (installed_iwads & iwads[i].mask) { - if (y > 9) - { - TXT_AddWidget(table, NULL); - } - else - { - 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 (warptype == WARP_DOOM1 - && warpepisode == x && warpmap == y) - { - TXT_SelectWidget(table, button); - } - } + found_iwads[num_iwads] = iwads[i].description; + ++num_iwads; } } + + // Build a dropdown list of IWADs + + if (num_iwads == 0) + { + // No IWAD found. Show Doom 2 options, but this probably + // isn't going to work. + + warptype = WARP_DOOM2; + warpepisode = 1; + warpmap = 1; + iwadfile = NULL; + UpdateWarpButton(); + + return (txt_widget_t *) TXT_NewLabel("Doom 2"); + } + else if (num_iwads == 1) + { + // We have only one IWAD. Show the first one as a label. + + found_iwad_selected = 0; + IWADSelected(NULL, NULL); + + return (txt_widget_t *) TXT_NewLabel(found_iwads[0]); + } + else + { + // Dropdown list allowing IWAD to be selected. + + found_iwad_selected = 0; + IWADSelected(NULL, NULL); + + dropdown = TXT_NewDropdownList(&found_iwad_selected, + found_iwads, num_iwads); + + TXT_SignalConnect(dropdown, "changed", IWADSelected, NULL); + + return (txt_widget_t *) dropdown; + } } static txt_window_action_t *StartGameAction(void) @@ -345,6 +497,7 @@ 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"); @@ -366,6 +519,8 @@ void StartMultiGame(void) TXT_SetColumnWidths(gameopt_table, 12, 12); TXT_AddWidgets(gameopt_table, + TXT_NewLabel("Game"), + iwad_selector = IWADSelector(), TXT_NewLabel("Skill"), TXT_NewDropdownList(&skill, skills, 5), TXT_NewLabel("Game type"), @@ -380,11 +535,14 @@ void StartMultiGame(void) 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(); } @@ -419,21 +577,30 @@ static txt_window_action_t *JoinGameAction(void) return action; } - void JoinMultiGame(void) { txt_window_t *window; + txt_table_t *gameopt_table; window = TXT_NewWindow("Join multiplayer game"); TXT_AddWidgets(window, - TXT_NewLabel("Connect to address: "), - TXT_NewInputBox(&connect_address, 40), + gameopt_table = TXT_NewTable(2), TXT_NewStrut(0, 1), TXT_NewButton2("Add extra parameters...", OpenExtraParamsWindow, NULL), - TXT_NewButton2("Add WADs...", OpenWadsWindow, 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()); } diff --git a/src/d_iwad.c b/src/d_iwad.c index 04774203..612f2434 100644 --- a/src/d_iwad.c +++ b/src/d_iwad.c @@ -170,12 +170,12 @@ static char *GetRegistryString(registry_value_t *reg_val) // Allocate a buffer for the value and read the value - result = Z_Malloc(len, PU_STATIC, 0); + result = malloc(len); if (RegQueryValueEx(key, reg_val->value, NULL, &valtype, (unsigned char *) result, &len) != ERROR_SUCCESS) { - Z_Free(result); + free(result); return NULL; } @@ -209,7 +209,7 @@ static void CheckUninstallStrings(void) if (unstr == NULL) { - Z_Free(val); + free(val); } else { @@ -238,17 +238,16 @@ static void CheckCollectorsEdition(void) for (i=0; i<sizeof(collectors_edition_subdirs) / sizeof(*collectors_edition_subdirs); ++i) { - subpath = Z_Malloc(strlen(install_path) - + strlen(collectors_edition_subdirs[i]) - + 5, - PU_STATIC, 0); + subpath = malloc(strlen(install_path) + + strlen(collectors_edition_subdirs[i]) + + 5); sprintf(subpath, "%s\\%s", install_path, collectors_edition_subdirs[i]); AddIWADDir(subpath); } - Z_Free(install_path); + free(install_path); } #endif @@ -279,7 +278,7 @@ static char *SearchDirectoryForIWAD(char *dir) iwadname = DEH_String(iwads[i].name); - filename = Z_Malloc(strlen(dir) + strlen(iwadname) + 3, PU_STATIC, 0); + filename = malloc(strlen(dir) + strlen(iwadname) + 3); sprintf(filename, "%s%c%s", dir, DIR_SEPARATOR, iwadname); @@ -289,7 +288,7 @@ static char *SearchDirectoryForIWAD(char *dir) return filename; } - Z_Free(filename); + free(filename); } return NULL; @@ -409,7 +408,6 @@ static void BuildIWADDirList(void) // Searches IWAD search paths for an IWAD with a specific name. // - char *D_FindIWADByName(char *name) { char *buf; @@ -429,7 +427,7 @@ char *D_FindIWADByName(char *name) { // Construct a string for the full path - buf = Z_Malloc(strlen(iwad_dirs[i]) + strlen(name) + 5, PU_STATIC, 0); + buf = malloc(strlen(iwad_dirs[i]) + strlen(name) + 5); sprintf(buf, "%s%c%s", iwad_dirs[i], DIR_SEPARATOR, name); exists = M_FileExists(buf); @@ -439,7 +437,7 @@ char *D_FindIWADByName(char *name) return buf; } - Z_Free(buf); + free(buf); } // File not found @@ -731,3 +729,27 @@ void D_SetGameDescription(void) } } +// Clever hack: Setup can invoke Doom to determine which IWADs are installed. +// Doom searches install paths and exits with the return code being a +// bitmask of the installed IWAD files. + +void D_FindInstalledIWADs(void) +{ + int i; + int result; + + BuildIWADDirList(); + + result = 0; + + for (i=0; i<sizeof(iwads) / sizeof(*iwads); ++i) + { + if (D_FindIWADByName(iwads[i].name) != NULL) + { + result |= 1 << i; + } + } + + exit(result); +} + diff --git a/src/d_iwad.h b/src/d_iwad.h index 404d7efb..a0f1a0ba 100644 --- a/src/d_iwad.h +++ b/src/d_iwad.h @@ -31,6 +31,7 @@ char *D_FindIWAD(void); void D_SetSaveGameDir(void); void D_IdentifyVersion(void); void D_SetGameDescription(void); +void D_FindInstalledIWADs(void); #endif diff --git a/src/d_main.c b/src/d_main.c index a8c46a95..af892d30 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -929,6 +929,11 @@ void D_DoomMain (void) FindResponseFile (); + if (M_CheckParm("-findiwads") > 0) + { + D_FindInstalledIWADs(); + } + // print banner PrintBanner(PACKAGE_STRING); |