shithub: choc

Download patch

ref: 37865c5d5b53fd0427b6f22d0a13f830a74c3064
parent: cf7b4fab6313cd2162cb0bd3f28596fbdc2fffd3
author: Simon Howard <[email protected]>
date: Sun Sep 7 17:03:09 EDT 2008

Move dehacked code to doom/. Split dehacked string replacement code into
common code and remove dependencies on deh_main.h.

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

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -61,19 +61,7 @@
 # source files needed for FEATURE_DEHACKED
 
 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
+deh_str.c            deh_str.h
 
 # source files needed for FEATURE_MULTIPLAYER
 
--- a/src/deh_ammo.c
+++ /dev/null
@@ -1,111 +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 "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,
-};
-
--- a/src/deh_cheat.c
+++ /dev/null
@@ -1,148 +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 "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,
-};
-
--- a/src/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 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 */
-
-
--- a/src/deh_frame.c
+++ /dev/null
@@ -1,169 +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 "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,
-};
-
--- a/src/deh_io.c
+++ /dev/null
@@ -1,212 +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; ; ++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");
-}
-
-
--- a/src/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/deh_main.c
+++ /dev/null
@@ -1,408 +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;
-
-//
-// 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;
-        }
-    }
-}
-
-
--- a/src/deh_main.h
+++ /dev/null
@@ -1,66 +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"
-
-// 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);
-
-// deh_text.c:
-//
-// Used to do dehacked text substitutions throughout the program
-
-#ifdef FEATURE_DEHACKED
-
-char *DEH_String(char *s);
-
-#else
-
-#define DEH_String(x) (x)
-
-#endif
-
-extern boolean deh_allow_long_strings;
-extern boolean deh_allow_long_cheats;
-
-#endif /* #ifndef DEH_MAIN_H */
-
--- a/src/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/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/deh_misc.c
+++ /dev/null
@@ -1,237 +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 "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,
-};
-
--- a/src/deh_misc.h
+++ /dev/null
@@ -1,92 +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 "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 */
-
--- a/src/deh_ptr.c
+++ /dev/null
@@ -1,151 +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 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,
-};
-
--- a/src/deh_sound.c
+++ /dev/null
@@ -1,113 +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 "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,
-};
-
--- /dev/null
+++ b/src/deh_str.c
@@ -1,0 +1,180 @@
+// 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 <stdlib.h>
+#include <string.h>
+
+#include "doomtype.h"
+#include "deh_str.h"
+
+#include "z_zone.h"
+
+typedef struct 
+{
+    char *from_text;
+    char *to_text;
+} deh_substitution_t;
+
+static deh_substitution_t **hash_table = NULL;
+static int hash_table_entries;
+static int hash_table_length = -1;
+
+// This is the algorithm used by glib
+
+static unsigned int strhash(char *s)
+{
+    char *p = s;
+    unsigned int h = *p;
+  
+    if (h)
+    {
+        for (p += 1; *p; p++)
+            h = (h << 5) - h + *p;
+    }
+
+    return h;
+}
+
+// Look up a string to see if it has been replaced with something else
+// This will be used throughout the program to substitute text
+
+char *DEH_String(char *s)
+{
+    int entry;
+
+    // Fallback if we have not initialised the hash table yet
+
+    if (hash_table_length < 0)
+	return s;
+
+    entry = strhash(s) % hash_table_length;
+
+    while (hash_table[entry] != NULL)
+    {
+        if (!strcmp(hash_table[entry]->from_text, s))
+        {
+            // substitution found!
+
+            return hash_table[entry]->to_text;
+        }
+
+        entry = (entry + 1) % hash_table_length;
+    }
+
+    // no substitution found
+
+    return s;
+}
+
+static void InitHashTable(void)
+{
+    // init hash table
+    
+    hash_table_entries = 0;
+    hash_table_length = 16;
+    hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
+                          PU_STATIC, NULL);
+    memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
+}
+
+static void DEH_AddToHashtable(deh_substitution_t *sub);
+
+static void IncreaseHashtable(void)
+{
+    deh_substitution_t **old_table;
+    int old_table_length;
+    int i;
+    
+    // save the old table
+
+    old_table = hash_table;
+    old_table_length = hash_table_length;
+    
+    // double the size 
+
+    hash_table_length *= 2;
+    hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
+                          PU_STATIC, NULL);
+    memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
+
+    // go through the old table and insert all the old entries
+
+    for (i=0; i<old_table_length; ++i)
+    {
+        if (old_table[i] != NULL)
+        {
+            DEH_AddToHashtable(old_table[i]);
+        }
+    }
+
+    // free the old table
+
+    Z_Free(old_table);
+}
+
+static void DEH_AddToHashtable(deh_substitution_t *sub)
+{
+    int entry;
+
+    // if the hash table is more than 60% full, increase its size
+
+    if ((hash_table_entries * 10) / hash_table_length > 6)
+    {
+        IncreaseHashtable();
+    }
+    
+    // find where to insert it
+    
+    entry = strhash(sub->from_text) % hash_table_length;
+
+    while (hash_table[entry] != NULL)
+    {
+        entry = (entry + 1) % hash_table_length;
+    }
+
+    hash_table[entry] = sub;
+    ++hash_table_entries;
+}
+
+void DEH_AddStringReplacement(char *from_text, char *to_text)
+{
+    deh_substitution_t *sub;
+
+    // Initialise the hash table if this is the first time
+
+    if (hash_table_length < 0)
+    {
+        InitHashTable();
+    }
+
+    sub = Z_Malloc(sizeof(*sub), PU_STATIC, 0);
+
+    sub->from_text = from_text;
+    sub->to_text = to_text;
+
+    DEH_AddToHashtable(sub);
+}
+
--- /dev/null
+++ b/src/deh_str.h
@@ -1,0 +1,46 @@
+// 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 string replacements
+//
+//-----------------------------------------------------------------------------
+
+#ifndef DEH_STR_H
+#define DEH_STR_H
+
+#include "doomfeatures.h"
+
+// Used to do dehacked text substitutions throughout the program
+
+#ifdef FEATURE_DEHACKED
+
+char *DEH_String(char *s);
+void DEH_AddStringReplacement(char *from_text, char *to_text);
+
+#else
+
+#define DEH_String(x) (x)
+
+#endif
+
+#endif /* #ifndef DEH_STR_H */
+
--- a/src/deh_text.c
+++ /dev/null
@@ -1,254 +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 <string.h>
-
-#include "doomtype.h"
-
-#include "z_zone.h"
-
-#include "deh_defs.h"
-#include "deh_io.h"
-#include "deh_main.h"
-
-typedef struct 
-{
-    char *from_text;
-    char *to_text;
-} deh_substitution_t;
-
-static deh_substitution_t **hash_table;
-static int hash_table_entries;
-static int hash_table_length = -1;
-
-// This is the algorithm used by glib
-
-static unsigned int strhash(char *s)
-{
-    char *p = s;
-    unsigned int h = *p;
-  
-    if (h)
-    {
-        for (p += 1; *p; p++)
-            h = (h << 5) - h + *p;
-    }
-
-    return h;
-}
-
-// Look up a string to see if it has been replaced with something else
-// This will be used throughout the program to substitute text
-
-char *DEH_String(char *s)
-{
-    int entry;
-
-    // Fallback if we have not initialised the hash table yet
-
-    if (hash_table_length < 0)
-	return s;
-
-    entry = strhash(s) % hash_table_length;
-
-    while (hash_table[entry] != NULL)
-    {
-        if (!strcmp(hash_table[entry]->from_text, s))
-        {
-            // substitution found!
-
-            return hash_table[entry]->to_text;
-        }
-
-        entry = (entry + 1) % hash_table_length;
-    }
-
-    // no substitution found
-
-    return s;
-}
-
-static void DEH_AddToHashtable(deh_substitution_t *sub);
-
-static void IncreaseHashtable(void)
-{
-    deh_substitution_t **old_table;
-    int old_table_length;
-    int i;
-    
-    // save the old table
-
-    old_table = hash_table;
-    old_table_length = hash_table_length;
-    
-    // double the size 
-
-    hash_table_length *= 2;
-    hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
-                          PU_STATIC, NULL);
-    memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
-
-    // go through the old table and insert all the old entries
-
-    for (i=0; i<old_table_length; ++i)
-    {
-        if (old_table[i] != NULL)
-        {
-            DEH_AddToHashtable(old_table[i]);
-        }
-    }
-
-    // free the old table
-
-    Z_Free(old_table);
-}
-
-static void DEH_AddToHashtable(deh_substitution_t *sub)
-{
-    int entry;
-
-    // if the hash table is more than 60% full, increase its size
-
-    if ((hash_table_entries * 10) / hash_table_length > 6)
-    {
-        IncreaseHashtable();
-    }
-    
-    // find where to insert it
-    
-    entry = strhash(sub->from_text) % hash_table_length;
-
-    while (hash_table[entry] != NULL)
-    {
-        entry = (entry + 1) % hash_table_length;
-    }
-
-    hash_table[entry] = sub;
-    ++hash_table_entries;
-}
-
-// 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_TextInit(void)
-{
-    // init hash table
-    
-    hash_table_entries = 0;
-    hash_table_length = 16;
-    hash_table = Z_Malloc(sizeof(deh_substitution_t *) * hash_table_length,
-                          PU_STATIC, NULL);
-    memset(hash_table, 0, sizeof(deh_substitution_t *) * hash_table_length);
-}
-
-static void *DEH_TextStart(deh_context_t *context, char *line)
-{
-    deh_substitution_t *sub;
-    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;
-    }
-
-    sub = Z_Malloc(sizeof(deh_substitution_t), PU_STATIC, NULL);
-    sub->from_text = Z_Malloc(fromlen + 1, PU_STATIC, NULL);
-    sub->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);
-            
-        sub->from_text[i] = c;
-    }
-
-    sub->from_text[fromlen] = '\0';
-
-    // read in the "to" text
-
-    for (i=0; i<tolen; ++i)
-    {
-        int c;
-
-        c = DEH_GetChar(context);
-            
-        sub->to_text[i] = c;
-    }
-    sub->to_text[tolen] = '\0';
-
-    DEH_AddToHashtable(sub);
-    
-    return NULL;
-}
-
-static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag)
-{
-    // not used
-}
-
-deh_section_t deh_section_text =
-{
-    "Text",
-    DEH_TextInit,
-    DEH_TextStart,
-    DEH_TextParseLine,
-    NULL,
-    NULL,
-};
-
--- a/src/deh_thing.c
+++ /dev/null
@@ -1,140 +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 "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,
-};
-
--- a/src/deh_weapon.c
+++ /dev/null
@@ -1,109 +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 "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,
-};
-
--- a/src/doom/Makefile.am
+++ b/src/doom/Makefile.am
@@ -60,5 +60,21 @@
 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)
 
