shithub: choc

Download patch

ref: 8a77b34e936a3fd752db3bc1113e3d7bd0555440
parent: 8f6edc1f7402215c5e38d1f03939ce6b5ff5e3ae
author: Simon Howard <[email protected]>
date: Tue Feb 2 14:02:16 EST 2010

Move parts of dehacked code into top-level common code, to allow future
HHE and SEH support.

Subversion-branch: /branches/raven-branch
Subversion-revision: 1841

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -50,6 +50,7 @@
 d_iwad.c             d_iwad.h              \
 d_mode.c             d_mode.h              \
                      d_ticcmd.h            \
+deh_str.c            deh_str.h             \
 i_cdmus.c            i_cdmus.h             \
 i_endoom.c           i_endoom.h            \
 i_joystick.c         i_joystick.h          \
@@ -79,8 +80,12 @@
 
 # source files needed for FEATURE_DEHACKED
 
-FEATURE_DEHACKED_SOURCE_FILES=             \
-deh_str.c            deh_str.h
+FEATURE_DEHACKED_SOURCE_FILES =            \
+deh_defs.h                                 \
+deh_io.c             deh_io.h              \
+deh_main.c           deh_main.h            \
+deh_mapping.c        deh_mapping.h         \
+deh_text.c
 
 # source files needed for FEATURE_MULTIPLAYER
 
@@ -111,12 +116,15 @@
 i_sdlmusic.c                               \
 mus2mid.c            mus2mid.h
 
+# Some games support dehacked patches, some don't:
+
 SOURCE_FILES = $(COMMON_SOURCE_FILES)              \
                $(GAME_SOURCE_FILES)                \
-               $(FEATURE_DEHACKED_SOURCE_FILES)    \
                $(FEATURE_WAD_MERGE_SOURCE_FILES)   \
                $(FEATURE_SOUND_SOURCE_FILES)
 
+SOURCE_FILES_WITH_DEH = $(SOURCE_FILES)                    \
+                        $(FEATURE_DEHACKED_SOURCE_FILES)
 
 EXTRA_LIBS =                                               \
                $(top_builddir)/wince/libc_wince.a          \
@@ -128,9 +136,9 @@
                @SDLNET_LIBS@ 
 
 if HAVE_WINDRES
-@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES) resource.rc
+@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH) resource.rc
 else
-@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES)
+@PROGRAM_PREFIX@doom_SOURCES=$(SOURCE_FILES_WITH_DEH)
 endif
 
 @PROGRAM_PREFIX@doom_LDADD = doom/libdoom.a $(EXTRA_LIBS)
--- /dev/null
+++ b/src/deh_defs.h
@@ -1,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 initialize 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 */
+
+
--- /dev/null
+++ b/src/deh_io.c
@@ -1,0 +1,211 @@
+// 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;;)
+    {
+        c = DEH_GetChar(context);
+
+        if (c < 0)
+        {
+            // end of file
+
+            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 if (c != '\0')
+        {
+            // normal character; don't allow NUL characters to be
+            // added.
+
+            context->readbuffer[pos] = (char) c;
+            ++pos;
+        }
+    }
+    
+    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");
+}
+
+
--- /dev/null
+++ b/src/deh_io.h
@@ -1,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 */
+
--- /dev/null
+++ b/src/deh_main.c
@@ -1,0 +1,384 @@
+// 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"
+
+extern deh_section_t *deh_section_types[];
+extern char *deh_signatures[];
+
+// 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;
+
+// If false, dehacked cheat replacements are ignored.
+
+boolean deh_apply_cheats = true;
+
+void DEH_Checksum(md5_digest_t digest)
+{
+    md5_context_t md5_context;
+    unsigned int i;
+
+    MD5_Init(&md5_context);
+
+    for (i=0; deh_section_types[i] != NULL; ++i)
+    {
+        if (deh_section_types[i]->md5_hash != NULL)
+        {
+            deh_section_types[i]->md5_hash(&md5_context);
+        }
+    }
+
+    MD5_Final(digest, &md5_context);
+}
+
+// Called on startup to call the Init functions
+
+static void InitializeSections(void)
+{
+    unsigned int i;
+
+    for (i=0; deh_section_types[i] != NULL; ++i)
+    {
+        if (deh_section_types[i]->init != NULL)
+        {
+            deh_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; deh_section_types[i] != NULL; ++i)
+    {
+        if (!strcasecmp(deh_section_types[i]->name, name))
+        {
+            return deh_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; deh_signatures[i] != NULL; ++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;
+
+    InitializeSections();
+
+    //!
+    // @category mod
+    //
+    // Ignore cheats in dehacked files.
+    //
+
+    if (M_CheckParm("-nocheats") > 0) 
+    {
+	deh_apply_cheats = false;
+    }
+
+    //!
+    // @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;
+        }
+    }
+}
+
+
--- /dev/null
+++ b/src/deh_main.h
@@ -1,0 +1,54 @@
+// 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;
+extern boolean deh_apply_cheats;
+
+#endif /* #ifndef DEH_MAIN_H */
+
--- /dev/null
+++ b/src/deh_mapping.c
@@ -1,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;
+        }
+    }
+}
+
--- /dev/null
+++ b/src/deh_mapping.h
@@ -1,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 */
+
--- /dev/null
+++ b/src/deh_text.c
@@ -1,0 +1,127 @@
+// 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 <stdio.h>
+#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,
+};
+
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -63,15 +63,11 @@
 FEATURE_DEHACKED_SOURCE_FILES =            \
 deh_ammo.c                                 \
 deh_cheat.c                                \
