foxygit / doom Log in
commit c06b2c5f8e22d7cf54a502df5042de87d6d2218e
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Fri Nov 2 22:24:18 2018 -0400
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Fri Nov 2 22:24:18 2018 -0400

    Add WAD file autoloading.

    Implements most of #1052, adding a new config file variable named
    `autoload_path` that is auto-configured on first run. The actual
    files are autoloaded from subdirectories named by IWAD file name that
    are automatically created. It's sufficient to just drop .WAD and .DEH
    files into the appropriate directory to have them automatically load
    on startup.

    Also add a -noautoload command line parameter to disable the autoload
    functionality on occasion if desired.
---
 src/deh_main.c       | 22 ++++++++++++++++++++++
 src/deh_main.h       |  1 +
 src/doom/d_main.c    | 14 ++++++++++++++
 src/heretic/d_main.c | 14 ++++++++++++++
 src/hexen/h2_main.c  | 14 ++++++++++++++
 src/m_config.c       | 42 +++++++++++++++++++++++++++++++++++++++++-
 src/m_config.h       |  1 +
 src/strife/d_main.c  | 14 ++++++++++++++
 src/w_main.c         | 22 ++++++++++++++++++++++
 src/w_main.h         |  3 +++
 10 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/src/deh_main.c b/src/deh_main.c
index a4d80608..0a929ec8 100644
--- a/src/deh_main.c
+++ b/src/deh_main.c
@@ -21,6 +21,7 @@
 #include <ctype.h>

 #include "doomtype.h"
+#include "i_glob.h"
 #include "i_system.h"
 #include "d_iwad.h"
 #include "m_argv.h"
@@ -406,6 +407,27 @@ int DEH_LoadFile(const char *filename)
     return 1;
 }

+// Load all dehacked patches from the given directory.
+void DEH_AutoLoadPatches(const char *path)
+{
+    const char *filename;
+    glob_t *glob;
+
+    glob = I_StartGlob(path, "*.deh", GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED);
+    for (;;)
+    {
+        filename = I_NextGlob(glob);
+        if (filename == NULL)
+        {
+            break;
+        }
+        printf(" [autoload]");
+        DEH_LoadFile(filename);
+    }
+
+    I_EndGlob(glob);
+}
+
 // Load dehacked file from WAD lump.
 // If allow_long is set, allow long strings and cheats just for this lump.

diff --git a/src/deh_main.h b/src/deh_main.h
index faedc581..9ab87040 100644
--- a/src/deh_main.h
+++ b/src/deh_main.h
@@ -31,6 +31,7 @@

 void DEH_ParseCommandLine(void);
 int DEH_LoadFile(const char *filename);
+void DEH_AutoLoadPatches(const char *path);
 int DEH_LoadLump(int lumpnum, boolean allow_long, boolean allow_error);
 int DEH_LoadLumpByName(const char *name, boolean allow_long, boolean allow_error);

diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index db685ce1..f790d019 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -1506,6 +1506,20 @@ void D_DoomMain (void)
         DEH_AddStringReplacement("M_SCRNSZ", "M_DISP");
     }

+    //!
+    // @category mod
+    //
+    // Disable auto-loading of .wad and .deh files.
+    //
+    if (!M_ParmExists("-noautoload") && gamemode != shareware)
+    {
+        char *autoload_dir;
+        autoload_dir = M_GetAutoloadDir(D_SaveGameIWADName(gamemission));
+        DEH_AutoLoadPatches(autoload_dir);
+        W_AutoLoadWADs(autoload_dir);
+        free(autoload_dir);
+    }
+
     // Load Dehacked patches specified on the command line with -deh.
     // Note that there's a very careful and deliberate ordering to how
     // Dehacked patches are loaded. The order we use is:
diff --git a/src/heretic/d_main.c b/src/heretic/d_main.c
index 97b1c07f..4182d1c2 100644
--- a/src/heretic/d_main.c
+++ b/src/heretic/d_main.c
@@ -901,6 +901,20 @@ void D_DoomMain(void)
     D_AddFile(iwadfile);
     W_CheckCorrectIWAD(heretic);

+    //!
+    // @category mod
+    //
+    // Disable auto-loading of .wad files.
+    //
+    if (!M_ParmExists("-noautoload"))
+    {
+        char *autoload_dir;
+        autoload_dir = M_GetAutoloadDir("heretic.wad");
+        // TODO? DEH_AutoLoadPatches(autoload_dir);
+        W_AutoLoadWADs(autoload_dir);
+        free(autoload_dir);
+    }
+
     // Load dehacked patches specified on the command line.
     DEH_ParseCommandLine();

diff --git a/src/hexen/h2_main.c b/src/hexen/h2_main.c
index 2a9f232c..88362e7a 100644
--- a/src/hexen/h2_main.c
+++ b/src/hexen/h2_main.c
@@ -422,6 +422,20 @@ void D_DoomMain(void)
     D_SetGameDescription();
     AdjustForMacIWAD();

+    //!
+    // @category mod
+    //
+    // Disable auto-loading of .wad files.
+    //
+    if (!M_ParmExists("-noautoload"))
+    {
+        char *autoload_dir;
+        autoload_dir = M_GetAutoloadDir("hexen.wad");
+        // TODO? DEH_AutoLoadPatches(autoload_dir);
+        W_AutoLoadWADs(autoload_dir);
+        free(autoload_dir);
+    }
+
     HandleArgs();

     I_PrintStartupBanner(gamedescription);
