summaryrefslogtreecommitdiff
path: root/src/doom
diff options
context:
space:
mode:
Diffstat (limited to 'src/doom')
-rw-r--r--src/doom/Makefile.am18
-rw-r--r--src/doom/deh_ammo.c111
-rw-r--r--src/doom/deh_cheat.c148
-rw-r--r--src/doom/deh_defs.h68
-rw-r--r--src/doom/deh_frame.c169
-rw-r--r--src/doom/deh_io.c212
-rw-r--r--src/doom/deh_io.h40
-rw-r--r--src/doom/deh_main.c408
-rw-r--r--src/doom/deh_main.h53
-rw-r--r--src/doom/deh_mapping.c133
-rw-r--r--src/doom/deh_mapping.h90
-rw-r--r--src/doom/deh_misc.c237
-rw-r--r--src/doom/deh_misc.h92
-rw-r--r--src/doom/deh_ptr.c151
-rw-r--r--src/doom/deh_sound.c113
-rw-r--r--src/doom/deh_text.c126
-rw-r--r--src/doom/deh_thing.c140
-rw-r--r--src/doom/deh_weapon.c109
18 files changed, 2417 insertions, 1 deletions
diff --git a/src/doom/Makefile.am b/src/doom/Makefile.am
index 4d95266e..3e142f93 100644
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -60,5 +60,21 @@ st_lib.c st_lib.h \
st_stuff.c st_stuff.h \
wi_stuff.c wi_stuff.h
-libdoom_a_SOURCES=$(SOURCE_FILES)
+FEATURE_DEHACKED_SOURCE_FILES = \
+deh_ammo.c \
+deh_cheat.c \
+deh_defs.h \
+deh_frame.c \
+deh_io.c deh_io.h \
+deh_main.c deh_main.h \
+deh_mapping.c deh_mapping.h \
+deh_misc.c deh_misc.h \
+deh_ptr.c \
+deh_sound.c \
+deh_text.c \
+deh_thing.c \
+deh_weapon.c
+
+libdoom_a_SOURCES = $(SOURCE_FILES) \
+ $(FEATURE_DEHACKED_SOURCE_FILES)
diff --git a/src/doom/deh_ammo.c b/src/doom/deh_ammo.c
new file mode 100644
index 00000000..eb26ef75
--- /dev/null
+++ b/src/doom/deh_ammo.c
@@ -0,0 +1,111 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Ammo" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "p_local.h"
+
+static void *DEH_AmmoStart(deh_context_t *context, char *line)
+{
+ int ammo_number = 0;
+
+ if (sscanf(line, "Ammo %i", &ammo_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (ammo_number < 0 || ammo_number >= NUMAMMO)
+ {
+ DEH_Warning(context, "Invalid ammo number: %i", ammo_number);
+ return NULL;
+ }
+
+ return &maxammo[ammo_number];
+}
+
+static void DEH_AmmoParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ int ivalue;
+ int ammo_number;
+
+ if (tag == NULL)
+ return;
+
+ ammo_number = ((int *) tag) - maxammo;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ // maxammo
+
+ if (!strcasecmp(variable_name, "Per ammo"))
+ clipammo[ammo_number] = ivalue;
+ else if (!strcasecmp(variable_name, "Max ammo"))
+ maxammo[ammo_number] = ivalue;
+ else
+ {
+ DEH_Warning(context, "Field named '%s' not found", variable_name);
+ }
+}
+
+static void DEH_AmmoMD5Hash(md5_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMAMMO; ++i)
+ {
+ MD5_UpdateInt32(context, clipammo[i]);
+ MD5_UpdateInt32(context, maxammo[i]);
+ }
+}
+
+deh_section_t deh_section_ammo =
+{
+ "Ammo",
+ NULL,
+ DEH_AmmoStart,
+ DEH_AmmoParseLine,
+ NULL,
+ DEH_AmmoMD5Hash,
+};
+
diff --git a/src/doom/deh_cheat.c b/src/doom/deh_cheat.c
new file mode 100644
index 00000000..d4ea9113
--- /dev/null
+++ b/src/doom/deh_cheat.c
@@ -0,0 +1,148 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Cheat" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomtype.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "am_map.h"
+#include "st_stuff.h"
+
+typedef struct
+{
+ char *name;
+ cheatseq_t *seq;
+} deh_cheat_t;
+
+static deh_cheat_t allcheats[] =
+{
+ {"Change music", &cheat_mus },
+ {"Chainsaw", &cheat_choppers },
+ {"God mode", &cheat_god },
+ {"Ammo & Keys", &cheat_ammo },
+ {"Ammo", &cheat_ammonokey },
+ {"No Clipping 1", &cheat_noclip },
+ {"No Clipping 2", &cheat_commercial_noclip },
+ {"Invincibility", &cheat_powerup[0] },
+ {"Berserk", &cheat_powerup[1] },
+ {"Invisibility", &cheat_powerup[2] },
+ {"Radiation Suit", &cheat_powerup[3] },
+ {"Auto-map", &cheat_powerup[4] },
+ {"Lite-Amp Goggles", &cheat_powerup[5] },
+ {"BEHOLD menu", &cheat_powerup[6] },
+ {"Level Warp", &cheat_clev },
+ {"Player Position", &cheat_mypos },
+ {"Map cheat", &cheat_amap },
+};
+
+static deh_cheat_t *FindCheatByName(char *name)
+{
+ size_t i;
+
+ for (i=0; i<arrlen(allcheats); ++i)
+ {
+ if (!strcasecmp(allcheats[i].name, name))
+ return &allcheats[i];
+ }
+
+ return NULL;
+}
+
+static void *DEH_CheatStart(deh_context_t *context, char *line)
+{
+ return NULL;
+}
+
+static void DEH_CheatParseLine(deh_context_t *context, char *line, void *tag)
+{
+ deh_cheat_t *cheat;
+ char *variable_name;
+ char *value;
+ unsigned char *unsvalue;
+ unsigned int i;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ unsvalue = (unsigned char *) value;
+
+ cheat = FindCheatByName(variable_name);
+
+ if (cheat == NULL)
+ {
+ DEH_Warning(context, "Unknown cheat '%s'", variable_name);
+ return;
+ }
+
+ // write the value into the cheat sequence
+
+ i = 0;
+
+ while (unsvalue[i] != 0 && unsvalue[i] != 0xff)
+ {
+ // If the cheat length exceeds the Vanilla limit, stop. This
+ // does not apply if we have the limit turned off.
+
+ if (!deh_allow_long_cheats && i >= cheat->seq->sequence_len)
+ {
+ DEH_Warning(context, "Cheat sequence longer than supported by "
+ "Vanilla dehacked");
+ break;
+ }
+
+ cheat->seq->sequence[i] = unsvalue[i];
+ ++i;
+
+ // Absolute limit - don't exceed
+
+ if (i >= MAX_CHEAT_LEN - cheat->seq->parameter_chars)
+ {
+ DEH_Error(context, "Cheat sequence too long!");
+ return;
+ }
+ }
+
+ cheat->seq->sequence[i] = '\0';
+}
+
+deh_section_t deh_section_cheat =
+{
+ "Cheat",
+ NULL,
+ DEH_CheatStart,
+ DEH_CheatParseLine,
+ NULL,
+ NULL,
+};
+
diff --git a/src/doom/deh_defs.h b/src/doom/deh_defs.h
new file mode 100644
index 00000000..a6650544
--- /dev/null
+++ b/src/doom/deh_defs.h
@@ -0,0 +1,68 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Definitions for use in the dehacked code
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_DEFS_H
+#define DEH_DEFS_H
+
+#include "md5.h"
+
+typedef struct deh_context_s deh_context_t;
+typedef struct deh_section_s deh_section_t;
+typedef void (*deh_section_init_t)(void);
+typedef void *(*deh_section_start_t)(deh_context_t *context, char *line);
+typedef void (*deh_section_end_t)(deh_context_t *context, void *tag);
+typedef void (*deh_line_parser_t)(deh_context_t *context, char *line, void *tag);
+typedef void (*deh_md5_hash_t)(md5_context_t *context);
+
+struct deh_section_s
+{
+ char *name;
+
+ // Called on startup to initialise code
+
+ deh_section_init_t init;
+
+ // This is called when a new section is started. The pointer
+ // returned is used as a tag for the following calls.
+
+ deh_section_start_t start;
+
+ // This is called for each line in the section
+
+ deh_line_parser_t line_parser;
+
+ // This is called at the end of the section for any cleanup
+
+ deh_section_end_t end;
+
+ // Called when generating an MD5 sum of the dehacked state
+
+ deh_md5_hash_t md5_hash;
+};
+
+#endif /* #ifndef DEH_DEFS_H */
+
+
diff --git a/src/doom/deh_frame.c b/src/doom/deh_frame.c
new file mode 100644
index 00000000..3972f8df
--- /dev/null
+++ b/src/doom/deh_frame.c
@@ -0,0 +1,169 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Frame" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+
+#include "doomtype.h"
+#include "d_items.h"
+#include "info.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+DEH_BEGIN_MAPPING(state_mapping, state_t)
+ DEH_MAPPING("Sprite number", sprite)
+ DEH_MAPPING("Sprite subnumber", frame)
+ DEH_MAPPING("Duration", tics)
+ DEH_MAPPING("Next frame", nextstate)
+ DEH_MAPPING("Unknown 1", misc1)
+ DEH_MAPPING("Unknown 2", misc2)
+ DEH_UNSUPPORTED_MAPPING("Codep frame")
+DEH_END_MAPPING
+
+static void *DEH_FrameStart(deh_context_t *context, char *line)
+{
+ int frame_number = 0;
+ state_t *state;
+
+ if (sscanf(line, "Frame %i", &frame_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (frame_number < 0 || frame_number >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid frame number: %i", frame_number);
+ return NULL;
+ }
+
+ if (frame_number >= DEH_VANILLA_NUMSTATES)
+ {
+ DEH_Warning(context, "Attempt to modify frame %i: this will cause "
+ "problems in Vanilla dehacked.", frame_number);
+ }
+
+ state = &states[frame_number];
+
+ return state;
+}
+
+// Simulate a frame overflow: Doom has 967 frames in the states[] array, but
+// DOS dehacked internally only allocates memory for 966. As a result,
+// attempts to set frame 966 (the last frame) will overflow the dehacked
+// array and overwrite the weaponinfo[] array instead.
+//
+// This is noticable in Batman Doom where it is impossible to switch weapons
+// away from the fist once selected.
+
+static void DEH_FrameOverflow(deh_context_t *context, char *varname, int value)
+{
+ if (!strcasecmp(varname, "Duration"))
+ {
+ weaponinfo[0].ammo = value;
+ }
+ else if (!strcasecmp(varname, "Codep frame"))
+ {
+ weaponinfo[0].upstate = value;
+ }
+ else if (!strcasecmp(varname, "Next frame"))
+ {
+ weaponinfo[0].downstate = value;
+ }
+ else if (!strcasecmp(varname, "Unknown 1"))
+ {
+ weaponinfo[0].readystate = value;
+ }
+ else if (!strcasecmp(varname, "Unknown 2"))
+ {
+ weaponinfo[0].atkstate = value;
+ }
+ else
+ {
+ DEH_Error(context, "Unable to simulate frame overflow: field '%s'",
+ varname);
+ }
+}
+
+static void DEH_FrameParseLine(deh_context_t *context, char *line, void *tag)
+{
+ state_t *state;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ state = (state_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ if (state == &states[NUMSTATES - 1])
+ {
+ DEH_FrameOverflow(context, variable_name, ivalue);
+ }
+ else
+ {
+ // set the appropriate field
+
+ DEH_SetMapping(context, &state_mapping, state, variable_name, ivalue);
+ }
+}
+
+static void DEH_FrameMD5Sum(md5_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
+ DEH_StructMD5Sum(context, &state_mapping, &states[i]);
+ }
+}
+
+deh_section_t deh_section_frame =
+{
+ "Frame",
+ NULL,
+ DEH_FrameStart,
+ DEH_FrameParseLine,
+ NULL,
+ DEH_FrameMD5Sum,
+};
+
diff --git a/src/doom/deh_io.c b/src/doom/deh_io.c
new file mode 100644
index 00000000..77cc40a1
--- /dev/null
+++ b/src/doom/deh_io.c
@@ -0,0 +1,212 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Dehacked I/O code (does all reads from dehacked files)
+//
+//-----------------------------------------------------------------------------
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "i_system.h"
+#include "z_zone.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+
+struct deh_context_s
+{
+ FILE *stream;
+ char *filename;
+ int linenum;
+ boolean last_was_newline;
+ char *readbuffer;
+ int readbuffer_size;
+};
+
+// Open a dehacked file for reading
+// Returns NULL if open failed
+
+deh_context_t *DEH_OpenFile(char *filename)
+{
+ FILE *fstream;
+ deh_context_t *context;
+
+ fstream = fopen(filename, "r");
+
+ if (fstream == NULL)
+ return NULL;
+
+ context = Z_Malloc(sizeof(*context), PU_STATIC, NULL);
+ context->stream = fstream;
+
+ // Initial read buffer size of 128 bytes
+
+ 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;
+}
+
+// Close dehacked file
+
+void DEH_CloseFile(deh_context_t *context)
+{
+ fclose(context->stream);
+ Z_Free(context->readbuffer);
+ Z_Free(context);
+}
+
+// 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
+ {
+ if (feof(context->stream))
+ {
+ // end of file
+
+ result = -1;
+ }
+ else
+ {
+ result = fgetc(context->stream);
+ }
+
+ } while (result == '\r');
+
+ // Track the current line number
+
+ if (context->last_was_newline)
+ {
+ ++context->linenum;
+ }
+
+ context->last_was_newline = result == '\n';
+
+ return result;
+}
+
+// Increase the read buffer size
+
+static void IncreaseReadBuffer(deh_context_t *context)
+{
+ char *newbuffer;
+ int newbuffer_size;
+
+ newbuffer_size = context->readbuffer_size * 2;
+ newbuffer = Z_Malloc(newbuffer_size, PU_STATIC, NULL);
+
+ memcpy(newbuffer, context->readbuffer, context->readbuffer_size);
+
+ Z_Free(context->readbuffer);
+
+ context->readbuffer = newbuffer;
+ context->readbuffer_size = newbuffer_size;
+}
+
+// Read a whole line
+
+char *DEH_ReadLine(deh_context_t *context)
+{
+ int c;
+ int pos;
+
+ for (pos=0; ; ++pos)
+ {
+ c = DEH_GetChar(context);
+
+ if (c < 0)
+ {
+ // end of file
+
+ return NULL;
+ }
+
+ if (c == '\0')
+ {
+ return NULL;
+ }
+
+ // cope with lines of any length: increase the buffer size
+
+ if (pos >= context->readbuffer_size)
+ {
+ IncreaseReadBuffer(context);
+ }
+
+ if (c == '\n')
+ {
+ // end of line: a full line has been read
+
+ context->readbuffer[pos] = '\0';
+ break;
+ }
+ else
+ {
+ context->readbuffer[pos] = (char) c;
+ }
+ }
+
+ return context->readbuffer;
+}
+
+void DEH_Warning(deh_context_t *context, char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s:%i: warning: ", context->filename, context->linenum);
+ vfprintf(stderr, msg, args);
+ fprintf(stderr, "\n");
+
+ va_end(args);
+}
+
+void DEH_Error(deh_context_t *context, char *msg, ...)
+{
+ va_list args;
+
+ va_start(args, msg);
+
+ fprintf(stderr, "%s:%i: ", context->filename, context->linenum);
+ vfprintf(stderr, msg, args);
+ fprintf(stderr, "\n");
+
+ va_end(args);
+
+ I_Error("Error parsing dehacked file");
+}
+
+
diff --git a/src/doom/deh_io.h b/src/doom/deh_io.h
new file mode 100644
index 00000000..061a5a0e
--- /dev/null
+++ b/src/doom/deh_io.h
@@ -0,0 +1,40 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Dehacked I/O code (does all reads from dehacked files)
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_IO_H
+#define DEH_IO_H
+
+#include "deh_defs.h"
+
+deh_context_t *DEH_OpenFile(char *filename);
+void DEH_CloseFile(deh_context_t *context);
+int DEH_GetChar(deh_context_t *context);
+char *DEH_ReadLine(deh_context_t *context);
+void DEH_Error(deh_context_t *context, char *msg, ...);
+void DEH_Warning(deh_context_t *context, char *msg, ...);
+
+#endif /* #ifndef DEH_IO_H */
+
diff --git a/src/doom/deh_main.c b/src/doom/deh_main.c
new file mode 100644
index 00000000..9d528b0a
--- /dev/null
+++ b/src/doom/deh_main.c
@@ -0,0 +1,408 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Main dehacked code
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "doomtype.h"
+#include "d_iwad.h"
+#include "m_argv.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+
+static char *deh_signatures[] =
+{
+ "Patch File for DeHackEd v2.3",
+ "Patch File for DeHackEd v3.0",
+};
+
+// deh_ammo.c:
+extern deh_section_t deh_section_ammo;
+// deh_cheat.c:
+extern deh_section_t deh_section_cheat;
+// deh_frame.c:
+extern deh_section_t deh_section_frame;
+// deh_misc.c:
+extern deh_section_t deh_section_misc;
+// deh_ptr.c:
+extern deh_section_t deh_section_pointer;
+// deh_sound.c
+extern deh_section_t deh_section_sound;
+// deh_text.c:
+extern deh_section_t deh_section_text;
+// deh_thing.c:
+extern deh_section_t deh_section_thing;
+// deh_weapon.c:
+extern deh_section_t deh_section_weapon;
+
+// If true, we can do long string replacements.
+
+boolean deh_allow_long_strings = false;
+
+// If true, we can do cheat replacements longer than the originals.
+
+boolean deh_allow_long_cheats = false;
+
+//
+// List of section types:
+//
+
+static deh_section_t *section_types[] =
+{
+ &deh_section_ammo,
+ &deh_section_cheat,
+ &deh_section_frame,
+ &deh_section_misc,
+ &deh_section_pointer,
+ &deh_section_sound,
+ &deh_section_text,
+ &deh_section_thing,
+ &deh_section_weapon,
+};
+
+void DEH_Checksum(md5_digest_t digest)
+{
+ md5_context_t md5_context;
+ unsigned int i;
+
+ MD5_Init(&md5_context);
+
+ for (i=0; i<arrlen(section_types); ++i)
+ {
+ if (section_types[i]->md5_hash != NULL)
+ {
+ section_types[i]->md5_hash(&md5_context);
+ }
+ }
+
+ MD5_Final(digest, &md5_context);
+}
+
+// Called on startup to call the Init functions
+
+static void InitialiseSections(void)
+{
+ unsigned int i;
+
+ for (i=0; i<arrlen(section_types); ++i)
+ {
+ if (section_types[i]->init != NULL)
+ {
+ section_types[i]->init();
+ }
+ }
+}
+
+// Given a section name, get the section structure which corresponds
+
+static deh_section_t *GetSectionByName(char *name)
+{
+ unsigned int i;
+
+ for (i=0; i<arrlen(section_types); ++i)
+ {
+ if (!strcasecmp(section_types[i]->name, name))
+ {
+ return section_types[i];
+ }
+ }
+
+ return NULL;
+}
+
+// Is the string passed just whitespace?
+
+static boolean IsWhitespace(char *s)
+{
+ for (; *s; ++s)
+ {
+ if (!isspace(*s))
+ return false;
+ }
+
+ return true;
+}
+
+// Strip whitespace from the start and end of a string
+
+static char *CleanString(char *s)
+{
+ char *strending;
+
+ // Leading whitespace
+
+ while (*s && isspace(*s))
+ ++s;
+
+ // Trailing whitespace
+
+ strending = s + strlen(s) - 1;
+
+ while (strlen(s) > 0 && isspace(*strending))
+ {
+ *strending = '\0';
+ --strending;
+ }
+
+ return s;
+}
+
+// This pattern is used a lot of times in different sections,
+// an assignment is essentially just a statement of the form:
+//
+// Variable Name = Value
+//
+// The variable name can include spaces or any other characters.
+// The string is split on the '=', essentially.
+//
+// Returns true if read correctly
+
+boolean DEH_ParseAssignment(char *line, char **variable_name, char **value)
+{
+ char *p;
+
+ // find the equals
+
+ p = strchr(line, '=');
+
+ if (p == NULL && p-line > 2)
+ {
+ return false;
+ }
+
+ // variable name at the start
+ // turn the '=' into a \0 to terminate the string here
+
+ *p = '\0';
+ *variable_name = CleanString(line);
+
+ // value immediately follows the '='
+
+ *value = CleanString(p+1);
+
+ return true;
+}
+
+static boolean CheckSignatures(deh_context_t *context)
+{
+ size_t i;
+ char *line;
+
+ // Read the first line
+
+ line = DEH_ReadLine(context);
+
+ if (line == NULL)
+ {
+ return false;
+ }
+
+ // Check all signatures to see if one matches
+
+ for (i=0; i<arrlen(deh_signatures); ++i)
+ {
+ if (!strcmp(deh_signatures[i], line))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Parses a comment string in a dehacked file.
+
+static void DEH_ParseComment(char *comment)
+{
+ // Allow comments containing this special value to allow string
+ // replacements longer than those permitted by DOS dehacked.
+ // This allows us to use a dehacked patch for doing string
+ // replacements for emulating Chex Quest.
+ //
+ // If you use this, your dehacked patch may not work in Vanilla
+ // Doom.
+
+ if (strstr(comment, "*allow-long-strings*") != NULL)
+ {
+ deh_allow_long_strings = true;
+ }
+
+ // Allow magic comments to allow longer cheat replacements than
+ // those permitted by DOS dehacked. This is also for Chex
+ // Quest.
+
+ if (strstr(comment, "*allow-long-cheats*") != NULL)
+ {
+ deh_allow_long_cheats = true;
+ }
+}
+
+// Parses a dehacked file by reading from the context
+
+static void DEH_ParseContext(deh_context_t *context)
+{
+ deh_section_t *current_section = NULL;
+ char section_name[20];
+ void *tag = NULL;
+ char *line;
+
+ // Read the header and check it matches the signature
+
+ if (!CheckSignatures(context))
+ {
+ 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 (;;)
+ {
+ // read a new line
+
+ line = DEH_ReadLine(context);
+
+ // end of file?
+
+ if (line == NULL)
+ return;
+
+ while (line[0] != '\0' && isspace(line[0]))
+ ++line;
+
+ if (line[0] == '#')
+ {
+ // comment
+
+ DEH_ParseComment(line);
+ continue;
+ }
+
+ if (IsWhitespace(line))
+ {
+ if (current_section != NULL)
+ {
+ // end of section
+
+ if (current_section->end != NULL)
+ {
+ current_section->end(context, tag);
+ }
+
+ //printf("end %s tag\n", current_section->name);
+ current_section = NULL;
+ }
+ }
+ else
+ {
+ if (current_section != NULL)
+ {
+ // parse this line
+
+ current_section->line_parser(context, line, tag);
+ }
+ else
+ {
+ // possibly the start of a new section
+
+ sscanf(line, "%19s", section_name);
+
+ current_section = GetSectionByName(section_name);
+
+ if (current_section != NULL)
+ {
+ tag = current_section->start(context, line);
+ //printf("started %s tag\n", section_name);
+ }
+ else
+ {
+ //printf("unknown section name %s\n", section_name);
+ }
+ }
+ }
+ }
+}
+
+// Parses a dehacked file
+
+int DEH_LoadFile(char *filename)
+{
+ deh_context_t *context;
+
+ printf(" loading %s\n", filename);
+
+ context = DEH_OpenFile(filename);
+
+ if (context == NULL)
+ {
+ fprintf(stderr, "DEH_LoadFile: Unable to open %s\n", filename);
+ return 0;
+ }
+
+ DEH_ParseContext(context);
+
+ DEH_CloseFile(context);
+
+ return 1;
+}
+
+// Checks the command line for -deh argument
+
+void DEH_Init(void)
+{
+ char *filename;
+ int p;
+
+ InitialiseSections();
+
+ //!
+ // @arg <files>
+ // @category mod
+ //
+ // Load the given dehacked patch(es)
+ //
+
+ p = M_CheckParm("-deh");
+
+ if (p > 0)
+ {
+ ++p;
+
+ while (p < myargc && myargv[p][0] != '-')
+ {
+ filename = D_TryFindWADByName(myargv[p]);
+ DEH_LoadFile(filename);
+ ++p;
+ }
+ }
+}
+
+
diff --git a/src/doom/deh_main.h b/src/doom/deh_main.h
new file mode 100644
index 00000000..8a0587ff
--- /dev/null
+++ b/src/doom/deh_main.h
@@ -0,0 +1,53 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Dehacked entrypoint and common code
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_MAIN_H
+#define DEH_MAIN_H
+
+#include "doomtype.h"
+#include "doomfeatures.h"
+#include "md5.h"
+#include "deh_str.h"
+
+// These are the limits that dehacked uses (from dheinit.h in the dehacked
+// source). If these limits are exceeded, it does not generate an error, but
+// a warning is displayed.
+
+#define DEH_VANILLA_NUMSTATES 966
+#define DEH_VANILLA_NUMSFX 107
+
+void DEH_Init(void);
+int DEH_LoadFile(char *filename);
+
+boolean DEH_ParseAssignment(char *line, char **variable_name, char **value);
+
+void DEH_Checksum(md5_digest_t digest);
+
+extern boolean deh_allow_long_strings;
+extern boolean deh_allow_long_cheats;
+
+#endif /* #ifndef DEH_MAIN_H */
+
diff --git a/src/doom/deh_mapping.c b/src/doom/deh_mapping.c
new file mode 100644
index 00000000..b215b128
--- /dev/null
+++ b/src/doom/deh_mapping.c
@@ -0,0 +1,133 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Dehacked "mapping" code
+// Allows the fields in structures to be mapped out and accessed by
+// name
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "i_system.h"
+#include "deh_mapping.h"
+
+//
+// Set the value of a particular field in a structure by name
+//
+
+boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
+ void *structptr, char *name, int value)
+{
+ int i;
+
+ for (i=0; mapping->entries[i].name != NULL; ++i)
+ {
+ deh_mapping_entry_t *entry = &mapping->entries[i];
+
+ if (!strcasecmp(entry->name, name))
+ {
+ void *location;
+
+ if (entry->location == NULL)
+ {
+ DEH_Warning(context, "Field '%s' is unsupported", name);
+ return false;
+ }
+
+ location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
+
+ // printf("Setting %p::%s to %i (%i bytes)\n",
+ // structptr, name, value, entry->size);
+
+ switch (entry->size)
+ {
+ case 1:
+ * ((uint8_t *) location) = value;
+ break;
+ case 2:
+ * ((uint16_t *) location) = value;
+ break;
+ case 4:
+ * ((uint32_t *) location) = value;
+ break;
+ default:
+ DEH_Error(context, "Unknown field type for '%s' (BUG)", name);
+ return false;
+ }
+
+ return true;
+ }
+ }
+
+ // field with this name not found
+
+ DEH_Warning(context, "Field named '%s' not found", name);
+
+ return false;
+}
+
+void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
+ void *structptr)
+{
+ int i;
+
+ // Go through each mapping
+
+ for (i=0; mapping->entries[i].name != NULL; ++i)
+ {
+ deh_mapping_entry_t *entry = &mapping->entries[i];
+ void *location;
+
+ if (entry->location == NULL)
+ {
+ // Unsupported field
+
+ continue;
+ }
+
+ // Add in data for this field
+
+ location = (uint8_t *)structptr + ((uint8_t *)entry->location - (uint8_t *)mapping->base);
+
+ switch (entry->size)
+ {
+ case 1:
+ MD5_UpdateInt32(context, *((uint8_t *) location));
+ break;
+ case 2:
+ MD5_UpdateInt32(context, *((uint16_t *) location));
+ break;
+ case 4:
+ MD5_UpdateInt32(context, *((uint32_t *) location));
+ break;
+ default:
+ I_Error("Unknown dehacked mapping field type for '%s' (BUG)",
+ entry->name);
+ break;
+ }
+ }
+}
+
diff --git a/src/doom/deh_mapping.h b/src/doom/deh_mapping.h
new file mode 100644
index 00000000..4862dec9
--- /dev/null
+++ b/src/doom/deh_mapping.h
@@ -0,0 +1,90 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Dehacked "mapping" code
+// Allows the fields in structures to be mapped out and accessed by
+// name
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_MAPPING_H
+#define DEH_MAPPING_H
+
+#include "doomtype.h"
+#include "deh_io.h"
+#include "md5.h"
+
+#define DEH_BEGIN_MAPPING(mapping_name, structname) \
+ static structname deh_mapping_base; \
+ static deh_mapping_t mapping_name = \
+ { \
+ &deh_mapping_base, \
+ {
+
+#define DEH_MAPPING(deh_name, fieldname) \
+ {deh_name, &deh_mapping_base.fieldname, \
+ sizeof(deh_mapping_base.fieldname)},
+
+#define DEH_UNSUPPORTED_MAPPING(deh_name) \
+ {deh_name, NULL, -1},
+
+#define DEH_END_MAPPING \
+ {NULL, NULL, -1} \
+ } \
+ };
+
+
+
+#define MAX_MAPPING_ENTRIES 32
+
+typedef struct deh_mapping_s deh_mapping_t;
+typedef struct deh_mapping_entry_s deh_mapping_entry_t;
+
+struct deh_mapping_entry_s
+{
+ // field name
+
+ char *name;
+
+ // location relative to the base in the deh_mapping_t struct
+ // If this is NULL, it is an unsupported mapping
+
+ void *location;
+
+ // field size
+
+ int size;
+};
+
+struct deh_mapping_s
+{
+ void *base;
+ deh_mapping_entry_t entries[MAX_MAPPING_ENTRIES];
+};
+
+boolean DEH_SetMapping(deh_context_t *context, deh_mapping_t *mapping,
+ void *structptr, char *name, int value);
+void DEH_StructMD5Sum(md5_context_t *context, deh_mapping_t *mapping,
+ void *structptr);
+
+#endif /* #ifndef DEH_MAPPING_H */
+
diff --git a/src/doom/deh_misc.c b/src/doom/deh_misc.c
new file mode 100644
index 00000000..b57d0ef0
--- /dev/null
+++ b/src/doom/deh_misc.c
@@ -0,0 +1,237 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Misc" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+#include "deh_misc.h"
+
+// Dehacked: "Initial Health"
+// This is the initial health a player has when starting anew.
+// See G_PlayerReborn in g_game.c
+
+int deh_initial_health = DEH_DEFAULT_INITIAL_HEALTH;
+
+// Dehacked: "Initial bullets"
+// This is the number of bullets the player has when starting anew.
+// See G_PlayerReborn in g_game.c
+
+int deh_initial_bullets = DEH_DEFAULT_INITIAL_BULLETS;
+
+// Dehacked: "Max Health"
+// This is the maximum health that can be reached using medikits
+// alone. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_health = DEH_DEFAULT_MAX_HEALTH;
+
+// Dehacked: "Max Armor"
+// This is the maximum armor which can be reached by picking up
+// armor helmets. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_armor = DEH_DEFAULT_MAX_ARMOR;
+
+// Dehacked: "Green Armor Class"
+// This is the armor class that is given when picking up the green
+// armor or an armor helmet. See P_TouchSpecialThing in p_inter.c
+//
+// DOS dehacked only modifies the behavior of the green armor shirt,
+// the armor class set by armor helmets is not affected.
+
+int deh_green_armor_class = DEH_DEFAULT_GREEN_ARMOR_CLASS;
+
+// Dehacked: "Blue Armor Class"
+// This is the armor class that is given when picking up the blue
+// armor or a megasphere. See P_TouchSpecialThing in p_inter.c
+//
+// DOS dehacked only modifies the MegaArmor behavior and not
+// the MegaSphere, which always gives armor type 2.
+
+int deh_blue_armor_class = DEH_DEFAULT_BLUE_ARMOR_CLASS;
+
+// Dehacked: "Max soulsphere"
+// The maximum health which can be reached by picking up the
+// soulsphere. See P_TouchSpecialThing in p_inter.c
+
+int deh_max_soulsphere = DEH_DEFAULT_MAX_SOULSPHERE;
+
+// Dehacked: "Soulsphere health"
+// The amount of health bonus that picking up a soulsphere
+// gives. See P_TouchSpecialThing in p_inter.c
+
+int deh_soulsphere_health = DEH_DEFAULT_SOULSPHERE_HEALTH;
+
+// Dehacked: "Megasphere health"
+// This is what the health is set to after picking up a
+// megasphere. See P_TouchSpecialThing in p_inter.c
+
+int deh_megasphere_health = DEH_DEFAULT_MEGASPHERE_HEALTH;
+
+// Dehacked: "God mode health"
+// This is what the health value is set to when cheating using
+// the IDDQD god mode cheat. See ST_Responder in st_stuff.c
+
+int deh_god_mode_health = DEH_DEFAULT_GOD_MODE_HEALTH;
+
+// Dehacked: "IDFA Armor"
+// This is what the armor is set to when using the IDFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idfa_armor = DEH_DEFAULT_IDFA_ARMOR;
+
+// Dehacked: "IDFA Armor Class"
+// This is what the armor class is set to when using the IDFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idfa_armor_class = DEH_DEFAULT_IDFA_ARMOR_CLASS;
+
+// Dehacked: "IDKFA Armor"
+// This is what the armor is set to when using the IDKFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idkfa_armor = DEH_DEFAULT_IDKFA_ARMOR;
+
+// Dehacked: "IDKFA Armor Class"
+// This is what the armor class is set to when using the IDKFA cheat.
+// See ST_Responder in st_stuff.c
+
+int deh_idkfa_armor_class = DEH_DEFAULT_IDKFA_ARMOR_CLASS;
+
+// Dehacked: "BFG Cells/Shot"
+// This is the number of CELLs firing the BFG uses up.
+// See P_CheckAmmo and A_FireBFG in p_pspr.c
+
+int deh_bfg_cells_per_shot = DEH_DEFAULT_BFG_CELLS_PER_SHOT;
+
+// Dehacked: "Monsters infight"
+// This controls whether monsters can harm other monsters of the same
+// species. For example, whether an imp fireball will damage other
+// imps. The value of this in dehacked patches is weird - '202' means
+// off, while '221' means on.
+//
+// See PIT_CheckThing in p_map.c
+
+int deh_species_infighting = DEH_DEFAULT_SPECIES_INFIGHTING;
+
+static struct
+{
+ char *deh_name;
+ int *value;
+} misc_settings[] = {
+ {"Initial Health", &deh_initial_health},
+ {"Initial Bullets", &deh_initial_bullets},
+ {"Max Health", &deh_max_health},
+ {"Max Armor", &deh_max_armor},
+ {"Green Armor Class", &deh_green_armor_class},
+ {"Blue Armor Class", &deh_blue_armor_class},
+ {"Max Soulsphere", &deh_max_soulsphere},
+ {"Soulsphere Health", &deh_soulsphere_health},
+ {"Megasphere Health", &deh_megasphere_health},
+ {"God Mode Health", &deh_god_mode_health},
+ {"IDFA Armor", &deh_idfa_armor},
+ {"IDFA Armor Class", &deh_idfa_armor_class},
+ {"IDKFA Armor", &deh_idkfa_armor},
+ {"IDKFA Armor Class", &deh_idkfa_armor_class},
+ {"BFG Cells/Shot", &deh_bfg_cells_per_shot},
+};
+
+static void *DEH_MiscStart(deh_context_t *context, char *line)
+{
+ return NULL;
+}
+
+static void DEH_MiscParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ int ivalue;
+ size_t i;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ if (!strcasecmp(variable_name, "Monsters Infight"))
+ {
+ // See notes above.
+
+ if (ivalue == 202)
+ {
+ deh_species_infighting = 0;
+ }
+ else if (ivalue == 221)
+ {
+ deh_species_infighting = 1;
+ }
+ else
+ {
+ DEH_Warning(context,
+ "Invalid value for 'Monsters Infight': %i", ivalue);
+ }
+
+ return;
+ }
+
+ for (i=0; i<arrlen(misc_settings); ++i)
+ {
+ if (!strcasecmp(variable_name, misc_settings[i].deh_name))
+ {
+ *misc_settings[i].value = ivalue;
+ return;
+ }
+ }
+
+ DEH_Warning(context, "Unknown Misc variable '%s'", variable_name);
+}
+
+static void DEH_MiscMD5Sum(md5_context_t *context)
+{
+ unsigned int i;
+
+ for (i=0; i<arrlen(misc_settings); ++i)
+ {
+ MD5_UpdateInt32(context, *misc_settings[i].value);
+ }
+}
+
+deh_section_t deh_section_misc =
+{
+ "Misc",
+ NULL,
+ DEH_MiscStart,
+ DEH_MiscParseLine,
+ NULL,
+ DEH_MiscMD5Sum,
+};
+
diff --git a/src/doom/deh_misc.h b/src/doom/deh_misc.h
new file mode 100644
index 00000000..a589b104
--- /dev/null
+++ b/src/doom/deh_misc.h
@@ -0,0 +1,92 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Misc" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_MISC_H
+#define DEH_MISC_H
+
+#include "doomfeatures.h"
+
+#define DEH_DEFAULT_INITIAL_HEALTH 100
+#define DEH_DEFAULT_INITIAL_BULLETS 50
+#define DEH_DEFAULT_MAX_HEALTH 200
+#define DEH_DEFAULT_MAX_ARMOR 200
+#define DEH_DEFAULT_GREEN_ARMOR_CLASS 1
+#define DEH_DEFAULT_BLUE_ARMOR_CLASS 2
+#define DEH_DEFAULT_MAX_SOULSPHERE 200
+#define DEH_DEFAULT_SOULSPHERE_HEALTH 100
+#define DEH_DEFAULT_MEGASPHERE_HEALTH 200
+#define DEH_DEFAULT_GOD_MODE_HEALTH 100
+#define DEH_DEFAULT_IDFA_ARMOR 200
+#define DEH_DEFAULT_IDFA_ARMOR_CLASS 2
+#define DEH_DEFAULT_IDKFA_ARMOR 200
+#define DEH_DEFAULT_IDKFA_ARMOR_CLASS 2
+#define DEH_DEFAULT_BFG_CELLS_PER_SHOT 40
+#define DEH_DEFAULT_SPECIES_INFIGHTING 0
+
+#ifdef FEATURE_DEHACKED
+
+extern int deh_initial_health;
+extern int deh_initial_bullets;
+extern int deh_max_health;
+extern int deh_max_armor;
+extern int deh_green_armor_class;
+extern int deh_blue_armor_class;
+extern int deh_max_soulsphere;
+extern int deh_soulsphere_health;
+extern int deh_megasphere_health;
+extern int deh_god_mode_health;
+extern int deh_idfa_armor;
+extern int deh_idfa_armor_class;
+extern int deh_idkfa_armor;
+extern int deh_idkfa_armor_class;
+extern int deh_bfg_cells_per_shot;
+extern int deh_species_infighting;
+
+#else
+
+// If dehacked is disabled, hard coded values
+
+#define deh_initial_health DEH_DEFAULT_INITIAL_HEALTH
+#define deh_initial_bullets DEH_DEFAULT_INITIAL_BULLETS
+#define deh_max_health DEH_DEFAULT_MAX_HEALTH
+#define deh_max_armor DEH_DEFAULT_MAX_ARMOR
+#define deh_green_armor_class DEH_DEFAULT_GREEN_ARMOR_CLASS
+#define deh_blue_armor_class DEH_DEFAULT_BLUE_ARMOR_CLASS
+#define deh_max_soulsphere DEH_DEFAULT_MAX_SOULSPHERE
+#define deh_soulsphere_health DEH_DEFAULT_SOULSPHERE_HEALTH
+#define deh_megasphere_health DEH_DEFAULT_MEGASPHERE_HEALTH
+#define deh_god_mode_health DEH_DEFAULT_GOD_MODE_HEALTH
+#define deh_idfa_armor DEH_DEFAULT_IDFA_ARMOR
+#define deh_idfa_armor_class DEH_DEFAULT_IDFA_ARMOR_CLASS
+#define deh_idkfa_armor DEH_DEFAULT_IDKFA_ARMOR
+#define deh_idkfa_armor_class DEH_DEFAULT_IDKFA_ARMOR_CLASS
+#define deh_bfg_cells_per_shot DEH_DEFAULT_BFG_CELLS_PER_SHOT
+#define deh_species_infighting DEH_DEFAULT_SPECIES_INFIGHTING
+
+#endif
+
+#endif /* #ifndef DEH_MISC_H */
+
diff --git a/src/doom/deh_ptr.c b/src/doom/deh_ptr.c
new file mode 100644
index 00000000..87daf7d8
--- /dev/null
+++ b/src/doom/deh_ptr.c
@@ -0,0 +1,151 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses Action Pointer entries in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "info.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+
+static actionf_t codeptrs[NUMSTATES];
+
+static int CodePointerIndex(actionf_t *ptr)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
+ if (!memcmp(&codeptrs[i], ptr, sizeof(actionf_t)))
+ {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+static void DEH_PointerInit(void)
+{
+ int i;
+
+ // Initialise list of dehacked pointers
+
+ for (i=0; i<NUMSTATES; ++i)
+ codeptrs[i] = states[i].action;
+}
+
+static void *DEH_PointerStart(deh_context_t *context, char *line)
+{
+ int frame_number = 0;
+
+ // FIXME: can the third argument here be something other than "Frame"
+ // or are we ok?
+
+ if (sscanf(line, "Pointer %*i (%*s %i)", &frame_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (frame_number < 0 || frame_number >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid frame number: %i", frame_number);
+ return NULL;
+ }
+
+ return &states[frame_number];
+}
+
+static void DEH_PointerParseLine(deh_context_t *context, char *line, void *tag)
+{
+ state_t *state;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ state = (state_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+// printf("Set %s to %s for state\n", variable_name, value);
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // set the appropriate field
+
+ if (!strcasecmp(variable_name, "Codep frame"))
+ {
+ if (ivalue < 0 || ivalue >= NUMSTATES)
+ {
+ DEH_Warning(context, "Invalid state '%i'", ivalue);
+ }
+ else
+ {
+ state->action = codeptrs[ivalue];
+ }
+ }
+ else
+ {
+ DEH_Warning(context, "Unknown variable name '%s'", variable_name);
+ }
+}
+
+static void DEH_PointerMD5Sum(md5_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMSTATES; ++i)
+ {
+ MD5_UpdateInt32(context, CodePointerIndex(&states[i].action));
+ }
+}
+
+deh_section_t deh_section_pointer =
+{
+ "Pointer",
+ DEH_PointerInit,
+ DEH_PointerStart,
+ DEH_PointerParseLine,
+ NULL,
+ DEH_PointerMD5Sum,
+};
+
diff --git a/src/doom/deh_sound.c b/src/doom/deh_sound.c
new file mode 100644
index 00000000..b28154d9
--- /dev/null
+++ b/src/doom/deh_sound.c
@@ -0,0 +1,113 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Sound" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomfeatures.h"
+#include "doomtype.h"
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+#include "sounds.h"
+
+DEH_BEGIN_MAPPING(sound_mapping, sfxinfo_t)
+ DEH_UNSUPPORTED_MAPPING("Offset")
+ DEH_MAPPING("Zero/One", singularity)
+ DEH_MAPPING("Value", priority)
+ DEH_MAPPING("Zero 1", link)
+ DEH_MAPPING("Zero 2", pitch)
+ DEH_MAPPING("Zero 3", volume)
+ DEH_MAPPING("Zero 4", data)
+ DEH_MAPPING("Neg. One 1", usefulness)
+ DEH_MAPPING("Neg. One 2", lumpnum)
+DEH_END_MAPPING
+
+static void *DEH_SoundStart(deh_context_t *context, char *line)
+{
+ int sound_number = 0;
+
+ if (sscanf(line, "Sound %i", &sound_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (sound_number < 0 || sound_number >= NUMSFX)
+ {
+ DEH_Warning(context, "Invalid sound number: %i", sound_number);
+ return NULL;
+ }
+
+ if (sound_number >= DEH_VANILLA_NUMSFX)
+ {
+ DEH_Warning(context, "Attempt to modify SFX %i. This will cause "
+ "problems in Vanilla dehacked.", sound_number);
+ }
+
+ return &S_sfx[sound_number];
+}
+
+static void DEH_SoundParseLine(deh_context_t *context, char *line, void *tag)
+{
+ sfxinfo_t *sfx;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ sfx = (sfxinfo_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // Set the field value
+
+ DEH_SetMapping(context, &sound_mapping, sfx, variable_name, ivalue);
+
+}
+
+deh_section_t deh_section_sound =
+{
+ "Sound",
+ NULL,
+ DEH_SoundStart,
+ DEH_SoundParseLine,
+ NULL,
+ NULL,
+};
+
diff --git a/src/doom/deh_text.c b/src/doom/deh_text.c
new file mode 100644
index 00000000..caac59a3
--- /dev/null
+++ b/src/doom/deh_text.c
@@ -0,0 +1,126 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses Text substitution sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <string.h>
+
+#include "doomtype.h"
+
+#include "z_zone.h"
+
+#include "deh_defs.h"
+#include "deh_io.h"
+#include "deh_main.h"
+
+// Given a string length, find the maximum length of a
+// string that can replace it.
+
+static int TXT_MaxStringLength(int len)
+{
+ // Enough bytes for the string and the NUL terminator
+
+ len += 1;
+
+ // All strings in doom.exe are on 4-byte boundaries, so we may be able
+ // to support a slightly longer string.
+ // Extend up to the next 4-byte boundary
+
+ len += (4 - (len % 4)) % 4;
+
+ // Less one for the NUL terminator.
+
+ return len - 1;
+}
+
+static void *DEH_TextStart(deh_context_t *context, char *line)
+{
+ char *from_text, *to_text;
+ int fromlen, tolen;
+ int i;
+
+ if (sscanf(line, "Text %i %i", &fromlen, &tolen) != 2)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ // Only allow string replacements that are possible in Vanilla Doom.
+ // Chocolate Doom is unforgiving!
+
+ if (!deh_allow_long_strings && tolen > TXT_MaxStringLength(fromlen))
+ {
+ DEH_Error(context, "Replacement string is longer than the maximum "
+ "possible in doom.exe");
+ return NULL;
+ }
+
+ from_text = Z_Malloc(fromlen + 1, PU_STATIC, NULL);
+ to_text = Z_Malloc(tolen + 1, PU_STATIC, NULL);
+
+ // read in the "from" text
+
+ for (i=0; i<fromlen; ++i)
+ {
+ int c;
+
+ c = DEH_GetChar(context);
+
+ from_text[i] = c;
+ }
+
+ from_text[fromlen] = '\0';
+
+ // read in the "to" text
+
+ for (i=0; i<tolen; ++i)
+ {
+ int c;
+
+ c = DEH_GetChar(context);
+
+ to_text[i] = c;
+ }
+ to_text[tolen] = '\0';
+
+ DEH_AddStringReplacement(from_text, to_text);
+
+ return NULL;
+}
+
+static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag)
+{
+ // not used
+}
+
+deh_section_t deh_section_text =
+{
+ "Text",
+ NULL,
+ DEH_TextStart,
+ DEH_TextParseLine,
+ NULL,
+ NULL,
+};
+
diff --git a/src/doom/deh_thing.c b/src/doom/deh_thing.c
new file mode 100644
index 00000000..5400ae60
--- /dev/null
+++ b/src/doom/deh_thing.c
@@ -0,0 +1,140 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Thing" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "doomtype.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+#include "info.h"
+
+DEH_BEGIN_MAPPING(thing_mapping, mobjinfo_t)
+ DEH_MAPPING("ID #", doomednum)
+ DEH_MAPPING("Initial frame", spawnstate)
+ DEH_MAPPING("Hit points", spawnhealth)
+ DEH_MAPPING("First moving frame", seestate)
+ DEH_MAPPING("Alert sound", seesound)
+ DEH_MAPPING("Reaction time", reactiontime)
+ DEH_MAPPING("Attack sound", attacksound)
+ DEH_MAPPING("Injury frame", painstate)
+ DEH_MAPPING("Pain chance", painchance)
+ DEH_MAPPING("Pain sound", painsound)
+ DEH_MAPPING("Close attack frame", meleestate)
+ DEH_MAPPING("Far attack frame", missilestate)
+ DEH_MAPPING("Death frame", deathstate)
+ DEH_MAPPING("Exploding frame", xdeathstate)
+ DEH_MAPPING("Death sound", deathsound)
+ DEH_MAPPING("Speed", speed)
+ DEH_MAPPING("Width", radius)
+ DEH_MAPPING("Height", height)
+ DEH_MAPPING("Mass", mass)
+ DEH_MAPPING("Missile damage", damage)
+ DEH_MAPPING("Action sound", activesound)
+ DEH_MAPPING("Bits", flags)
+ DEH_MAPPING("Respawn frame", raisestate)
+DEH_END_MAPPING
+
+static void *DEH_ThingStart(deh_context_t *context, char *line)
+{
+ int thing_number = 0;
+ mobjinfo_t *mobj;
+
+ if (sscanf(line, "Thing %i", &thing_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ // dehacked files are indexed from 1
+ --thing_number;
+
+ if (thing_number < 0 || thing_number >= NUMMOBJTYPES)
+ {
+ DEH_Warning(context, "Invalid thing number: %i", thing_number);
+ return NULL;
+ }
+
+ mobj = &mobjinfo[thing_number];
+
+ return mobj;
+}
+
+static void DEH_ThingParseLine(deh_context_t *context, char *line, void *tag)
+{
+ mobjinfo_t *mobj;
+ char *variable_name, *value;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ mobj = (mobjinfo_t *) tag;
+
+ // Parse the assignment
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+// printf("Set %s to %s for mobj\n", variable_name, value);
+
+ // all values are integers
+
+ ivalue = atoi(value);
+
+ // Set the field value
+
+ DEH_SetMapping(context, &thing_mapping, mobj, variable_name, ivalue);
+}
+
+static void DEH_ThingMD5Sum(md5_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMMOBJTYPES; ++i)
+ {
+ DEH_StructMD5Sum(context, &thing_mapping, &mobjinfo[i]);
+ }
+}
+
+deh_section_t deh_section_thing =
+{
+ "Thing",
+ NULL,
+ DEH_ThingStart,
+ DEH_ThingParseLine,
+ NULL,
+ DEH_ThingMD5Sum,
+};
+
diff --git a/src/doom/deh_weapon.c b/src/doom/deh_weapon.c
new file mode 100644
index 00000000..7ffa159a
--- /dev/null
+++ b/src/doom/deh_weapon.c
@@ -0,0 +1,109 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// Copyright(C) 2005 Simon Howard
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+// 02111-1307, USA.
+//
+//-----------------------------------------------------------------------------
+//
+// Parses "Weapon" sections in dehacked files
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+
+#include "d_items.h"
+
+#include "deh_defs.h"
+#include "deh_main.h"
+#include "deh_mapping.h"
+
+DEH_BEGIN_MAPPING(weapon_mapping, weaponinfo_t)
+ DEH_MAPPING("Ammo type", ammo)
+ DEH_MAPPING("Deselect frame", upstate)
+ DEH_MAPPING("Select frame", downstate)
+ DEH_MAPPING("Bobbing frame", readystate)
+ DEH_MAPPING("Shooting frame", atkstate)
+ DEH_MAPPING("Firing frame", flashstate)
+DEH_END_MAPPING
+
+static void *DEH_WeaponStart(deh_context_t *context, char *line)
+{
+ int weapon_number = 0;
+
+ if (sscanf(line, "Weapon %i", &weapon_number) != 1)
+ {
+ DEH_Warning(context, "Parse error on section start");
+ return NULL;
+ }
+
+ if (weapon_number < 0 || weapon_number >= NUMWEAPONS)
+ {
+ DEH_Warning(context, "Invalid weapon number: %i", weapon_number);
+ return NULL;
+ }
+
+ return &weaponinfo[weapon_number];
+}
+
+static void DEH_WeaponParseLine(deh_context_t *context, char *line, void *tag)
+{
+ char *variable_name, *value;
+ weaponinfo_t *weapon;
+ int ivalue;
+
+ if (tag == NULL)
+ return;
+
+ weapon = (weaponinfo_t *) tag;
+
+ if (!DEH_ParseAssignment(line, &variable_name, &value))
+ {
+ // Failed to parse
+
+ DEH_Warning(context, "Failed to parse assignment");
+ return;
+ }
+
+ ivalue = atoi(value);
+
+ DEH_SetMapping(context, &weapon_mapping, weapon, variable_name, ivalue);
+}
+
+static void DEH_WeaponMD5Sum(md5_context_t *context)
+{
+ int i;
+
+ for (i=0; i<NUMWEAPONS ;++i)
+ {
+ DEH_StructMD5Sum(context, &weapon_mapping, &weaponinfo[i]);
+ }
+}
+
+deh_section_t deh_section_weapon =
+{
+ "Weapon",
+ NULL,
+ DEH_WeaponStart,
+ DEH_WeaponParseLine,
+ NULL,
+ DEH_WeaponMD5Sum,
+};
+