-deh_defs.h                                 \
+deh_doom.c                                 \
 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
 
--- a/src/doom/deh_defs.h
+++ /dev/null
@@ -1,68 +1,0 @@
-// 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 initialize 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 */
-
-
--- /dev/null
+++ b/src/doom/deh_doom.c
@@ -1,0 +1,74 @@
+// 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.
+//
+//-----------------------------------------------------------------------------
+//
+// Top-level dehacked definitions for Doom dehacked.
+//
+//-----------------------------------------------------------------------------
+
+#include <stdlib.h>
+#include "deh_defs.h"
+#include "deh_main.h"
+
+char *deh_signatures[] =
+{
+    "Patch File for DeHackEd v2.3",
+    "Patch File for DeHackEd v3.0",
+    NULL
+};
+
+// 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;
+
+//
+// List of section types:
+//
+
+deh_section_t *deh_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,
+    NULL
+};
+
--- a/src/doom/deh_io.c
+++ /dev/null
@@ -1,211 +1,0 @@
-// 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;;)
-    {
-        c = DEH_GetChar(context);
-
-        if (c < 0)
-        {
-            // end of file
-
-            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 if (c != '\0')
-        {
-            // normal character; don't allow NUL characters to be
-            // added.
-
-            context->readbuffer[pos] = (char) c;
-            ++pos;
-        }
-    }
-    
-    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");
-}
-
-
--- a/src/doom/deh_io.h
+++ /dev/null
@@ -1,40 +1,0 @@
-// 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 */
-
--- a/src/doom/deh_main.c
+++ /dev/null
@@ -1,423 +1,0 @@
-// 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;
-
-// If false, dehacked cheat replacements are ignored.
-
-boolean deh_apply_cheats = true;
-
-//
-// 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 InitializeSections(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;
-
-    InitializeSections();
-
-    //!
-    // @category mod
-    //
-    // Ignore cheats in dehacked files.
-    //
-
-    if (M_CheckParm("-nocheats") > 0) 
-    {
-	deh_apply_cheats = false;
-    }
-
-    //!
-    // @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;
-        }
-    }
-}
-
-
--- a/src/doom/deh_main.h
+++ /dev/null
@@ -1,54 +1,0 @@
-// 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;
-extern boolean deh_apply_cheats;
-
-#endif /* #ifndef DEH_MAIN_H */
-
--- a/src/doom/deh_mapping.c
+++ /dev/null
@@ -1,133 +1,0 @@
-// 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;
-        }
-    }
-}
-
--- a/src/doom/deh_mapping.h
+++ /dev/null
@@ -1,90 +1,0 @@
-// 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 */
-
--- a/src/doom/deh_text.c
+++ /dev/null
@@ -1,127 +1,0 @@
-// 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 <stdio.h>
-#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,
-};
-