shithub: choc

Download patch

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);