diff --git a/src/m_config.c b/src/m_config.c
index eeb825e9..db4a9298 100644
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -33,6 +33,7 @@
 #include "doomkeys.h"
 #include "i_system.h"
 #include "m_argv.h"
+#include "m_config.h"
 #include "m_misc.h"

 #include "z_zone.h"
@@ -46,6 +47,8 @@

 const char *configdir;

+static char *autoload_path = "";
+
 // Default filenames for configuration files.

 static const char *default_main_config;
@@ -908,6 +911,14 @@ static default_t extra_defaults_list[] =

     CONFIG_VARIABLE_FLOAT(libsamplerate_scale),

+    //!
+    // Full path to a directory in which WAD files and dehacked patches
+    // can be placed to be automatically loaded on startup. A subdirectory
+    // of this directory matching the IWAD name is checked to find the
+    // files to load.
+
+    CONFIG_VARIABLE_STRING(autoload_path),
+
     //!
     // Full path to a directory containing configuration files for
     // substitute music packs. These packs contain high quality renderings
@@ -1977,7 +1988,10 @@ void M_SaveDefaultsAlternate(const char *main, const char *extra)
 void M_LoadDefaults (void)
 {
     int i;
-
+
+    // This variable is a special snowflake for no good reason.
+    M_BindStringVariable("autoload_path", &autoload_path);
+
     // check for a custom default file

     //!
@@ -2317,3 +2331,29 @@ char *M_GetSaveGameDir(const char *iwadname)
     return savegamedir;
 }

+//
+// Calculate the path to the directory for autoloaded WADs/DEHs.
+// Creates the directory as necessary.
+//
+char *M_GetAutoloadDir(const char *iwadname)
+{
+    char *result;
+
+    if (autoload_path == NULL || strlen(autoload_path) == 0)
+    {
+        char *prefdir;
+        prefdir = SDL_GetPrefPath("", PACKAGE_TARNAME);
+        autoload_path = M_StringJoin(prefdir, "autoload", NULL);
+        free(prefdir);
+    }
+
+    M_MakeDirectory(autoload_path);
+
+    result = M_StringJoin(autoload_path, DIR_SEPARATOR_S, iwadname, NULL);
+    M_MakeDirectory(result);
+
+    // TODO: Add README file
+
+    return result;
+}
+
diff --git a/src/m_config.h b/src/m_config.h
index 4bc3ba54..5939b6be 100644
--- a/src/m_config.h
+++ b/src/m_config.h
@@ -36,6 +36,7 @@ const char *M_GetStringVariable(const char *name);
 float M_GetFloatVariable(const char *name);
 void M_SetConfigFilenames(const char *main_config, const char *extra_config);
 char *M_GetSaveGameDir(const char *iwadname);
+char *M_GetAutoloadDir(const char *iwadname);

 extern const char *configdir;

diff --git a/src/strife/d_main.c b/src/strife/d_main.c
index f9ca3c76..03fd9114 100644
--- a/src/strife/d_main.c
+++ b/src/strife/d_main.c
@@ -1736,6 +1736,20 @@ void D_DoomMain (void)
     W_CheckCorrectIWAD(strife);
     D_IdentifyVersion();

+    //!
+    // @category mod
+    //
+    // Disable auto-loading of .wad files.
+    //
+    if (!M_ParmExists("-noautoload"))
+    {
+        char *autoload_dir;
+        autoload_dir = M_GetAutoloadDir("strife1.wad");
+        // TODO? DEH_AutoLoadPatches(autoload_dir);
+        W_AutoLoadWADs(autoload_dir);
+        free(autoload_dir);
+    }
+
     // Load dehacked patches specified on the command line.
     DEH_ParseCommandLine();

diff --git a/src/w_main.c b/src/w_main.c
index a9592932..a08f4172 100644
--- a/src/w_main.c
+++ b/src/w_main.c
@@ -20,6 +20,7 @@

 #include "config.h"
 #include "d_iwad.h"
+#include "i_glob.h"
 #include "i_system.h"
 #include "m_argv.h"
 #include "w_main.h"
@@ -200,6 +201,27 @@ boolean W_ParseCommandLine(void)
     return modifiedgame;
 }

+// Load all WAD files from the given directory.
+void W_AutoLoadWADs(const char *path)
+{
+    glob_t *glob;
+    const char *filename;
+
+    glob = I_StartGlob(path, "*.wad", GLOB_FLAG_NOCASE|GLOB_FLAG_SORTED);
+    for (;;)
+    {
+        filename = I_NextGlob(glob);
+        if (filename == NULL)
+        {
+            break;
+        }
+        printf(" [autoload] merging %s\n", filename);
+        W_MergeFile(filename);
+    }
+
+    I_EndGlob(glob);
+}
+
 // Lump names that are unique to particular game types. This lets us check
 // the user is not trying to play with the wrong executable, eg.
 // chocolate-doom -iwad hexen.wad.
diff --git a/src/w_main.h b/src/w_main.h
index 26b487c8..4565c657 100644
--- a/src/w_main.h
+++ b/src/w_main.h
@@ -23,5 +23,8 @@
 boolean W_ParseCommandLine(void);
 void W_CheckCorrectIWAD(GameMission_t mission);

+// Autoload all .wad files from the given directory:
+void W_AutoLoadWADs(const char *path);
+
 #endif /* #ifndef W_MAIN_H */