shithub: choc

ref: 56412813c70ba44a6f6a74cee5bf460ca6a31402
dir: /src/heretic/deh_htext.c/

View raw version
// Emacs style mode select   -*- C++ -*- 
//-----------------------------------------------------------------------------
//
// Copyright(C) 2005-2010 Simon Howard
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
// 02111-1307, USA.
//
//-----------------------------------------------------------------------------
//
// Parses Text substitution sections in dehacked files
//
//-----------------------------------------------------------------------------

#include <stdio.h>
#include <string.h>

#include "doomtype.h"
#include "dstrings.h"

#include "z_zone.h"

#include "deh_defs.h"
#include "deh_io.h"
#include "deh_main.h"

//
// Ok, Greg, the action pointers thing was bad enough, but this really
// takes the biscuit.  Why does HHE's text replacement address strings
// by offset??!!  The dehacked way was much nicer, why change it?
//
// Anyway, this is the Heretic 1.0 string table, which can be seen in
// HHE.  This is the string and its offset from the start of the
// text section.  Not all the strings are here; this is a redacted list
// that contains just the strings we support.
//

static const struct
{
    unsigned int offset;
    char *string;
}
string_table[] =
{
    {      0, NULL },
    {      4, NULL },
    {     64, NULL },
    {    104, NULL },
    {    160, NULL },
    {    200, NULL },
    {    220, NULL },
    {    228, "PLAYPAL" },
    {    236, NULL },
    {    244, NULL },
    {    252, NULL },
    {    272, NULL },
    {    288, NULL },
    {    296, NULL },
    {    316, NULL },
    {    332, NULL },
    {    372, NULL },
    {    436, NULL },
    {    504, NULL },
    {    536, NULL },
    {    544, NULL },
    {    560, NULL },
    {    576, NULL },
    {    584, "ENDTEXT" },
    {    592, NULL },
    {    612, NULL },
    {    640, NULL },
    {    664, NULL },
    {    712, NULL },
    {    744, NULL },
    {    764, NULL },
    {    808, NULL },
    {    820, NULL },
    {    828, NULL },
    {    840, NULL },
    {    876, NULL },
    {    884, NULL },
    {    908, NULL },
    {    952, NULL },
    {    992, NULL },
    {   1028, NULL },
    {   1036, NULL },
    {   1048, NULL },
    {   1088, NULL },
    {   1128, NULL },
    {   1160, NULL },
    {   1192, NULL },
    {   1212, NULL },
    {   1240, "E1M1:  THE DOCKS" },
    {   1260, "E1M2:  THE DUNGEONS" },
    {   1280, "E1M3:  THE GATEHOUSE" },
    {   1304, "E1M4:  THE GUARD TOWER" },
    {   1328, "E1M5:  THE CITADEL" },
    {   1348, "E1M6:  THE CATHEDRAL" },
    {   1372, "E1M7:  THE CRYPTS" },
    {   1392, "E1M8:  HELL'S MAW" },
    {   1412, "E1M9:  THE GRAVEYARD" },
    {   1436, "E2M1:  THE CRATER" },
    {   1456, "E2M2:  THE LAVA PITS" },
    {   1480, "E2M3:  THE RIVER OF FIRE" },
    {   1508, "E2M4:  THE ICE GROTTO" },
    {   1532, "E2M5:  THE CATACOMBS" },
    {   1556, "E2M6:  THE LABYRINTH" },
    {   1580, "E2M7:  THE GREAT HALL" },
    {   1604, "E2M8:  THE PORTALS OF CHAOS" },
    {   1632, "E2M9:  THE GLACIER" },
    {   1652, "E3M1:  THE STOREHOUSE" },
    {   1676, "E3M2:  THE CESSPOOL" },
    {   1696, "E3M3:  THE CONFLUENCE" },
    {   1720, "E3M4:  THE AZURE FORTRESS" },
    {   1748, "E3M5:  THE OPHIDIAN LAIR" },
    {   1776, "E3M6:  THE HALLS OF FEAR" },
    {   1804, "E3M7:  THE CHASM" },
    {   1824, "E3M8:  D'SPARIL'S KEEP" },
    {   1848, "E3M9:  THE AQUIFER" },
    {   1868, "AUTOPAGE" },
    {   1880, "FOLLOW MODE ON" },
    {   1896, "FOLLOW MODE OFF" },
    {   1912, "GREEN:  " },
    {   1936, "YELLOW:  " },
    {   1948, "RED:  " },
    {   1956, "BLUE:  " },
    {   1964, "FONTA_S" },
    {   1972, "-MESSAGE SENT-" },
    {   1988, "THERE ARE NO OTHER PLAYERS IN THE GAME!" },
    {   2028, "FONTA59" },
    {   2036, "PAUSED" },
    {   2044, NULL },
    {   2056, NULL },
    {   2072, "ADVISOR" },
    {   2080, "TITLE" },
    {   2088, "demo1" },
    {   2096, "CREDIT" },
    {   2104, "demo2" },
    {   2112, "ORDER" },
    {   2120, "demo3" },
    {   2128, NULL },
    {   2140, NULL },
    {   2168, "hticsav%c.hsg" },
    {   2184, "heretic.wad" },
    {   2196, NULL },
    {   2212, NULL },
    {   2228, NULL },
    {   2240, "heretic.cfg" },
    {   2252, NULL },
    {   2264, NULL },
    {   2284, NULL },
    {   2304, "Exited from HERETIC.\n" },
    {   2328, NULL },
    {   2340, NULL },
    {   2352, NULL },
    {   2364, NULL },
    {   2372, NULL },
    {   2388, NULL },
    {   2404, NULL },
    {   2412, "c:\\heretic.cd" },
    {   2428, NULL },
    {   2436, NULL },
    {   2444, NULL },
    {   2464, NULL },
    {   2496, NULL },
    {   2508, NULL },
    {   2520, NULL },
    {   2528, "Playing demo %s.lmp.\n" },
    {   2552, NULL },
    {   2564, NULL },
    {   2572, NULL },
    {   2584, NULL },
    {   2592, "V_Init: allocate screens.\n" },
    {   2620, "M_LoadDefaults: Load system defaults.\n" },
    {   2660, "Z_Init: Init zone memory allocation daemon.\n" },
    {   2708, "W_Init: Init WADfiles.\n" },
    {   2732, "E2M1" },
    {   2740, "LOADING" },
    {   2748, "DeathMatch..." },
    {   2764, "No Monsters..." },
    {   2780, "Respawning..." },
    {   2796, "Warp to Episode %d, Map %d, Skill %d " },
    {   2836, "MN_Init: Init menu system.\n" },
    {   2864, "R_Init: Init Heretic refresh daemon." },
    {   2904, "Loading graphics" },
    {   2924, "P_Init: Init Playloop state." },
    {   2956, "Init game engine." },
    {   2976, "I_Init: Setting up machine state.\n" },
    {   3012, "D_CheckNetGame: Checking network game status.\n" },
    {   3060, "Checking network game status." },
    {   3092, "SB_Init: Loading patches.\n" },
    {   3120, NULL },
    {   3128, NULL },
    {   3140, NULL },
    {   3184, NULL },
    {   3220, NULL },
    {   3256, NULL },
    {   3280, NULL },
    {   3304, NULL },
    {   3320, NULL },
    {   3352, "PLAYER 1 HAS LEFT THE GAME" },
    {   3380, NULL },
    {   3432, NULL },
    {   3464, NULL },
    {   3508, NULL },
    {   3548, NULL },
    {   3600, NULL },
    {   3624, NULL },
    {   3664, NULL },
    {   3696, NULL },
    {   3736, "NET GAME" },
    {   3748, "SAVE GAME" },
    {   3760, "Only %i deathmatch spots, 4 required" },
    {   3800, "version %i" },
    {   3812, NULL },
    {   3828, NULL },
    {   3856, NULL },
    {   3872, NULL },
    {   3896, "GAME SAVED" },
    {   3908, "SKY1" },
    {   3916, "SKY2" },
    {   3924, "SKY3" },
    {   3932, NULL },
    {   3940, NULL },
    {   3976, NULL },
    {   3996, NULL },
    {   4016, E1TEXT },
    {   4536, E2TEXT },
    {   5068, E3TEXT },
    {   5632, "FLOOR25" },
    {   5640, "FLATHUH1" },
    {   5652, "FLTWAWA2" },
    {   5664, "FONTA_S" },
    {   5672, "FINAL1" },
    {   5680, "FINAL2" },
    {   5688, "E2PAL" },
    {   5696, "E2END" },
    {   5704, "PLAYPAL" },
    {   5712, "ORDER" },
    {   5720, "IMPX" },
    {   5728, "ACLO" },
    {   5736, "PTN1" },
    {   5744, "SHLD" },
    {   5752, "SHD2" },
    {   5760, "BAGH" },
    {   5768, "SPMP" },
    {   5776, "INVS" },
    {   5784, "PTN2" },
    {   5792, "SOAR" },
    {   5800, "INVU" },
    {   5808, "PWBK" },
    {   5816, "EGGC" },
    {   5824, "EGGM" },
    {   5832, "FX01" },
    {   5840, "SPHL" },
    {   5848, "TRCH" },
    {   5856, "FBMB" },
    {   5864, "XPL1" },
    {   5872, "ATLP" },
    {   5880, "PPOD" },
    {   5888, "AMG1" },
    {   5896, "SPSH" },
    {   5904, "LVAS" },
    {   5912, "SLDG" },
    {   5920, "SKH1" },
    {   5928, "SKH2" },
    {   5936, "SKH3" },
    {   5944, "SKH4" },
    {   5952, "CHDL" },
    {   5960, "SRTC" },
    {   5968, "SMPL" },
    {   5976, "STGS" },
    {   5984, "STGL" },
    {   5992, "STCS" },
    {   6000, "STCL" },
    {   6008, "KFR1" },
    {   6016, "BARL" },
    {   6024, "BRPL" },
    {   6032, "MOS1" },
    {   6040, "MOS2" },
    {   6048, "WTRH" },
    {   6056, "HCOR" },
    {   6064, "KGZ1" },
    {   6072, "KGZB" },
    {   6080, "KGZG" },
    {   6088, "KGZY" },
    {   6096, "VLCO" },
    {   6104, "VFBL" },
    {   6112, "VTFB" },
    {   6120, "SFFI" },
    {   6128, "TGLT" },
    {   6136, "TELE" },
    {   6144, "STFF" },
    {   6152, "PUF3" },
    {   6160, "PUF4" },
    {   6168, "BEAK" },
    {   6176, "WGNT" },
    {   6184, "GAUN" },
    {   6192, "PUF1" },
    {   6200, "WBLS" },
    {   6208, "BLSR" },
    {   6216, "FX18" },
    {   6224, "FX17" },
    {   6232, "WMCE" },
    {   6240, "MACE" },
    {   6248, "FX02" },
    {   6256, "WSKL" },
    {   6264, "HROD" },
    {   6272, "FX00" },
    {   6280, "FX20" },
    {   6288, "FX21" },
    {   6296, "FX22" },
    {   6304, "FX23" },
    {   6312, "GWND" },
    {   6320, "PUF2" },
    {   6328, "WPHX" },
    {   6336, "PHNX" },
    {   6344, "FX04" },
    {   6352, "FX08" },
    {   6360, "FX09" },
    {   6368, "WBOW" },
    {   6376, "CRBW" },
    {   6384, "FX03" },
    {   6392, "BLOD" },
    {   6400, "PLAY" },
    {   6408, "FDTH" },
    {   6416, "BSKL" },
    {   6424, "CHKN" },
    {   6432, "MUMM" },
    {   6440, "FX15" },
    {   6448, "BEAS" },
    {   6456, "FRB1" },
    {   6464, "SNKE" },
    {   6472, "SNFX" },
    {   6480, "HEAD" },
    {   6488, "FX05" },
    {   6496, "FX06" },
    {   6504, "FX07" },
    {   6512, "CLNK" },
    {   6520, "WZRD" },
    {   6528, "FX11" },
    {   6536, "FX10" },
    {   6544, "KNIG" },
    {   6552, "SPAX" },
    {   6560, "RAXE" },
    {   6568, "SRCR" },
    {   6576, "FX14" },
    {   6584, "SOR2" },
    {   6592, "SDTH" },
    {   6600, "FX16" },
    {   6608, "MNTR" },
    {   6616, "FX12" },
    {   6624, "FX13" },
    {   6632, "AKYY" },
    {   6640, "BKYY" },
    {   6648, "CKYY" },
    {   6656, "AMG2" },
    {   6664, "AMM1" },
    {   6672, "AMM2" },
    {   6680, "AMC1" },
    {   6688, "AMC2" },
    {   6696, "AMS1" },
    {   6704, "AMS2" },
    {   6712, "AMP1" },
    {   6720, "AMP2" },
    {   6728, "AMB1" },
    {   6736, "AMB2" },
    {   6768, "PLAYPAL" },
    {   6776, "MAPE1" },
    {   6784, "MAPE2" },
    {   6792, "MAPE3" },
    {   6800, "IN_X" },
    {   6808, "IN_YAH" },
    {   6816, "FONTB16" },
    {   6824, "FONTB_S" },
    {   6832, "FONTB13" },
    {   6840, "FONTB15" },
    {   6848, "FONTB05" },
    {   6856, "FACEA0" },
    {   6864, "FACEB0" },
    {   6872, NULL },
    {   6896, NULL },
    {   6940, "FLOOR16" },
    {   6948, "FINISHED" },
    {   6960, "NOW ENTERING:" },
    {   6976, "KILLS" },
    {   6984, "ITEMS" },
    {   6992, "SECRETS" },
    {   7000, "TIME" },
    {   7008, "BONUS" },
    {   7016, "SECRET" },
    {   7024, "TOTAL" },
    {   7032, "VICTIMS" },
    {   7044, "NEW GAME" },
    {   7056, "OPTIONS" },
    {   7064, "GAME FILES" },
    {   7076, "INFO" },
    {   7084, "QUIT GAME" },
    {   7096, "CITY OF THE DAMNED" },
    {   7116, "HELL'S MAW" },
    {   7128, "THE DOME OF D'SPARIL" },
    {   7152, "LOAD GAME" },
    {   7164, "SAVE GAME" },
    {   7176, "THOU NEEDETH A WET-NURSE" },
    {   7204, "YELLOWBELLIES-R-US" },
    {   7224, "BRINGEST THEM ONETH" },
    {   7244, "THOU ART A SMITE-MEISTER" },
    {   7272, "BLACK PLAGUE POSSESSES THEE" },
    {   7300, "END GAME" },
    {   7312, "MESSAGES : " },
    {   7324, "MOUSE SENSITIVITY" },
    {   7344, "MORE..." },
    {   7352, "SCREEN SIZE" },
    {   7364, "SFX VOLUME" },
    {   7376, "MUSIC VOLUME" },
    {   7392, "M_SKL00" },
    {   7400, "FONTA_S" },
    {   7408, "FONTB_S" },
    {   7416, "ARE YOU SURE YOU WANT TO QUIT?" },
    {   7448, "ARE YOU SURE YOU WANT TO END THE GAME?" },
    {   7488, "DO YOU WANT TO QUICKSAVE THE GAME NAMED" },
    {   7528, "DO YOU WANT TO QUICKLOAD THE GAME NAMED" },
    {   7572, "M_SLCTR1" },
    {   7584, "M_SLCTR2" },
    {   7596, "M_HTIC" },
    {   7604, NULL },
    {   7632, "hticsav%d.hsg" },
    {   7652, "M_FSLOT" },
    {   7668, "MESSAGES ON" },
    {   7680, "MESSAGES OFF" },
    {   7696, "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!" },
    {   7748, "ONLY AVAILABLE IN THE REGISTERED VERSION" },
    {   7792, "PLAYPAL" },
    {   7800, "QUICKSAVING...." },
    {   7816, "QUICKLOADING...." },
    {   7836, "CHOOSE A QUICKSAVE SLOT" },
    {   7860, "CHOOSE A QUICKLOAD SLOT" },
    {   7884, "TITLE" },
    {   7892, "M_SLDLT" },
    {   7900, "M_SLDMD1" },
    {   7912, "M_SLDMD2" },
    {   7924, "M_SLDRT" },
    {   7932, "M_SLDKB" },
    {   7940, NULL },
    {   7968, NULL },
    {   7992, NULL },
    {   8020, NULL },
    {   8028, NULL },
    {   8056, NULL },
    {   8076, NULL },
    {   8088, NULL },
    {   8104, NULL },
    {   8116, NULL },
    {   8128, NULL },
    {   8136, NULL },
    {   8148, NULL },
    {   8164, NULL },
    {   8180, NULL },
    {   8192, NULL },
    {   8204, NULL },
    {   8220, NULL },
    {   8232, NULL },
    {   8248, NULL },
    {   8264, NULL },
    {   8276, NULL },
    {   8292, NULL },
    {   8308, NULL },
    {   8320, NULL },
    {   8328, NULL },
    {   8340, NULL },
    {   8352, NULL },
    {   8364, NULL },
    {   8376, NULL },
    {   8392, NULL },
    {   8408, NULL },
    {   8424, NULL },
    {   8436, NULL },
    {   8448, NULL },
    {   8460, NULL },
    {   8472, NULL },
    {   8488, NULL },
    {   8504, NULL },
    {   8520, NULL },
    {   8536, NULL },
    {   8548, NULL },
    {   8560, NULL },
    {   8572, NULL },
    {   8584, NULL },
    {   8596, NULL },
    {   8612, NULL },
    {   8624, NULL },
    {   8648, NULL },
    {   8660, NULL },
    {   8668, NULL },
    {   8680, NULL },
    {   8708, NULL },
    {   8720, NULL },
    {   8728, NULL },
    {   8740, NULL },
    {   8752, NULL },
    {   8764, NULL },
    {   8788, NULL },
    {   8800, NULL },
    {   8812, NULL },
    {   8824, NULL },
    {   8848, NULL },
    {   8880, NULL },
    {   8888, NULL },
    {   8896, NULL },
    {   8916, NULL },
    {   8968, "HRTIC00.pcx" },
    {   8980, NULL },
    {   9016, "SCREEN SHOT" },
    {   9028, "YOU NEED A BLUE KEY TO OPEN THIS DOOR" },
    {   9068, "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" },
    {   9108, "YOU NEED A GREEN KEY TO OPEN THIS DOOR" },
    {   9148, NULL },
    {   9172, NULL },
    {   9220, NULL },
    {   9244, "CRYSTAL VIAL" },
    {   9260, "SILVER SHIELD" },
    {   9276, "ENCHANTED SHIELD" },
    {   9296, "BAG OF HOLDING" },
    {   9312, "MAP SCROLL" },
    {   9324, "BLUE KEY" },
    {   9336, "YELLOW KEY" },
    {   9348, "GREEN KEY" },
    {   9360, "QUARTZ FLASK" },
    {   9376, "WINGS OF WRATH" },
    {   9392, "RING OF INVINCIBILITY" },
    {   9416, "TOME OF POWER" },
    {   9432, "SHADOWSPHERE" },
    {   9448, "MORPH OVUM" },
    {   9460, "MYSTIC URN" },
    {   9472, "TORCH" },
    {   9480, "TIME BOMB OF THE ANCIENTS" },
    {   9508, "CHAOS DEVICE" },
    {   9524, "WAND CRYSTAL" },
    {   9540, "CRYSTAL GEODE" },
    {   9556, "MACE SPHERES" },
    {   9572, "PILE OF MACE SPHERES" },
    {   9596, "ETHEREAL ARROWS" },
    {   9612, "QUIVER OF ETHEREAL ARROWS" },
    {   9640, "CLAW ORB" },
    {   9652, "ENERGY ORB" },
    {   9664, "LESSER RUNES" },
    {   9680, "GREATER RUNES" },
    {   9696, "FLAME ORB" },
    {   9708, "INFERNO ORB" },
    {   9720, "FIREMACE" },
    {   9732, "ETHEREAL CROSSBOW" },
    {   9752, "DRAGON CLAW" },
    {   9764, "HELLSTAFF" },
    {   9776, "PHOENIX ROD" },
    {   9788, "GAUNTLETS OF THE NECROMANCER" },
    {   9820, NULL },
    {   9860, NULL },
    {   9892, NULL },
    {   9940, NULL },
    {   9972, NULL },
    {  10012, NULL },
    {  10052, NULL },
    {  10080, NULL },
    {  10088, "FLTWAWA1" },
    {  10100, "FLTFLWW1" },
    {  10112, "FLTLAVA1" },
    {  10124, "FLATHUH1" },
    {  10136, "FLTSLUD1" },
    {  10152, NULL },
    {  10192, NULL },
    {  10236, NULL },
    {  10248, NULL },
    {  10284, NULL },
    {  10320, NULL },
    {  10360, NULL },
    {  10392, NULL },
    {  10444, "PLAYPAL" },
    {  10452, NULL },
    {  10488, NULL },
    {  10508, NULL },
    {  10556, NULL },
    {  10596, "PNAMES" },
    {  10604, "TEXTURE1" },
    {  10616, "TEXTURE2" },
    {  10628, "S_END" },
    {  10636, "S_START" },
    {  10644, NULL },
    {  10684, NULL },
    {  10728, "F_START" },
    {  10736, "F_END" },
    {  10744, "COLORMAP" },
    {  10756, "\nR_InitTextures " },
    {  10776, "R_InitFlats\n" },
    {  10792, "R_InitSpriteLumps " },
    {  10812, NULL },
    {  10844, NULL },
    {  10880, NULL },
    {  10912, NULL },
    {  10948, "TINTTAB" },
    {  10956, NULL },
    {  10984, "FLOOR04" },
    {  10992, "FLAT513" },
    {  11000, "bordt" },
    {  11008, "bordb" },
    {  11016, "bordl" },
    {  11024, "bordr" },
    {  11032, "bordtl" },
    {  11040, "bordtr" },
    {  11048, "bordbr" },
    {  11056, "bordbl" },
    {  11064, "R_InitData " },
    {  11076, "R_InitPointToAngle\n" },
    {  11096, "R_InitTables " },
    {  11112, "R_InitPlanes\n" },
    {  11128, "R_InitLightTables " },
    {  11148, "R_InitSkyMap\n" },
    {  11164, "F_SKY1" },
    {  11172, NULL },
    {  11200, NULL },
    {  11232, NULL },
    {  11272, NULL },
    {  11312, NULL },
    {  11348, NULL },
    {  11380, NULL },
    {  11404, NULL },
    {  11436, NULL },
    {  11492, NULL },
    {  11548, NULL },
    {  11616, NULL },
    {  11684, NULL },
    {  11748, NULL },
    {  11792, NULL },
    {  11840, NULL },
    {  11896, NULL },
    {  11936, NULL },
    {  11980, NULL },
    {  12028, NULL },
    {  12072, NULL },
    {  12120, "LTFACE" },
    {  12128, "RTFACE" },
    {  12136, "BARBACK" },
    {  12144, "INVBAR" },
    {  12152, "CHAIN" },
    {  12160, "STATBAR" },
    {  12168, "LIFEBAR" },
    {  12176, "LIFEGEM2" },
    {  12188, "LIFEGEM0" },
    {  12200, "LTFCTOP" },
    {  12208, "RTFCTOP" },
    {  12216, "ARTIBOX" },
    {  12224, "SELECTBOX" },
    {  12236, "INVGEML1" },
    {  12248, "INVGEML2" },
    {  12260, "INVGEMR1" },
    {  12272, "INVGEMR2" },
    {  12284, "BLACKSQ" },
    {  12292, "ARMCLEAR" },
    {  12304, "CHAINBACK" },
    {  12320, "NEGNUM" },
    {  12328, "FONTB16" },
    {  12336, "SMALLIN0" },
    {  12348, "PLAYPAL" },
    {  12356, "SPINBK0" },
    {  12364, "SPFLY0" },
    {  12372, "LAME" },
    {  12408, "NAME" },
    {  12416, "MO.T" },
    {  12424, "MO.X" },
    {  12432, "MO.Y" },
    {  12448, "DIST" },
    {  12456, "------" },
    {  12472, "GOD1" },
    {  12480, "GOD2" },
    {  12488, "useartia" },
    {  12500, "ykeyicon" },
    {  12512, "gkeyicon" },
    {  12524, "bkeyicon" },
    {  12536, "GOD MODE ON" },
    {  12548, "GOD MODE OFF" },
    {  12564, "NO CLIPPING ON" },
    {  12580, "NO CLIPPING OFF" },
    {  12596, "ALL WEAPONS" },
    {  12608, "POWER OFF" },
    {  12620, "POWER ON" },
    {  12632, "FULL HEALTH" },
    {  12644, "ALL KEYS" },
    {  12656, "SOUND DEBUG ON" },
    {  12672, "SOUND DEBUG OFF" },
    {  12688, "TICKER ON" },
    {  12700, "TICKER OFF" },
    {  12712, "CHOOSE AN ARTIFACT ( A - J )" },
    {  12744, "HOW MANY ( 1 - 9 )" },
    {  12764, "YOU GOT IT" },
    {  12776, "BAD INPUT" },
    {  12788, "LEVEL WARP" },
    {  12800, "CHICKEN OFF" },
    {  12812, "CHICKEN ON" },
    {  12824, "MASSACRE" },
    {  12836, "CHEATER - YOU DON'T DESERVE WEAPONS" },
    {  12872, "TRYING TO CHEAT, EH?  NOW YOU DIE!" },
    {  12908, "Bad V_DrawPatch" },
    {  12924, NULL },
    {  12960, NULL },
    {  12968, NULL },
    {  12976, NULL },
    {  13020, NULL },
    {  13048, NULL },
    {  13076, NULL },
    {  13104, NULL },
    {  13136, NULL },
    {  13168, NULL },
    {  13196, NULL },
    {  13240, NULL },
    {  13272, NULL },
    {  13296, NULL },
    {  13312, NULL },
    {  13324, NULL },
    {  13364, NULL },
    {  13408, NULL },
    {  13460, NULL },
    {  13492, NULL },
    {  13516, NULL },
    {  13560, NULL },
    {  13612, NULL },
    {  13664, NULL },
    {  13700, NULL },
    {  13744, NULL },
    {  13796, NULL },
    {  13848, NULL },
    {  13884, NULL },
    {  13940, NULL },
    {  13996, NULL },
    {  14040, NULL },
    {  14084, NULL },
    {  14140, NULL },
    {  14148, NULL },
    {  14164, NULL },
    {  14184, NULL },
    {  14192, NULL },
    {  14212, NULL },
    {  14256, NULL },
    {  14272, NULL },
    {  14284, NULL },
    {  14300, NULL },
    {  14312, NULL },
    {  14324, NULL },
    {  14348, NULL },
    {  14360, NULL },
    {  14372, NULL },
    {  14380, NULL },
    {  14392, NULL },
    {  14432, NULL },
    {  14444, NULL },
    {  14472, NULL },
    {  14496, NULL },
    {  14516, NULL },
    {  14536, NULL },
    {  14548, NULL },
    {  14560, NULL },
    {  14572, NULL },
    {  14580, NULL },
    {  14588, NULL },
    {  14596, NULL },
    {  14604, NULL },
    {  14612, NULL },
    {  14620, NULL },
    {  14636, NULL },
    {  14660, NULL },
    {  14704, NULL },
    {  14748, NULL },
    {  14760, NULL },
    {  14768, NULL },
};

