From 3a140fe3b5bf1775276a0a454c52b6974b68055f Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 10 May 2015 18:48:05 -0400 Subject: 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); -- cgit v1.2.3