shithub: choc

Download patch

ref: 9e54684b11cf8e8e4ae19ebd2d754ee472c70089
parent: e18391bb0f7b2690d0055fb031caa5fe7d3cdecf
author: Simon Howard <fraggle@gmail.com>
date: Tue Nov 30 15:00:06 EST 2010

Add support for HACX v1.2 IWAD file.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 2176

--- a/src/d_iwad.c
+++ b/src/d_iwad.c
@@ -326,16 +326,22 @@
     {"doom.wad",     doom},
     {"doom1.wad",    doom},
     {"chex.wad",     doom},
+    {"hacx.wad",     doom2},
 };
-            
+
 // Hack for chex quest mode
 
-static void CheckChex(char *iwad_name)
+static void CheckSpecialIWADs(char *iwad_name)
 {
-    if (!strcmp(iwad_name, "chex.wad")) 
+    if (!strcasecmp(iwad_name, "chex.wad"))
     {
         gameversion = exe_chex;
     }
+
+    if (!strcasecmp(iwad_name, "hacx.wad"))
+    {
+        gameversion = exe_hacx;
+    }
 }
 
 // Returns true if the specified path is a path to a file
@@ -408,7 +414,7 @@
 
         if (filename != NULL)
         {
-            CheckChex(iwads[i].name);
+            CheckSpecialIWADs(iwads[i].name);
             gamemission = iwads[i].mission;
 
             return filename;
@@ -441,7 +447,7 @@
         if (!strcasecmp(name + strlen(name) - strlen(iwadname), 
                         iwadname))
         {
-            CheckChex(iwads[i].name);
+            CheckSpecialIWADs(iwads[i].name);
             gamemission = iwads[i].mission;
             break;
         }
@@ -701,6 +707,13 @@
         return "chex.wad";
     }
 
+    // Hacx hack
+
+    if (gameversion == exe_hacx)
+    {
+        return "hacx.wad";
+    }
+
     // Find what subdirectory to use for savegames
     //
     // They should be stored in something like
