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