--- /dev/null
+++ b/src/doom/deh_ammo.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_cheat.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/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 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 */
+
+
--- /dev/null
+++ b/src/doom/deh_frame.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_io.c
@@ -1,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");
+}
+
+
--- /dev/null
+++ b/src/doom/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/doom/deh_main.c
@@ -1,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;
+        }
+    }
+}
+
+
--- /dev/null
+++ b/src/doom/deh_main.h
@@ -1,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 */
+
--- /dev/null
+++ b/src/doom/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/doom/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/doom/deh_misc.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_misc.h
@@ -1,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 */
+
--- /dev/null
+++ b/src/doom/deh_ptr.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_sound.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_text.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_thing.c
@@ -1,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,
+};
+
--- /dev/null
+++ b/src/doom/deh_weapon.c
@@ -1,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,
+};
+
--- a/src/i_pcsound.c
+++ b/src/i_pcsound.c
@@ -27,7 +27,7 @@
 
 #include "doomtype.h"
 
-#include "deh_main.h"
+#include "deh_str.h"
 #include "s_sound.h"
 #include "sounds.h"
 
--- a/src/i_sdlmusic.c
+++ b/src/i_sdlmusic.c
@@ -34,7 +34,7 @@
 #include "memio.h"
 #include "mus2mid.h"
 