@@ -770,6 +783,10 @@
 
 static char *banners[] = 
 {
+    // doom2.wad
+    "                         "
+    "DOOM 2: Hell on Earth v%i.%i"
+    "                           ",
     // doom1.wad
     "                            "
     "DOOM Shareware Startup v%i.%i"
@@ -786,10 +803,6 @@
     "                         "
     "The Ultimate DOOM Startup v%i.%i"
     "                        ",
-    // doom2.wad
-    "                         "
-    "DOOM 2: Hell on Earth v%i.%i"
-    "                           ",
     // tnt.wad
     "                     "
     "DOOM 2: TNT - Evilution v%i.%i"
@@ -809,13 +822,13 @@
 {
     size_t i;
     char *deh_sub;
-    
+
     for (i=0; i<arrlen(banners); ++i)
     {
         // Has the banner been replaced?
 
         deh_sub = DEH_String(banners[i]);
-        
+
         if (deh_sub != banners[i])
         {
             // Has been replaced
--- a/src/d_main.c
+++ b/src/d_main.c
@@ -660,6 +660,7 @@
     GameVersion_t version;
 } gameversions[] = {
     {"Doom 1.9",             "1.9",        exe_doom_1_9},
+    {"Hacx",                 "hacx",       exe_hacx},
     {"Ultimate Doom",        "ultimate",   exe_ultimate},
     {"Final Doom",           "final",      exe_final},
     {"Chex Quest",           "chex",       exe_chex},
@@ -711,7 +712,7 @@
     {
         // Determine automatically
 
-        if (gameversion == exe_chex) 
+        if (gameversion == exe_chex || gameversion == exe_hacx)
         {
             // Already determined
         }
@@ -796,6 +797,20 @@
     }
 }
 
+static void LoadHacxDeh(void)
+{
+    // If this is the HACX IWAD, we need to load the DEHACKED lump.
+
+    if (gameversion == exe_hacx)
+    {
+        if (!DEH_LoadLumpByName("DEHACKED"))
+        {
+            I_Error("DEHACKED lump not found.  Please check that this is the "
+                    "Hacx v1.2 IWAD.");
+        }
+    }
+}
+
 //
 // D_DoomMain
 //
@@ -1227,6 +1242,7 @@
     D_IdentifyVersion();
     InitGameVersion();
     LoadChexDeh();
+    LoadHacxDeh();
     D_SetGameDescription();
     D_SetSaveGameDir();
 
--- a/src/deh_io.c
+++ b/src/deh_io.c
@@ -30,21 +30,63 @@
 #include <string.h>
 
 #include "i_system.h"
+#include "w_wad.h"
 #include "z_zone.h"
 
 #include "deh_defs.h"
 #include "deh_io.h"
 
+typedef enum
+{
+    DEH_INPUT_FILE,
+    DEH_INPUT_LUMP
+} deh_input_type_t;
+
 struct deh_context_s
 {
-    FILE *stream;
+    deh_input_type_t type;
     char *filename;
+
+    // If the input comes from a memory buffer, pointer to the memory
+    // buffer.
+
+    unsigned char *input_buffer;
+    size_t input_buffer_len;
+    unsigned int input_buffer_pos;
+    int lumpnum;
+
+    // If the input comes from a file, the file stream for reading
+    // data.
+
+    FILE *stream;
+
+    // Current line number that we have reached:
+
     int linenum;
+
+    // Used by DEH_ReadLine:
+
     boolean last_was_newline;
     char *readbuffer;
     int readbuffer_size;
 };
 
+static deh_context_t *DEH_NewContext(void)
+{
+    deh_context_t *context;
+
+    context = Z_Malloc(sizeof(*context), PU_STATIC, NULL);
+
+    // Initial read buffer size of 128 bytes
+
+    context->readbuffer_size = 128;
+    context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL);
+    context->linenum = 0;
+    context->last_was_newline = true;
+
+    return context;
+}
+
 // Open a dehacked file for reading
 // Returns NULL if open failed
 
@@ -52,23 +94,42 @@
 {
     FILE *fstream;
     deh_context_t *context;
-    
+
     fstream = fopen(filename, "r");
 
     if (fstream == NULL)
         return NULL;
 
-    context = Z_Malloc(sizeof(*context), PU_STATIC, NULL);
+    context = DEH_NewContext();
+
+    context->type = DEH_INPUT_FILE;
     context->stream = fstream;
-    
-    // Initial read buffer size of 128 bytes
+    context->filename = strdup(filename);
 
-    context->readbuffer_size = 128;
-    context->readbuffer = Z_Malloc(context->readbuffer_size, PU_STATIC, NULL);
-    context->filename = filename;
-    context->linenum = 0;
-    context->last_was_newline = true;
+    return context;
+}
 
+// Open a WAD lump for reading.
+
+deh_context_t *DEH_OpenLump(int lumpnum)
+{
+    deh_context_t *context;
+    void *lump;
+
+    lump = W_CacheLumpNum(lumpnum, PU_STATIC);
+
+    context = DEH_NewContext();
+
+    context->type = DEH_INPUT_LUMP;
+    context->lumpnum = lumpnum;
+    context->input_buffer = lump;
+    context->input_buffer_len = W_LumpLength(lumpnum);
+    context->input_buffer_pos = 0;
+
+    context->filename = malloc(9);
+    strncpy(context->filename, lumpinfo[lumpnum].name, 8);
+    context->filename[8] = '\0';
+
     return context;
 }
 
@@ -76,33 +137,65 @@
 
 void DEH_CloseFile(deh_context_t *context)
 {
-    fclose(context->stream);
+    if (context->type == DEH_INPUT_FILE)
+    {
+        fclose(context->stream);
+    }
+    else if (context->type == DEH_INPUT_LUMP)
+    {
+        W_ReleaseLumpNum(context->lumpnum);
+    }
+
     Z_Free(context->readbuffer);
     Z_Free(context);
 }
 
+int DEH_GetCharFile(deh_context_t *context)
+{
+    if (feof(context->stream))
+    {
+        // end of file
+
+        return -1;
+    }
+
+    return fgetc(context->stream);
+}
+
+int DEH_GetCharLump(deh_context_t *context)
+{
+    int result;
+
+    if (context->input_buffer_pos >= context->input_buffer_len)
+    {
+        return -1;
+    }
+
+    result = context->input_buffer[context->input_buffer_pos];
+    ++context->input_buffer_pos;
+
+    return result;
+}
+
 // Reads a single character from a dehacked file
 
 int DEH_GetChar(deh_context_t *context)
 {
     int result;
-   
+
     // Read characters, but ignore carriage returns
     // Essentially this is a DOS->Unix conversion
 
-    do 
+    do
     {
-        if (feof(context->stream))
+        switch (context->type)
         {
-            // end of file
+            case DEH_INPUT_FILE:
+                result = DEH_GetCharFile(context);
 
-            result = -1;
+            case DEH_INPUT_LUMP:
+                result = DEH_GetCharLump(context);
         }
-        else
-        {
-            result = fgetc(context->stream);
-        }
-
     } while (result == '\r');
 
     // Track the current line number
@@ -111,9 +204,9 @@
     {
         ++context->linenum;
     }
-    
+
     context->last_was_newline = result == '\n';
-    
+
     return result;
 }
 
--- a/src/deh_io.h
+++ b/src/deh_io.h
@@ -30,6 +30,7 @@
 #include "deh_defs.h"
 
 deh_context_t *DEH_OpenFile(char *filename);
+deh_context_t *DEH_OpenLump(int lumpnum);
 void DEH_CloseFile(deh_context_t *context);
 int DEH_GetChar(deh_context_t *context);
 char *DEH_ReadLine(deh_context_t *context);
--- a/src/deh_main.c
+++ b/src/deh_main.c
@@ -30,6 +30,7 @@
 #include "doomtype.h"
 #include "d_iwad.h"
 #include "m_argv.h"
+#include "w_wad.h"
 
 #include "deh_defs.h"
 #include "deh_io.h"
@@ -281,9 +282,6 @@
         DEH_Error(context, "This is not a valid dehacked patch file!");
     }
 
-    deh_allow_long_strings = false;
-    deh_allow_long_cheats = false;
-    
     // Read the file
     
     for (;;) 
@@ -295,7 +293,9 @@
         // end of file?
 
         if (line == NULL)
+        {
             return;
+        }
 
         while (line[0] != '\0' && isspace(line[0]))
             ++line;
@@ -359,6 +359,11 @@
 {
     deh_context_t *context;
 
+    // Vanilla dehacked files don't allow long string or cheat replacements.
+
+    deh_allow_long_strings = false;
+    deh_allow_long_cheats = false;
+
     printf(" loading %s\n", filename);
 
     context = DEH_OpenFile(filename);
@@ -376,6 +381,48 @@
     return 1;
 }
 
+// Load dehacked file from WAD lump.
+
+int DEH_LoadLump(int lumpnum)
+{
+    deh_context_t *context;
+
+    // If it's in a lump, it's probably designed for a modern source port,
+    // so allow it to do long string and cheat replacements.
+
+    deh_allow_long_strings = true;
+    deh_allow_long_cheats = true;
+
+    context = DEH_OpenLump(lumpnum);
+
+    if (context == NULL)
+    {
+        fprintf(stderr, "DEH_LoadFile: Unable to open lump %i\n", lumpnum);
+        return 0;
+    }
+
+    DEH_ParseContext(context);
+
+    DEH_CloseFile(context);
+
+    return 1;
+}
+
+int DEH_LoadLumpByName(char *name)
+{
+    int lumpnum;
+
+    lumpnum = W_CheckNumForName(name);
+
+    if (lumpnum == -1)
+    {
+        fprintf(stderr, "DEH_LoadLumpByName: '%s' lump not found\n", name);
+        return 0;
+    }
+
+    return DEH_LoadLump(lumpnum);
+}
+
 // Checks the command line for -deh argument
 
 void DEH_Init(void)
@@ -417,5 +464,4 @@
         }
     }
 }
-
 
--- a/src/deh_main.h
+++ b/src/deh_main.h
@@ -42,6 +42,8 @@
 
 void DEH_Init(void);
 int DEH_LoadFile(char *filename);
+int DEH_LoadLump(int lumpnum);
+int DEH_LoadLumpByName(char *name);
 
 boolean DEH_ParseAssignment(char *line, char **variable_name, char **value);
 
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -104,6 +104,7 @@
 typedef enum
 {
     exe_doom_1_9,   // Doom 1.9: used for shareware, registered and commercial
+    exe_hacx,       // Hacx executable (Doom 1.9 with patch applied)
     exe_ultimate,   // Ultimate Doom (retail)
     exe_final,      // Final Doom
     exe_chex,       // Chex Quest executable (based on Final Doom)
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -784,6 +784,8 @@
     switch (gameversion)
     {
         case exe_doom_1_9:
+        case exe_hacx:
+
             if (gamemode == commercial)
             {
                 // Doom 2