static boolean GetStringByOffset(unsigned int offset, char **result)
{
    int i;

    for (i=0; i<arrlen(string_table); ++i)
    {
        if (string_table[i].offset == offset)
        {
            *result = string_table[i].string;
            return true;
        }
    }

    return false;
}

// Given a string length, find the maximum length of a 
// string that can replace it.

static int 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 *repl_text;
    char *orig_text;
    int orig_offset, repl_len;
    int i;

    if (sscanf(line, "Text %i %i", &orig_offset, &repl_len) != 2)
    {
        DEH_Warning(context, "Parse error on section start");
        return NULL;
    }

    repl_text = Z_Malloc(repl_len + 1, PU_STATIC, NULL);

    // read in the "to" text

    for (i=0; i<repl_len; ++i)
    {
        int c;

        c = DEH_GetChar(context);

        repl_text[i] = c;
    }
    repl_text[repl_len] = '\0';

    // Find the string to replace:

    if (!GetStringByOffset(orig_offset, &orig_text))
    {
        DEH_Error(context, "Unknown string offset: %i", orig_offset);
    }

    // We don't support all strings, but at least recognise them:

    else if (orig_text == NULL)
    {
        DEH_Warning(context, "Unsupported string replacement: %i", orig_offset);
    }

    // Only allow string replacements that are possible in Vanilla Doom.  
    // Chocolate Doom is unforgiving!

    else if (!deh_allow_long_strings
          && repl_len > MaxStringLength(strlen(orig_text)))
    {
        DEH_Error(context, "Replacement string is longer than the maximum "
                           "possible in heretic.exe");
    }
    else
    {
        // Success.

        DEH_AddStringReplacement(orig_text, repl_text);

        return NULL;
    }

    // Failure.

    Z_Free(repl_text);

    return NULL;
}

static void DEH_TextParseLine(deh_context_t *context, char *line, void *tag)
{
    // not used
}

deh_section_t deh_section_heretic_text =
{
    "Text",
    NULL,
    DEH_TextStart,
    DEH_TextParseLine,
    NULL,
    NULL,
};