-#include "deh_main.h"
+#include "deh_str.h"
 #include "m_misc.h"
 #include "s_sound.h"
 #include "w_wad.h"
--- a/src/i_sdlsound.c
+++ b/src/i_sdlsound.c
@@ -38,7 +38,7 @@
 #include <samplerate.h>
 #endif
 
-#include "deh_main.h"
+#include "deh_str.h"
 #include "i_system.h"
 #include "s_sound.h"
 #include "m_argv.h"
--- a/src/i_system.c
+++ b/src/i_system.c
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #endif
 
-#include "deh_main.h"
+#include "deh_str.h"
 #include "doomtype.h"
 #include "doomstat.h"
 #include "m_argv.h"
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -33,7 +33,7 @@
 #include "icon.c"
 
 #include "config.h"
-#include "deh_main.h"
+#include "deh_str.h"
 #include "doomtype.h"
 #include "doomkeys.h"
 #include "i_joystick.h"
--- a/src/m_config.c
+++ b/src/m_config.c
@@ -32,7 +32,7 @@
 #include <errno.h>
 
 #include "config.h"
-#include "deh_main.h"
+#include "deh_str.h"
 #include "doomtype.h"
 #include "doomkeys.h"
 #include "doomfeatures.h"
--- a/src/m_misc.c
+++ b/src/m_misc.c
@@ -45,7 +45,7 @@
 #include "doomtype.h"
 #include "doomstat.h"
 
-#include "deh_main.h"
+#include "deh_str.h"
 
 #include "i_swap.h"
 #include "i_system.h"
--- a/src/net_client.c
+++ b/src/net_client.c
@@ -29,6 +29,7 @@
 #include "doomtype.h"
 #include "doomstat.h"
 #include "deh_main.h"
+#include "deh_str.h"
 #include "g_game.h"
 #include "i_system.h"
 #include "i_timer.h"
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -29,7 +29,7 @@
 #include "i_system.h"
 
 #include "doomfeatures.h"
-#include "deh_main.h"
+#include "deh_str.h"
 
 #include "doomstat.h"
 #include "doomtype.h"
--- a/src/v_video.c
+++ b/src/v_video.c
@@ -34,7 +34,7 @@
 #include "doomtype.h"
 #include "doomdata.h"
 
-#include "deh_main.h"
+#include "deh_str.h"
 #include "m_bbox.h"
 #include "i_swap.h"
 #include "i_video.h"