foxygit / doom Log in
commit 3a140fe3b5bf1775276a0a454c52b6974b68055f
Author:     Simon Howard <fraggle@soulsphere.org>
AuthorDate: Sun May 10 18:48:05 2015 -0400
Commit:     Simon Howard <fraggle@soulsphere.org>
CommitDate: Sun May 10 18:48:05 2015 -0400

    Add back the Doom PWAD reload hack.

    This was removed back in d190b596c566394717324296cbf6b46e67c64f5c;
    at the time I didn't understand what it was or how it was supposed
    to be used - it seemed like cruft left over from Doom's development.

    It is actually a potentially useful feature for level authors when
    developing their maps. See here: http://doomwiki.org/wiki/Reload_hack

    The reload hack is a relatively obscure feature of limited usefulness
    nowadays, but nonetheless a technical curiosity that ought to be
    preserved in Chocolate Doom.

    The reimplementation here is a lot cleaner than the original version
    from the source release: W_Reload() is based on a call to W_AddFile(),
    we don't reopen the reload file every time we want to read a lump,
    and we include a check in W_AddFile() that we are not trying to use
    the hack on more than one PWAD file.

    This fixes #539.
---
 src/doom/p_setup.c   |  5 ++-
 src/strife/p_setup.c |  3 ++
 src/w_wad.c          | 87 +++++++++++++++++++++++++++++++++++++++++++++++-----
 src/w_wad.h          |  1 +
 4 files changed, 87 insertions(+), 9 deletions(-)

diff --git a/src/doom/p_setup.c b/src/doom/p_setup.c
index 00306e84..08fed7aa 100644
--- a/src/doom/p_setup.c
+++ b/src/doom/p_setup.c
@@ -770,7 +770,10 @@ P_SetupLevel

     // UNUSED W_Profile ();
     P_InitThinkers ();
-
+
+    // if working with a devlopment map, reload it
+    W_Reload ();
+
     // find map name
     if ( gamemode == commercial)
     {
diff --git a/src/strife/p_setup.c b/src/strife/p_setup.c
index 1fd889fa..fe1140bd 100644
--- a/src/strife/p_setup.c
+++ b/src/strife/p_setup.c
@@ -785,6 +785,9 @@ P_SetupLevel
     // UNUSED W_Profile ();
     P_InitThinkers ();

+    // if working with a devlopment map, reload it
+    W_Reload();
+
     // [STRIFE] Removed ExMy map support
     if (map<10)
         DEH_snprintf(lumpname, 9, "map0%i", map);
diff --git a/src/w_wad.c b/src/w_wad.c
index aa0646af..a8a952b6 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -39,7 +39,7 @@
 typedef struct
 {
     // Should be "IWAD" or "PWAD".
-    char		identification[4];
+    char		identification[4];
     int			numlumps;
     int			infotableofs;
 } PACKEDATTR wadinfo_t;
@@ -57,16 +57,20 @@ typedef struct
 //

 // Location of each lump on disk.
-
-lumpinfo_t *lumpinfo;
+lumpinfo_t *lumpinfo;
 unsigned int numlumps = 0;

 // Hash table for fast lookups
-
 static lumpinfo_t **lumphash;

-// Hash function used for lump names.
+// Variables for the reload hack: filename of the PWAD to reload, and the
+// lumps from WADs before the reload file, so we can resent numlumps and
+// load the file again.
+static wad_file_t *reloadhandle = NULL;
+static char *reloadname = NULL;
+static int reloadlump = -1;

+// Hash function used for lump names.
 unsigned int W_LumpNameHash(const char *s)
 {
     // This is the djb2 string hash function, modded to work on strings
@@ -148,8 +152,26 @@ wad_file_t *W_AddFile (char *filename)
     filelump_t *filerover;
     int newnumlumps;

-    // open the file and add to directory
+    // If the filename begins with a ~, it indicates that we should use the
+    // reload hack.
+    if (filename[0] == '~')
+    {
+        if (reloadname != NULL)
+        {
+            I_Error("Prefixing a WAD filename with '~' indicates that the "
+                    "WAD should be reloaded\n"
+                    "on each level restart, for use by level authors for "
+                    "rapid development. You\n"
+                    "can only reload one WAD file, and it must be the last "
+                    "file in the -file list.");
+        }

+        reloadname = strdup(filename);
+        reloadlump = numlumps;
+        ++filename;
+    }
+
+    // Open the file and add to directory
     wad_file = W_OpenFile(filename);

     if (wad_file == NULL)
@@ -158,6 +180,13 @@ wad_file_t *W_AddFile (char *filename)
 	return NULL;
     }

+    // If this is the reload file, we need to save the file handle so that we
+    // can close it later on when we do a reload.
+    if (reloadname)
+    {
+        reloadhandle = wad_file;
+    }
+
     newnumlumps = numlumps;

     if (strcasecmp(filename+strlen(filename)-3 , "wad" ) )
@@ -539,8 +568,7 @@ void W_GenerateHashTable(void)
 {
     unsigned int i;

-    // Free the old hash table, if there is one
-
+    // Free the old hash table, if there is one:
     if (lumphash != NULL)
     {
         Z_Free(lumphash);
@@ -568,6 +596,49 @@ void W_GenerateHashTable(void)
     // All done!
 }

+// The Doom reload hack. The idea here is that if you give a WAD file to -file
+// prefixed with the ~ hack, that WAD file will be reloaded each time a new
+// level is loaded. This lets you use a level editor in parallel and make
+// incremental changes to the level you're working on without having to restart
+// the game after every change.
+// But: the reload feature is a fragile hack...
+void W_Reload(void)
+{
+    char *filename;
+    int i;
+
+    if (reloadname == NULL)
+    {
+        return;
+    }
+
+    // We must release any lumps being held in the PWAD we're about to reload:
+    for (i = reloadlump; i < numlumps; ++i)
+    {
+        if (lumpinfo[i].cache != NULL)
+        {
+            W_ReleaseLumpNum(i);
+        }
+    }
+
+    // Reset numlumps to remove the reload WAD file:
+    numlumps = reloadlump;
+
+    // Now reload the WAD file.
+    filename = reloadname;
+
+    W_CloseFile(reloadhandle);
+    reloadname = NULL;
+    reloadlump = -1;
+    reloadhandle = NULL;
+    W_AddFile(filename);
+    free(filename);
+
+    // The WAD directory has changed, so we have to regenerate the
+    // fast lookup hashtable:
+    W_GenerateHashTable();
+}
+
 // 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_wad.h b/src/w_wad.h
index 71895749..e5dc18b3 100644
--- a/src/w_wad.h
+++ b/src/w_wad.h
@@ -56,6 +56,7 @@ extern lumpinfo_t *lumpinfo;
 extern unsigned int numlumps;

 wad_file_t *W_AddFile (char *filename);
+void    W_Reload (void);

 int	W_CheckNumForName (char* name);
 int	W_GetNumForName (char* name);