ref: 052741d3485780d8e029ada086e330fdd56ee7ac
parent: 8630d0991eb32b3bedecb6655ac9935bd50391df
author: Simon Howard <fraggle@gmail.com>
date: Sat Dec 23 16:24:56 EST 2006
Add '-findiwads' command line hack so that the setup program can find out what games are installed. Provide a drop-down list in setup to allow the game type to be selected. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 803
--- a/TODO
+++ b/TODO
@@ -5,8 +5,6 @@
- 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.
--- 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 @@
fprintf(context->stream, "\n");
}
-void ExecuteDoom(execute_context_t *context)
+int ExecuteDoom(execute_context_t *context)
{
char *cmdline;
+ int result;
fclose(context->stream);
@@ -110,7 +114,7 @@
sprintf(cmdline, "%s @%s", DOOM_BINARY, context->response_file);
// Run the command
- system(cmdline);
+ result = system(cmdline);
free(cmdline);
@@ -117,6 +121,15 @@
// 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))
@@ -172,5 +185,28 @@
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;
+ }
}
--- 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);
--- a/setup/multiplayer.c
+++ b/setup/multiplayer.c
@@ -34,6 +34,13 @@
#define NUM_WADS 10
#define NUM_EXTRA_PARAMS 10
+typedef struct
+{
+ char *filename;
+ char *description;
+ int mask;
+} iwad_t;
+
typedef enum
{
WARP_DOOM1,
@@ -40,6 +47,27 @@
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 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 @@
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 @@
l = (int) val;
- warptype = WARP_DOOM1;
warpepisode = l / 10;
warpmap = l % 10;
@@ -207,7 +257,6 @@
l = (int) val;
- warptype = WARP_DOOM2;
warpmap = l;
UpdateWarpButton();
@@ -228,69 +277,172 @@
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);
+ TXT_SelectWidget(table, button);
+ }
+ }
+ }
+}
- if (warptype == WARP_DOOM2
- && 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 = GetIWADForDescription(found_iwads[found_iwad_selected]);
+
+ // Update iwadfile
+
+ iwadfile = iwad->filename;
+}
- // ExMy levels
-
- for (x=1; x<=4; ++x)
- {
- 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);
+// Called when the IWAD button is changed, to update warptype.
- if (warptype == WARP_DOOM1
- && warpepisode == x && warpmap == y)
- {
- TXT_SelectWidget(table, button);
- }
- }
+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)
+ {
+ 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 @@
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 @@
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 @@
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 @@
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());
}
--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -170,12 +170,12 @@
// 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 @@
if (unstr == NULL)
{
- Z_Free(val);
+ free(val);
}
else
{
@@ -238,10 +238,9 @@
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]);
@@ -248,7 +247,7 @@
AddIWADDir(subpath);
}
- Z_Free(install_path);
+ free(install_path);
}
#endif
@@ -279,7 +278,7 @@
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 @@
return filename;
}
- Z_Free(filename);
+ free(filename);
}
return NULL;
@@ -409,7 +408,6 @@
// Searches IWAD search paths for an IWAD with a specific name.
//
-
char *D_FindIWADByName(char *name)
{
char *buf;
@@ -429,7 +427,7 @@
{
// 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 @@
return buf;
}
- Z_Free(buf);
+ free(buf);
}
// File not found
@@ -729,5 +727,29 @@
else if (gamemission == pack_tnt)
gamedescription = GetGameName("DOOM 2: TNT - Evilution");
}
+}
+
+// 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);
}
--- a/src/d_iwad.h
+++ b/src/d_iwad.h
@@ -31,6 +31,7 @@
void D_SetSaveGameDir(void);
void D_IdentifyVersion(void);
void D_SetGameDescription(void);
+void D_FindInstalledIWADs(void);
#endif
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -929,6 +929,11 @@
FindResponseFile ();
+ if (M_CheckParm("-findiwads") > 0)
+ {
+ D_FindInstalledIWADs();
+ }
+
// print banner
PrintBanner(PACKAGE_STRING);