aboutsummaryrefslogtreecommitdiff
path: root/src/d_deh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/d_deh.c')
-rw-r--r--src/d_deh.c3090
1 files changed, 3090 insertions, 0 deletions
diff --git a/src/d_deh.c b/src/d_deh.c
new file mode 100644
index 0000000..b3790f5
--- /dev/null
+++ b/src/d_deh.c
@@ -0,0 +1,3090 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2004 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Dehacked file support
31 * New for the TeamTNT "Boom" engine
32 *
33 * Author: Ty Halderman, TeamTNT
34 *
35 *--------------------------------------------------------------------*/
36
37// killough 5/2/98: fixed headers, removed rendunant external declarations:
38#include "doomdef.h"
39#include "doomtype.h"
40#include "doomstat.h"
41#include "d_deh.h"
42#include "sounds.h"
43#include "info.h"
44#include "m_cheat.h"
45#include "p_inter.h"
46#include "p_enemy.h"
47#include "g_game.h"
48#include "d_think.h"
49#include "w_wad.h"
50
51// CPhipps - modify to use logical output routine
52#include "lprintf.h"
53
54#define TRUE 1
55#define FALSE 0
56
57#ifndef HAVE_STRLWR
58#include <ctype.h>
59
60static char* strlwr(char* str)
61{
62 char* p;
63 for (p=str; *p; p++) *p = tolower(*p);
64 return str;
65}
66#endif
67
68// killough 10/98: new functions, to allow processing DEH files in-memory
69// (e.g. from wads)
70
71typedef struct {
72 /* cph 2006/08/06 -
73 * if lump != NULL, lump is the start of the lump,
74 * inp is the current read pos. */
75 const byte *inp, *lump;
76 long size;
77 /* else, !lump, and f is the file being read */
78 FILE* f;
79} DEHFILE;
80
81// killough 10/98: emulate IO whether input really comes from a file or not
82
83static char *dehfgets(char *buf, size_t n, DEHFILE *fp)
84{
85 if (!fp->lump) // If this is a real file,
86 return (fgets)(buf, n, fp->f); // return regular fgets
87 if (!n || !*fp->inp || fp->size<=0) // If no more characters
88 return NULL;
89 if (n==1)
90 fp->size--, *buf = *fp->inp++;
91 else
92 { // copy buffer
93 char *p = buf;
94 while (n>1 && *fp->inp && fp->size &&
95 (n--, fp->size--, *p++ = *fp->inp++) != '\n')
96 ;
97 *p = 0;
98 }
99 return buf; // Return buffer pointer
100}
101
102static int dehfeof(DEHFILE *fp)
103{
104 return !fp->lump ? feof(fp->f) : !*fp->inp || fp->size<=0;
105}
106
107static int dehfgetc(DEHFILE *fp)
108{
109 return !fp->lump ? fgetc(fp->f) : fp->size > 0 ?
110 fp->size--, *fp->inp++ : EOF;
111}
112
113// haleyjd 9/22/99
114int HelperThing = -1; // in P_SpawnMapThing to substitute helper thing
115
116// variables used in other routines
117boolean deh_pars = FALSE; // in wi_stuff to allow pars in modified games
118
119// #include "d_deh.h" -- we don't do that here but we declare the
120// variables. This externalizes everything that there is a string
121// set for in the language files. See d_deh.h for detailed comments,
122// original English values etc. These are set to the macro values,
123// which are set by D_ENGLSH.H or D_FRENCH.H(etc). BEX files are a
124// better way of changing these strings globally by language.
125
126// ====================================================================
127// Any of these can be changed using the bex extensions
128#include "dstrings.h" // to get the initial values
129/* cph - const's
130 * - removed redundant "can't XXX in a netgame" strings.
131 */
132const char *s_D_DEVSTR = D_DEVSTR;
133const char *s_D_CDROM = D_CDROM;
134const char *s_PRESSKEY = PRESSKEY;
135const char *s_PRESSYN = PRESSYN;
136const char *s_QUITMSG = QUITMSG;
137const char *s_QSAVESPOT = QSAVESPOT; // PRESSKEY;
138const char *s_SAVEDEAD = SAVEDEAD; // PRESSKEY; // remove duplicate y/n
139const char *s_QSPROMPT = QSPROMPT; // PRESSYN;
140const char *s_QLPROMPT = QLPROMPT; // PRESSYN;
141const char *s_NEWGAME = NEWGAME; // PRESSKEY;
142const char *s_RESTARTLEVEL= RESTARTLEVEL; // PRESSYN;
143const char *s_NIGHTMARE = NIGHTMARE; // PRESSYN;
144const char *s_SWSTRING = SWSTRING; // PRESSKEY;
145const char *s_MSGOFF = MSGOFF;
146const char *s_MSGON = MSGON;
147const char *s_NETEND = NETEND; // PRESSKEY;
148const char *s_ENDGAME = ENDGAME; // PRESSYN; // killough 4/4/98: end
149const char *s_DOSY = DOSY;
150const char *s_DETAILHI = DETAILHI;
151const char *s_DETAILLO = DETAILLO;
152const char *s_GAMMALVL0 = GAMMALVL0;
153const char *s_GAMMALVL1 = GAMMALVL1;
154const char *s_GAMMALVL2 = GAMMALVL2;
155const char *s_GAMMALVL3 = GAMMALVL3;
156const char *s_GAMMALVL4 = GAMMALVL4;
157const char *s_EMPTYSTRING = EMPTYSTRING;
158const char *s_GOTARMOR = GOTARMOR;
159const char *s_GOTMEGA = GOTMEGA;
160const char *s_GOTHTHBONUS = GOTHTHBONUS;
161const char *s_GOTARMBONUS = GOTARMBONUS;
162const char *s_GOTSTIM = GOTSTIM;
163const char *s_GOTMEDINEED = GOTMEDINEED;
164const char *s_GOTMEDIKIT = GOTMEDIKIT;
165const char *s_GOTSUPER = GOTSUPER;
166const char *s_GOTBLUECARD = GOTBLUECARD;
167const char *s_GOTYELWCARD = GOTYELWCARD;
168const char *s_GOTREDCARD = GOTREDCARD;
169const char *s_GOTBLUESKUL = GOTBLUESKUL;
170const char *s_GOTYELWSKUL = GOTYELWSKUL;
171const char *s_GOTREDSKULL = GOTREDSKULL;
172const char *s_GOTINVUL = GOTINVUL;
173const char *s_GOTBERSERK = GOTBERSERK;
174const char *s_GOTINVIS = GOTINVIS;
175const char *s_GOTSUIT = GOTSUIT;
176const char *s_GOTMAP = GOTMAP;
177const char *s_GOTVISOR = GOTVISOR;
178const char *s_GOTMSPHERE = GOTMSPHERE;
179const char *s_GOTCLIP = GOTCLIP;
180const char *s_GOTCLIPBOX = GOTCLIPBOX;
181const char *s_GOTROCKET = GOTROCKET;
182const char *s_GOTROCKBOX = GOTROCKBOX;
183const char *s_GOTCELL = GOTCELL;
184const char *s_GOTCELLBOX = GOTCELLBOX;
185const char *s_GOTSHELLS = GOTSHELLS;
186const char *s_GOTSHELLBOX = GOTSHELLBOX;
187const char *s_GOTBACKPACK = GOTBACKPACK;
188const char *s_GOTBFG9000 = GOTBFG9000;
189const char *s_GOTCHAINGUN = GOTCHAINGUN;
190const char *s_GOTCHAINSAW = GOTCHAINSAW;
191const char *s_GOTLAUNCHER = GOTLAUNCHER;
192const char *s_GOTPLASMA = GOTPLASMA;
193const char *s_GOTSHOTGUN = GOTSHOTGUN;
194const char *s_GOTSHOTGUN2 = GOTSHOTGUN2;
195const char *s_PD_BLUEO = PD_BLUEO;
196const char *s_PD_REDO = PD_REDO;
197const char *s_PD_YELLOWO = PD_YELLOWO;
198const char *s_PD_BLUEK = PD_BLUEK;
199const char *s_PD_REDK = PD_REDK;
200const char *s_PD_YELLOWK = PD_YELLOWK;
201const char *s_PD_BLUEC = PD_BLUEC;
202const char *s_PD_REDC = PD_REDC;
203const char *s_PD_YELLOWC = PD_YELLOWC;
204const char *s_PD_BLUES = PD_BLUES;
205const char *s_PD_REDS = PD_REDS;
206const char *s_PD_YELLOWS = PD_YELLOWS;
207const char *s_PD_ANY = PD_ANY;
208const char *s_PD_ALL3 = PD_ALL3;
209const char *s_PD_ALL6 = PD_ALL6;
210const char *s_GGSAVED = GGSAVED;
211const char *s_HUSTR_MSGU = HUSTR_MSGU;
212const char *s_HUSTR_E1M1 = HUSTR_E1M1;
213const char *s_HUSTR_E1M2 = HUSTR_E1M2;
214const char *s_HUSTR_E1M3 = HUSTR_E1M3;
215const char *s_HUSTR_E1M4 = HUSTR_E1M4;
216const char *s_HUSTR_E1M5 = HUSTR_E1M5;
217const char *s_HUSTR_E1M6 = HUSTR_E1M6;
218const char *s_HUSTR_E1M7 = HUSTR_E1M7;
219const char *s_HUSTR_E1M8 = HUSTR_E1M8;
220const char *s_HUSTR_E1M9 = HUSTR_E1M9;
221const char *s_HUSTR_E2M1 = HUSTR_E2M1;
222const char *s_HUSTR_E2M2 = HUSTR_E2M2;
223const char *s_HUSTR_E2M3 = HUSTR_E2M3;
224const char *s_HUSTR_E2M4 = HUSTR_E2M4;
225const char *s_HUSTR_E2M5 = HUSTR_E2M5;
226const char *s_HUSTR_E2M6 = HUSTR_E2M6;
227const char *s_HUSTR_E2M7 = HUSTR_E2M7;
228const char *s_HUSTR_E2M8 = HUSTR_E2M8;
229const char *s_HUSTR_E2M9 = HUSTR_E2M9;
230const char *s_HUSTR_E3M1 = HUSTR_E3M1;
231const char *s_HUSTR_E3M2 = HUSTR_E3M2;
232const char *s_HUSTR_E3M3 = HUSTR_E3M3;
233const char *s_HUSTR_E3M4 = HUSTR_E3M4;
234const char *s_HUSTR_E3M5 = HUSTR_E3M5;
235const char *s_HUSTR_E3M6 = HUSTR_E3M6;
236const char *s_HUSTR_E3M7 = HUSTR_E3M7;
237const char *s_HUSTR_E3M8 = HUSTR_E3M8;
238const char *s_HUSTR_E3M9 = HUSTR_E3M9;
239const char *s_HUSTR_E4M1 = HUSTR_E4M1;
240const char *s_HUSTR_E4M2 = HUSTR_E4M2;
241const char *s_HUSTR_E4M3 = HUSTR_E4M3;
242const char *s_HUSTR_E4M4 = HUSTR_E4M4;
243const char *s_HUSTR_E4M5 = HUSTR_E4M5;
244const char *s_HUSTR_E4M6 = HUSTR_E4M6;
245const char *s_HUSTR_E4M7 = HUSTR_E4M7;
246const char *s_HUSTR_E4M8 = HUSTR_E4M8;
247const char *s_HUSTR_E4M9 = HUSTR_E4M9;
248const char *s_HUSTR_1 = HUSTR_1;
249const char *s_HUSTR_2 = HUSTR_2;
250const char *s_HUSTR_3 = HUSTR_3;
251const char *s_HUSTR_4 = HUSTR_4;
252const char *s_HUSTR_5 = HUSTR_5;
253const char *s_HUSTR_6 = HUSTR_6;
254const char *s_HUSTR_7 = HUSTR_7;
255const char *s_HUSTR_8 = HUSTR_8;
256const char *s_HUSTR_9 = HUSTR_9;
257const char *s_HUSTR_10 = HUSTR_10;
258const char *s_HUSTR_11 = HUSTR_11;
259const char *s_HUSTR_12 = HUSTR_12;
260const char *s_HUSTR_13 = HUSTR_13;
261const char *s_HUSTR_14 = HUSTR_14;
262const char *s_HUSTR_15 = HUSTR_15;
263const char *s_HUSTR_16 = HUSTR_16;
264const char *s_HUSTR_17 = HUSTR_17;
265const char *s_HUSTR_18 = HUSTR_18;
266const char *s_HUSTR_19 = HUSTR_19;
267const char *s_HUSTR_20 = HUSTR_20;
268const char *s_HUSTR_21 = HUSTR_21;
269const char *s_HUSTR_22 = HUSTR_22;
270const char *s_HUSTR_23 = HUSTR_23;
271const char *s_HUSTR_24 = HUSTR_24;
272const char *s_HUSTR_25 = HUSTR_25;
273const char *s_HUSTR_26 = HUSTR_26;
274const char *s_HUSTR_27 = HUSTR_27;
275const char *s_HUSTR_28 = HUSTR_28;
276const char *s_HUSTR_29 = HUSTR_29;
277const char *s_HUSTR_30 = HUSTR_30;
278const char *s_HUSTR_31 = HUSTR_31;
279const char *s_HUSTR_32 = HUSTR_32;
280const char *s_PHUSTR_1 = PHUSTR_1;
281const char *s_PHUSTR_2 = PHUSTR_2;
282const char *s_PHUSTR_3 = PHUSTR_3;
283const char *s_PHUSTR_4 = PHUSTR_4;
284const char *s_PHUSTR_5 = PHUSTR_5;
285const char *s_PHUSTR_6 = PHUSTR_6;
286const char *s_PHUSTR_7 = PHUSTR_7;
287const char *s_PHUSTR_8 = PHUSTR_8;
288const char *s_PHUSTR_9 = PHUSTR_9;
289const char *s_PHUSTR_10 = PHUSTR_10;
290const char *s_PHUSTR_11 = PHUSTR_11;
291const char *s_PHUSTR_12 = PHUSTR_12;
292const char *s_PHUSTR_13 = PHUSTR_13;
293const char *s_PHUSTR_14 = PHUSTR_14;
294const char *s_PHUSTR_15 = PHUSTR_15;
295const char *s_PHUSTR_16 = PHUSTR_16;
296const char *s_PHUSTR_17 = PHUSTR_17;
297const char *s_PHUSTR_18 = PHUSTR_18;
298const char *s_PHUSTR_19 = PHUSTR_19;
299const char *s_PHUSTR_20 = PHUSTR_20;
300const char *s_PHUSTR_21 = PHUSTR_21;
301const char *s_PHUSTR_22 = PHUSTR_22;
302const char *s_PHUSTR_23 = PHUSTR_23;
303const char *s_PHUSTR_24 = PHUSTR_24;
304const char *s_PHUSTR_25 = PHUSTR_25;
305const char *s_PHUSTR_26 = PHUSTR_26;
306const char *s_PHUSTR_27 = PHUSTR_27;
307const char *s_PHUSTR_28 = PHUSTR_28;
308const char *s_PHUSTR_29 = PHUSTR_29;
309const char *s_PHUSTR_30 = PHUSTR_30;
310const char *s_PHUSTR_31 = PHUSTR_31;
311const char *s_PHUSTR_32 = PHUSTR_32;
312const char *s_THUSTR_1 = THUSTR_1;
313const char *s_THUSTR_2 = THUSTR_2;
314const char *s_THUSTR_3 = THUSTR_3;
315const char *s_THUSTR_4 = THUSTR_4;
316const char *s_THUSTR_5 = THUSTR_5;
317const char *s_THUSTR_6 = THUSTR_6;
318const char *s_THUSTR_7 = THUSTR_7;
319const char *s_THUSTR_8 = THUSTR_8;
320const char *s_THUSTR_9 = THUSTR_9;
321const char *s_THUSTR_10 = THUSTR_10;
322const char *s_THUSTR_11 = THUSTR_11;
323const char *s_THUSTR_12 = THUSTR_12;
324const char *s_THUSTR_13 = THUSTR_13;
325const char *s_THUSTR_14 = THUSTR_14;
326const char *s_THUSTR_15 = THUSTR_15;
327const char *s_THUSTR_16 = THUSTR_16;
328const char *s_THUSTR_17 = THUSTR_17;
329const char *s_THUSTR_18 = THUSTR_18;
330const char *s_THUSTR_19 = THUSTR_19;
331const char *s_THUSTR_20 = THUSTR_20;
332const char *s_THUSTR_21 = THUSTR_21;
333const char *s_THUSTR_22 = THUSTR_22;
334const char *s_THUSTR_23 = THUSTR_23;
335const char *s_THUSTR_24 = THUSTR_24;
336const char *s_THUSTR_25 = THUSTR_25;
337const char *s_THUSTR_26 = THUSTR_26;
338const char *s_THUSTR_27 = THUSTR_27;
339const char *s_THUSTR_28 = THUSTR_28;
340const char *s_THUSTR_29 = THUSTR_29;
341const char *s_THUSTR_30 = THUSTR_30;
342const char *s_THUSTR_31 = THUSTR_31;
343const char *s_THUSTR_32 = THUSTR_32;
344const char *s_HUSTR_CHATMACRO1 = HUSTR_CHATMACRO1;
345const char *s_HUSTR_CHATMACRO2 = HUSTR_CHATMACRO2;
346const char *s_HUSTR_CHATMACRO3 = HUSTR_CHATMACRO3;
347const char *s_HUSTR_CHATMACRO4 = HUSTR_CHATMACRO4;
348const char *s_HUSTR_CHATMACRO5 = HUSTR_CHATMACRO5;
349const char *s_HUSTR_CHATMACRO6 = HUSTR_CHATMACRO6;
350const char *s_HUSTR_CHATMACRO7 = HUSTR_CHATMACRO7;
351const char *s_HUSTR_CHATMACRO8 = HUSTR_CHATMACRO8;
352const char *s_HUSTR_CHATMACRO9 = HUSTR_CHATMACRO9;
353const char *s_HUSTR_CHATMACRO0 = HUSTR_CHATMACRO0;
354const char *s_HUSTR_TALKTOSELF1 = HUSTR_TALKTOSELF1;
355const char *s_HUSTR_TALKTOSELF2 = HUSTR_TALKTOSELF2;
356const char *s_HUSTR_TALKTOSELF3 = HUSTR_TALKTOSELF3;
357const char *s_HUSTR_TALKTOSELF4 = HUSTR_TALKTOSELF4;
358const char *s_HUSTR_TALKTOSELF5 = HUSTR_TALKTOSELF5;
359const char *s_HUSTR_MESSAGESENT = HUSTR_MESSAGESENT;
360const char *s_HUSTR_PLRGREEN = HUSTR_PLRGREEN;
361const char *s_HUSTR_PLRINDIGO = HUSTR_PLRINDIGO;
362const char *s_HUSTR_PLRBROWN = HUSTR_PLRBROWN;
363const char *s_HUSTR_PLRRED = HUSTR_PLRRED;
364const char *s_AMSTR_FOLLOWON = AMSTR_FOLLOWON;
365const char *s_AMSTR_FOLLOWOFF = AMSTR_FOLLOWOFF;
366const char *s_AMSTR_GRIDON = AMSTR_GRIDON;
367const char *s_AMSTR_GRIDOFF = AMSTR_GRIDOFF;
368const char *s_AMSTR_MARKEDSPOT = AMSTR_MARKEDSPOT;
369const char *s_AMSTR_MARKSCLEARED = AMSTR_MARKSCLEARED;
370// CPhipps - automap rotate & overlay
371const char* s_AMSTR_ROTATEON = AMSTR_ROTATEON;
372const char* s_AMSTR_ROTATEOFF = AMSTR_ROTATEOFF;
373const char* s_AMSTR_OVERLAYON = AMSTR_OVERLAYON;
374const char* s_AMSTR_OVERLAYOFF = AMSTR_OVERLAYOFF;
375const char *s_STSTR_MUS = STSTR_MUS;
376const char *s_STSTR_NOMUS = STSTR_NOMUS;
377const char *s_STSTR_DQDON = STSTR_DQDON;
378const char *s_STSTR_DQDOFF = STSTR_DQDOFF;
379const char *s_STSTR_KFAADDED = STSTR_KFAADDED;
380const char *s_STSTR_FAADDED = STSTR_FAADDED;
381const char *s_STSTR_NCON = STSTR_NCON;
382const char *s_STSTR_NCOFF = STSTR_NCOFF;
383const char *s_STSTR_BEHOLD = STSTR_BEHOLD;
384const char *s_STSTR_BEHOLDX = STSTR_BEHOLDX;
385const char *s_STSTR_CHOPPERS = STSTR_CHOPPERS;
386const char *s_STSTR_CLEV = STSTR_CLEV;
387const char *s_STSTR_COMPON = STSTR_COMPON;
388const char *s_STSTR_COMPOFF = STSTR_COMPOFF;
389const char *s_E1TEXT = E1TEXT;
390const char *s_E2TEXT = E2TEXT;
391const char *s_E3TEXT = E3TEXT;
392const char *s_E4TEXT = E4TEXT;
393const char *s_C1TEXT = C1TEXT;
394const char *s_C2TEXT = C2TEXT;
395const char *s_C3TEXT = C3TEXT;
396const char *s_C4TEXT = C4TEXT;
397const char *s_C5TEXT = C5TEXT;
398const char *s_C6TEXT = C6TEXT;
399const char *s_P1TEXT = P1TEXT;
400const char *s_P2TEXT = P2TEXT;
401const char *s_P3TEXT = P3TEXT;
402const char *s_P4TEXT = P4TEXT;
403const char *s_P5TEXT = P5TEXT;
404const char *s_P6TEXT = P6TEXT;
405const char *s_T1TEXT = T1TEXT;
406const char *s_T2TEXT = T2TEXT;
407const char *s_T3TEXT = T3TEXT;
408const char *s_T4TEXT = T4TEXT;
409const char *s_T5TEXT = T5TEXT;
410const char *s_T6TEXT = T6TEXT;
411const char *s_CC_ZOMBIE = CC_ZOMBIE;
412const char *s_CC_SHOTGUN = CC_SHOTGUN;
413const char *s_CC_HEAVY = CC_HEAVY;
414const char *s_CC_IMP = CC_IMP;
415const char *s_CC_DEMON = CC_DEMON;
416const char *s_CC_LOST = CC_LOST;
417const char *s_CC_CACO = CC_CACO;
418const char *s_CC_HELL = CC_HELL;
419const char *s_CC_BARON = CC_BARON;
420const char *s_CC_ARACH = CC_ARACH;
421const char *s_CC_PAIN = CC_PAIN;
422const char *s_CC_REVEN = CC_REVEN;
423const char *s_CC_MANCU = CC_MANCU;
424const char *s_CC_ARCH = CC_ARCH;
425const char *s_CC_SPIDER = CC_SPIDER;
426const char *s_CC_CYBER = CC_CYBER;
427const char *s_CC_HERO = CC_HERO;
428// Ty 03/30/98 - new substitutions for background textures
429// during int screens
430const char *bgflatE1 = "FLOOR4_8"; // end of DOOM Episode 1
431const char *bgflatE2 = "SFLR6_1"; // end of DOOM Episode 2
432const char *bgflatE3 = "MFLR8_4"; // end of DOOM Episode 3
433const char *bgflatE4 = "MFLR8_3"; // end of DOOM Episode 4
434const char *bgflat06 = "SLIME16"; // DOOM2 after MAP06
435const char *bgflat11 = "RROCK14"; // DOOM2 after MAP11
436const char *bgflat20 = "RROCK07"; // DOOM2 after MAP20
437const char *bgflat30 = "RROCK17"; // DOOM2 after MAP30
438const char *bgflat15 = "RROCK13"; // DOOM2 going MAP15 to MAP31
439const char *bgflat31 = "RROCK19"; // DOOM2 going MAP31 to MAP32
440const char *bgcastcall = "BOSSBACK"; // Panel behind cast call
441
442const char *startup1 = ""; // blank lines are default and are not printed
443const char *startup2 = "";
444const char *startup3 = "";
445const char *startup4 = "";
446const char *startup5 = "";
447
448/* Ty 05/03/98 - externalized
449 * cph - updated for prboom */
450const char *savegamename = "prbmsav";
451
452// end d_deh.h variable declarations
453// ====================================================================
454
455// Do this for a lookup--the pointer (loaded above) is cross-referenced
456// to a string key that is the same as the define above. We will use
457// strdups to set these new values that we read from the file, orphaning
458// the original value set above.
459
460// CPhipps - make strings pointed to const
461typedef struct {
462 const char **ppstr; // doubly indirect pointer to string
463 const char *lookup; // pointer to lookup string name
464} deh_strs;
465
466/* CPhipps - const, static
467 * - removed redundant "Can't XXX in a netgame" strings
468 */
469static const deh_strs deh_strlookup[] = {
470 {&s_D_DEVSTR,"D_DEVSTR"},
471 {&s_D_CDROM,"D_CDROM"},
472 {&s_PRESSKEY,"PRESSKEY"},
473 {&s_PRESSYN,"PRESSYN"},
474 {&s_QUITMSG,"QUITMSG"},
475 {&s_QSAVESPOT,"QSAVESPOT"},
476 {&s_SAVEDEAD,"SAVEDEAD"},
477 /* cph - disabled to prevent format string attacks in WAD files
478 {&s_QSPROMPT,"QSPROMPT"},
479 {&s_QLPROMPT,"QLPROMPT"},*/
480 {&s_NEWGAME,"NEWGAME"},
481 {&s_RESTARTLEVEL,"RESTARTLEVEL"},
482 {&s_NIGHTMARE,"NIGHTMARE"},
483 {&s_SWSTRING,"SWSTRING"},
484 {&s_MSGOFF,"MSGOFF"},
485 {&s_MSGON,"MSGON"},
486 {&s_NETEND,"NETEND"},
487 {&s_ENDGAME,"ENDGAME"},
488 {&s_DOSY,"DOSY"},
489 {&s_DETAILHI,"DETAILHI"},
490 {&s_DETAILLO,"DETAILLO"},
491 {&s_GAMMALVL0,"GAMMALVL0"},
492 {&s_GAMMALVL1,"GAMMALVL1"},
493 {&s_GAMMALVL2,"GAMMALVL2"},
494 {&s_GAMMALVL3,"GAMMALVL3"},
495 {&s_GAMMALVL4,"GAMMALVL4"},
496 {&s_EMPTYSTRING,"EMPTYSTRING"},
497 {&s_GOTARMOR,"GOTARMOR"},
498 {&s_GOTMEGA,"GOTMEGA"},
499 {&s_GOTHTHBONUS,"GOTHTHBONUS"},
500 {&s_GOTARMBONUS,"GOTARMBONUS"},
501 {&s_GOTSTIM,"GOTSTIM"},
502 {&s_GOTMEDINEED,"GOTMEDINEED"},
503 {&s_GOTMEDIKIT,"GOTMEDIKIT"},
504 {&s_GOTSUPER,"GOTSUPER"},
505 {&s_GOTBLUECARD,"GOTBLUECARD"},
506 {&s_GOTYELWCARD,"GOTYELWCARD"},
507 {&s_GOTREDCARD,"GOTREDCARD"},
508 {&s_GOTBLUESKUL,"GOTBLUESKUL"},
509 {&s_GOTYELWSKUL,"GOTYELWSKUL"},
510 {&s_GOTREDSKULL,"GOTREDSKULL"},
511 {&s_GOTINVUL,"GOTINVUL"},
512 {&s_GOTBERSERK,"GOTBERSERK"},
513 {&s_GOTINVIS,"GOTINVIS"},
514 {&s_GOTSUIT,"GOTSUIT"},
515 {&s_GOTMAP,"GOTMAP"},
516 {&s_GOTVISOR,"GOTVISOR"},
517 {&s_GOTMSPHERE,"GOTMSPHERE"},
518 {&s_GOTCLIP,"GOTCLIP"},
519 {&s_GOTCLIPBOX,"GOTCLIPBOX"},
520 {&s_GOTROCKET,"GOTROCKET"},
521 {&s_GOTROCKBOX,"GOTROCKBOX"},
522 {&s_GOTCELL,"GOTCELL"},
523 {&s_GOTCELLBOX,"GOTCELLBOX"},
524 {&s_GOTSHELLS,"GOTSHELLS"},
525 {&s_GOTSHELLBOX,"GOTSHELLBOX"},
526 {&s_GOTBACKPACK,"GOTBACKPACK"},
527 {&s_GOTBFG9000,"GOTBFG9000"},
528 {&s_GOTCHAINGUN,"GOTCHAINGUN"},
529 {&s_GOTCHAINSAW,"GOTCHAINSAW"},
530 {&s_GOTLAUNCHER,"GOTLAUNCHER"},
531 {&s_GOTPLASMA,"GOTPLASMA"},
532 {&s_GOTSHOTGUN,"GOTSHOTGUN"},
533 {&s_GOTSHOTGUN2,"GOTSHOTGUN2"},
534 {&s_PD_BLUEO,"PD_BLUEO"},
535 {&s_PD_REDO,"PD_REDO"},
536 {&s_PD_YELLOWO,"PD_YELLOWO"},
537 {&s_PD_BLUEK,"PD_BLUEK"},
538 {&s_PD_REDK,"PD_REDK"},
539 {&s_PD_YELLOWK,"PD_YELLOWK"},
540 {&s_PD_BLUEC,"PD_BLUEC"},
541 {&s_PD_REDC,"PD_REDC"},
542 {&s_PD_YELLOWC,"PD_YELLOWC"},
543 {&s_PD_BLUES,"PD_BLUES"},
544 {&s_PD_REDS,"PD_REDS"},
545 {&s_PD_YELLOWS,"PD_YELLOWS"},
546 {&s_PD_ANY,"PD_ANY"},
547 {&s_PD_ALL3,"PD_ALL3"},
548 {&s_PD_ALL6,"PD_ALL6"},
549 {&s_GGSAVED,"GGSAVED"},
550 {&s_HUSTR_MSGU,"HUSTR_MSGU"},
551 {&s_HUSTR_E1M1,"HUSTR_E1M1"},
552 {&s_HUSTR_E1M2,"HUSTR_E1M2"},
553 {&s_HUSTR_E1M3,"HUSTR_E1M3"},
554 {&s_HUSTR_E1M4,"HUSTR_E1M4"},
555 {&s_HUSTR_E1M5,"HUSTR_E1M5"},
556 {&s_HUSTR_E1M6,"HUSTR_E1M6"},
557 {&s_HUSTR_E1M7,"HUSTR_E1M7"},
558 {&s_HUSTR_E1M8,"HUSTR_E1M8"},
559 {&s_HUSTR_E1M9,"HUSTR_E1M9"},
560 {&s_HUSTR_E2M1,"HUSTR_E2M1"},
561 {&s_HUSTR_E2M2,"HUSTR_E2M2"},
562 {&s_HUSTR_E2M3,"HUSTR_E2M3"},
563 {&s_HUSTR_E2M4,"HUSTR_E2M4"},
564 {&s_HUSTR_E2M5,"HUSTR_E2M5"},
565 {&s_HUSTR_E2M6,"HUSTR_E2M6"},
566 {&s_HUSTR_E2M7,"HUSTR_E2M7"},
567 {&s_HUSTR_E2M8,"HUSTR_E2M8"},
568 {&s_HUSTR_E2M9,"HUSTR_E2M9"},
569 {&s_HUSTR_E3M1,"HUSTR_E3M1"},
570 {&s_HUSTR_E3M2,"HUSTR_E3M2"},
571 {&s_HUSTR_E3M3,"HUSTR_E3M3"},
572 {&s_HUSTR_E3M4,"HUSTR_E3M4"},
573 {&s_HUSTR_E3M5,"HUSTR_E3M5"},
574 {&s_HUSTR_E3M6,"HUSTR_E3M6"},
575 {&s_HUSTR_E3M7,"HUSTR_E3M7"},
576 {&s_HUSTR_E3M8,"HUSTR_E3M8"},
577 {&s_HUSTR_E3M9,"HUSTR_E3M9"},
578 {&s_HUSTR_E4M1,"HUSTR_E4M1"},
579 {&s_HUSTR_E4M2,"HUSTR_E4M2"},
580 {&s_HUSTR_E4M3,"HUSTR_E4M3"},
581 {&s_HUSTR_E4M4,"HUSTR_E4M4"},
582 {&s_HUSTR_E4M5,"HUSTR_E4M5"},
583 {&s_HUSTR_E4M6,"HUSTR_E4M6"},
584 {&s_HUSTR_E4M7,"HUSTR_E4M7"},
585 {&s_HUSTR_E4M8,"HUSTR_E4M8"},
586 {&s_HUSTR_E4M9,"HUSTR_E4M9"},
587 {&s_HUSTR_1,"HUSTR_1"},
588 {&s_HUSTR_2,"HUSTR_2"},
589 {&s_HUSTR_3,"HUSTR_3"},
590 {&s_HUSTR_4,"HUSTR_4"},
591 {&s_HUSTR_5,"HUSTR_5"},
592 {&s_HUSTR_6,"HUSTR_6"},
593 {&s_HUSTR_7,"HUSTR_7"},
594 {&s_HUSTR_8,"HUSTR_8"},
595 {&s_HUSTR_9,"HUSTR_9"},
596 {&s_HUSTR_10,"HUSTR_10"},
597 {&s_HUSTR_11,"HUSTR_11"},
598 {&s_HUSTR_12,"HUSTR_12"},
599 {&s_HUSTR_13,"HUSTR_13"},
600 {&s_HUSTR_14,"HUSTR_14"},
601 {&s_HUSTR_15,"HUSTR_15"},
602 {&s_HUSTR_16,"HUSTR_16"},
603 {&s_HUSTR_17,"HUSTR_17"},
604 {&s_HUSTR_18,"HUSTR_18"},
605 {&s_HUSTR_19,"HUSTR_19"},
606 {&s_HUSTR_20,"HUSTR_20"},
607 {&s_HUSTR_21,"HUSTR_21"},
608 {&s_HUSTR_22,"HUSTR_22"},
609 {&s_HUSTR_23,"HUSTR_23"},
610 {&s_HUSTR_24,"HUSTR_24"},
611 {&s_HUSTR_25,"HUSTR_25"},
612 {&s_HUSTR_26,"HUSTR_26"},
613 {&s_HUSTR_27,"HUSTR_27"},
614 {&s_HUSTR_28,"HUSTR_28"},
615 {&s_HUSTR_29,"HUSTR_29"},
616 {&s_HUSTR_30,"HUSTR_30"},
617 {&s_HUSTR_31,"HUSTR_31"},
618 {&s_HUSTR_32,"HUSTR_32"},
619 {&s_PHUSTR_1,"PHUSTR_1"},
620 {&s_PHUSTR_2,"PHUSTR_2"},
621 {&s_PHUSTR_3,"PHUSTR_3"},
622 {&s_PHUSTR_4,"PHUSTR_4"},
623 {&s_PHUSTR_5,"PHUSTR_5"},
624 {&s_PHUSTR_6,"PHUSTR_6"},
625 {&s_PHUSTR_7,"PHUSTR_7"},
626 {&s_PHUSTR_8,"PHUSTR_8"},
627 {&s_PHUSTR_9,"PHUSTR_9"},
628 {&s_PHUSTR_10,"PHUSTR_10"},
629 {&s_PHUSTR_11,"PHUSTR_11"},
630 {&s_PHUSTR_12,"PHUSTR_12"},
631 {&s_PHUSTR_13,"PHUSTR_13"},
632 {&s_PHUSTR_14,"PHUSTR_14"},
633 {&s_PHUSTR_15,"PHUSTR_15"},
634 {&s_PHUSTR_16,"PHUSTR_16"},
635 {&s_PHUSTR_17,"PHUSTR_17"},
636 {&s_PHUSTR_18,"PHUSTR_18"},
637 {&s_PHUSTR_19,"PHUSTR_19"},
638 {&s_PHUSTR_20,"PHUSTR_20"},
639 {&s_PHUSTR_21,"PHUSTR_21"},
640 {&s_PHUSTR_22,"PHUSTR_22"},
641 {&s_PHUSTR_23,"PHUSTR_23"},
642 {&s_PHUSTR_24,"PHUSTR_24"},
643 {&s_PHUSTR_25,"PHUSTR_25"},
644 {&s_PHUSTR_26,"PHUSTR_26"},
645 {&s_PHUSTR_27,"PHUSTR_27"},
646 {&s_PHUSTR_28,"PHUSTR_28"},
647 {&s_PHUSTR_29,"PHUSTR_29"},
648 {&s_PHUSTR_30,"PHUSTR_30"},
649 {&s_PHUSTR_31,"PHUSTR_31"},
650 {&s_PHUSTR_32,"PHUSTR_32"},
651 {&s_THUSTR_1,"THUSTR_1"},
652 {&s_THUSTR_2,"THUSTR_2"},
653 {&s_THUSTR_3,"THUSTR_3"},
654 {&s_THUSTR_4,"THUSTR_4"},
655 {&s_THUSTR_5,"THUSTR_5"},
656 {&s_THUSTR_6,"THUSTR_6"},
657 {&s_THUSTR_7,"THUSTR_7"},
658 {&s_THUSTR_8,"THUSTR_8"},
659 {&s_THUSTR_9,"THUSTR_9"},
660 {&s_THUSTR_10,"THUSTR_10"},
661 {&s_THUSTR_11,"THUSTR_11"},
662 {&s_THUSTR_12,"THUSTR_12"},
663 {&s_THUSTR_13,"THUSTR_13"},
664 {&s_THUSTR_14,"THUSTR_14"},
665 {&s_THUSTR_15,"THUSTR_15"},
666 {&s_THUSTR_16,"THUSTR_16"},
667 {&s_THUSTR_17,"THUSTR_17"},
668 {&s_THUSTR_18,"THUSTR_18"},
669 {&s_THUSTR_19,"THUSTR_19"},
670 {&s_THUSTR_20,"THUSTR_20"},
671 {&s_THUSTR_21,"THUSTR_21"},
672 {&s_THUSTR_22,"THUSTR_22"},
673 {&s_THUSTR_23,"THUSTR_23"},
674 {&s_THUSTR_24,"THUSTR_24"},
675 {&s_THUSTR_25,"THUSTR_25"},
676 {&s_THUSTR_26,"THUSTR_26"},
677 {&s_THUSTR_27,"THUSTR_27"},
678 {&s_THUSTR_28,"THUSTR_28"},
679 {&s_THUSTR_29,"THUSTR_29"},
680 {&s_THUSTR_30,"THUSTR_30"},
681 {&s_THUSTR_31,"THUSTR_31"},
682 {&s_THUSTR_32,"THUSTR_32"},
683 {&s_HUSTR_CHATMACRO1,"HUSTR_CHATMACRO1"},
684 {&s_HUSTR_CHATMACRO2,"HUSTR_CHATMACRO2"},
685 {&s_HUSTR_CHATMACRO3,"HUSTR_CHATMACRO3"},
686 {&s_HUSTR_CHATMACRO4,"HUSTR_CHATMACRO4"},
687 {&s_HUSTR_CHATMACRO5,"HUSTR_CHATMACRO5"},
688 {&s_HUSTR_CHATMACRO6,"HUSTR_CHATMACRO6"},
689 {&s_HUSTR_CHATMACRO7,"HUSTR_CHATMACRO7"},
690 {&s_HUSTR_CHATMACRO8,"HUSTR_CHATMACRO8"},
691 {&s_HUSTR_CHATMACRO9,"HUSTR_CHATMACRO9"},
692 {&s_HUSTR_CHATMACRO0,"HUSTR_CHATMACRO0"},
693 {&s_HUSTR_TALKTOSELF1,"HUSTR_TALKTOSELF1"},
694 {&s_HUSTR_TALKTOSELF2,"HUSTR_TALKTOSELF2"},
695 {&s_HUSTR_TALKTOSELF3,"HUSTR_TALKTOSELF3"},
696 {&s_HUSTR_TALKTOSELF4,"HUSTR_TALKTOSELF4"},
697 {&s_HUSTR_TALKTOSELF5,"HUSTR_TALKTOSELF5"},
698 {&s_HUSTR_MESSAGESENT,"HUSTR_MESSAGESENT"},
699 {&s_HUSTR_PLRGREEN,"HUSTR_PLRGREEN"},
700 {&s_HUSTR_PLRINDIGO,"HUSTR_PLRINDIGO"},
701 {&s_HUSTR_PLRBROWN,"HUSTR_PLRBROWN"},
702 {&s_HUSTR_PLRRED,"HUSTR_PLRRED"},
703 //{c_HUSTR_KEYGREEN,"HUSTR_KEYGREEN"},
704 //{c_HUSTR_KEYINDIGO,"HUSTR_KEYINDIGO"},
705 //{c_HUSTR_KEYBROWN,"HUSTR_KEYBROWN"},
706 //{c_HUSTR_KEYRED,"HUSTR_KEYRED"},
707 {&s_AMSTR_FOLLOWON,"AMSTR_FOLLOWON"},
708 {&s_AMSTR_FOLLOWOFF,"AMSTR_FOLLOWOFF"},
709 {&s_AMSTR_GRIDON,"AMSTR_GRIDON"},
710 {&s_AMSTR_GRIDOFF,"AMSTR_GRIDOFF"},
711 {&s_AMSTR_MARKEDSPOT,"AMSTR_MARKEDSPOT"},
712 {&s_AMSTR_MARKSCLEARED,"AMSTR_MARKSCLEARED"},
713 {&s_STSTR_MUS,"STSTR_MUS"},
714 {&s_STSTR_NOMUS,"STSTR_NOMUS"},
715 {&s_STSTR_DQDON,"STSTR_DQDON"},
716 {&s_STSTR_DQDOFF,"STSTR_DQDOFF"},
717 {&s_STSTR_KFAADDED,"STSTR_KFAADDED"},
718 {&s_STSTR_FAADDED,"STSTR_FAADDED"},
719 {&s_STSTR_NCON,"STSTR_NCON"},
720 {&s_STSTR_NCOFF,"STSTR_NCOFF"},
721 {&s_STSTR_BEHOLD,"STSTR_BEHOLD"},
722 {&s_STSTR_BEHOLDX,"STSTR_BEHOLDX"},
723 {&s_STSTR_CHOPPERS,"STSTR_CHOPPERS"},
724 {&s_STSTR_CLEV,"STSTR_CLEV"},
725 {&s_STSTR_COMPON,"STSTR_COMPON"},
726 {&s_STSTR_COMPOFF,"STSTR_COMPOFF"},
727 {&s_E1TEXT,"E1TEXT"},
728 {&s_E2TEXT,"E2TEXT"},
729 {&s_E3TEXT,"E3TEXT"},
730 {&s_E4TEXT,"E4TEXT"},
731 {&s_C1TEXT,"C1TEXT"},
732 {&s_C2TEXT,"C2TEXT"},
733 {&s_C3TEXT,"C3TEXT"},
734 {&s_C4TEXT,"C4TEXT"},
735 {&s_C5TEXT,"C5TEXT"},
736 {&s_C6TEXT,"C6TEXT"},
737 {&s_P1TEXT,"P1TEXT"},
738 {&s_P2TEXT,"P2TEXT"},
739 {&s_P3TEXT,"P3TEXT"},
740 {&s_P4TEXT,"P4TEXT"},
741 {&s_P5TEXT,"P5TEXT"},
742 {&s_P6TEXT,"P6TEXT"},
743 {&s_T1TEXT,"T1TEXT"},
744 {&s_T2TEXT,"T2TEXT"},
745 {&s_T3TEXT,"T3TEXT"},
746 {&s_T4TEXT,"T4TEXT"},
747 {&s_T5TEXT,"T5TEXT"},
748 {&s_T6TEXT,"T6TEXT"},
749 {&s_CC_ZOMBIE,"CC_ZOMBIE"},
750 {&s_CC_SHOTGUN,"CC_SHOTGUN"},
751 {&s_CC_HEAVY,"CC_HEAVY"},
752 {&s_CC_IMP,"CC_IMP"},
753 {&s_CC_DEMON,"CC_DEMON"},
754 {&s_CC_LOST,"CC_LOST"},
755 {&s_CC_CACO,"CC_CACO"},
756 {&s_CC_HELL,"CC_HELL"},
757 {&s_CC_BARON,"CC_BARON"},
758 {&s_CC_ARACH,"CC_ARACH"},
759 {&s_CC_PAIN,"CC_PAIN"},
760 {&s_CC_REVEN,"CC_REVEN"},
761 {&s_CC_MANCU,"CC_MANCU"},
762 {&s_CC_ARCH,"CC_ARCH"},
763 {&s_CC_SPIDER,"CC_SPIDER"},
764 {&s_CC_CYBER,"CC_CYBER"},
765 {&s_CC_HERO,"CC_HERO"},
766 {&bgflatE1,"BGFLATE1"},
767 {&bgflatE2,"BGFLATE2"},
768 {&bgflatE3,"BGFLATE3"},
769 {&bgflatE4,"BGFLATE4"},
770 {&bgflat06,"BGFLAT06"},
771 {&bgflat11,"BGFLAT11"},
772 {&bgflat20,"BGFLAT20"},
773 {&bgflat30,"BGFLAT30"},
774 {&bgflat15,"BGFLAT15"},
775 {&bgflat31,"BGFLAT31"},
776 {&bgcastcall,"BGCASTCALL"},
777 // Ty 04/08/98 - added 5 general purpose startup announcement
778 // strings for hacker use. See m_menu.c
779 {&startup1,"STARTUP1"},
780 {&startup2,"STARTUP2"},
781 {&startup3,"STARTUP3"},
782 {&startup4,"STARTUP4"},
783 {&startup5,"STARTUP5"},
784 {&savegamename,"SAVEGAMENAME"}, // Ty 05/03/98
785};
786
787static int deh_numstrlookup =
788sizeof(deh_strlookup)/sizeof(deh_strlookup[0]);
789
790const char *deh_newlevel = "NEWLEVEL"; // CPhipps - const
791
792// DOOM shareware/registered/retail (Ultimate) names.
793// CPhipps - const**const
794const char **const mapnames[] =
795{
796 &s_HUSTR_E1M1,
797 &s_HUSTR_E1M2,
798 &s_HUSTR_E1M3,
799 &s_HUSTR_E1M4,
800 &s_HUSTR_E1M5,
801 &s_HUSTR_E1M6,
802 &s_HUSTR_E1M7,
803 &s_HUSTR_E1M8,
804 &s_HUSTR_E1M9,
805
806 &s_HUSTR_E2M1,
807 &s_HUSTR_E2M2,
808 &s_HUSTR_E2M3,
809 &s_HUSTR_E2M4,
810 &s_HUSTR_E2M5,
811 &s_HUSTR_E2M6,
812 &s_HUSTR_E2M7,
813 &s_HUSTR_E2M8,
814 &s_HUSTR_E2M9,
815
816 &s_HUSTR_E3M1,
817 &s_HUSTR_E3M2,
818 &s_HUSTR_E3M3,
819 &s_HUSTR_E3M4,
820 &s_HUSTR_E3M5,
821 &s_HUSTR_E3M6,
822 &s_HUSTR_E3M7,
823 &s_HUSTR_E3M8,
824 &s_HUSTR_E3M9,
825
826 &s_HUSTR_E4M1,
827 &s_HUSTR_E4M2,
828 &s_HUSTR_E4M3,
829 &s_HUSTR_E4M4,
830 &s_HUSTR_E4M5,
831 &s_HUSTR_E4M6,
832 &s_HUSTR_E4M7,
833 &s_HUSTR_E4M8,
834 &s_HUSTR_E4M9,
835
836 &deh_newlevel, // spares? Unused.
837 &deh_newlevel,
838 &deh_newlevel,
839 &deh_newlevel,
840 &deh_newlevel,
841 &deh_newlevel,
842 &deh_newlevel,
843 &deh_newlevel,
844 &deh_newlevel
845};
846
847// CPhipps - const**const
848const char **const mapnames2[] = // DOOM 2 map names.
849{
850 &s_HUSTR_1,
851 &s_HUSTR_2,
852 &s_HUSTR_3,
853 &s_HUSTR_4,
854 &s_HUSTR_5,
855 &s_HUSTR_6,
856 &s_HUSTR_7,
857 &s_HUSTR_8,
858 &s_HUSTR_9,
859 &s_HUSTR_10,
860 &s_HUSTR_11,
861
862 &s_HUSTR_12,
863 &s_HUSTR_13,
864 &s_HUSTR_14,
865 &s_HUSTR_15,
866 &s_HUSTR_16,
867 &s_HUSTR_17,
868 &s_HUSTR_18,
869 &s_HUSTR_19,
870 &s_HUSTR_20,
871
872 &s_HUSTR_21,
873 &s_HUSTR_22,
874 &s_HUSTR_23,
875 &s_HUSTR_24,
876 &s_HUSTR_25,
877 &s_HUSTR_26,
878 &s_HUSTR_27,
879 &s_HUSTR_28,
880 &s_HUSTR_29,
881 &s_HUSTR_30,
882 &s_HUSTR_31,
883 &s_HUSTR_32,
884};
885
886// CPhipps - const**const
887const char **const mapnamesp[] = // Plutonia WAD map names.
888{
889 &s_PHUSTR_1,
890 &s_PHUSTR_2,
891 &s_PHUSTR_3,
892 &s_PHUSTR_4,
893 &s_PHUSTR_5,
894 &s_PHUSTR_6,
895 &s_PHUSTR_7,
896 &s_PHUSTR_8,
897 &s_PHUSTR_9,
898 &s_PHUSTR_10,
899 &s_PHUSTR_11,
900
901 &s_PHUSTR_12,
902 &s_PHUSTR_13,
903 &s_PHUSTR_14,
904 &s_PHUSTR_15,
905 &s_PHUSTR_16,
906 &s_PHUSTR_17,
907 &s_PHUSTR_18,
908 &s_PHUSTR_19,
909 &s_PHUSTR_20,
910
911 &s_PHUSTR_21,
912 &s_PHUSTR_22,
913 &s_PHUSTR_23,
914 &s_PHUSTR_24,
915 &s_PHUSTR_25,
916 &s_PHUSTR_26,
917 &s_PHUSTR_27,
918 &s_PHUSTR_28,
919 &s_PHUSTR_29,
920 &s_PHUSTR_30,
921 &s_PHUSTR_31,
922 &s_PHUSTR_32,
923};
924
925// CPhipps - const**const
926const char **const mapnamest[] = // TNT WAD map names.
927{
928 &s_THUSTR_1,
929 &s_THUSTR_2,
930 &s_THUSTR_3,
931 &s_THUSTR_4,
932 &s_THUSTR_5,
933 &s_THUSTR_6,
934 &s_THUSTR_7,
935 &s_THUSTR_8,
936 &s_THUSTR_9,
937 &s_THUSTR_10,
938 &s_THUSTR_11,
939
940 &s_THUSTR_12,
941 &s_THUSTR_13,
942 &s_THUSTR_14,
943 &s_THUSTR_15,
944 &s_THUSTR_16,
945 &s_THUSTR_17,
946 &s_THUSTR_18,
947 &s_THUSTR_19,
948 &s_THUSTR_20,
949
950 &s_THUSTR_21,
951 &s_THUSTR_22,
952 &s_THUSTR_23,
953 &s_THUSTR_24,
954 &s_THUSTR_25,
955 &s_THUSTR_26,
956 &s_THUSTR_27,
957 &s_THUSTR_28,
958 &s_THUSTR_29,
959 &s_THUSTR_30,
960 &s_THUSTR_31,
961 &s_THUSTR_32,
962};
963
964// Function prototypes
965void lfstrip(char *); // strip the \r and/or \n off of a line
966void rstrip(char *); // strip trailing whitespace
967char * ptr_lstrip(char *); // point past leading whitespace
968boolean deh_GetData(char *, char *, uint_64_t *, char **, FILE *);
969boolean deh_procStringSub(char *, char *, char *, FILE *);
970char * dehReformatStr(char *);
971
972// Prototypes for block processing functions
973// Pointers to these functions are used as the blocks are encountered.
974
975static void deh_procThing(DEHFILE *fpin, FILE* fpout, char *line);
976static void deh_procFrame(DEHFILE *, FILE*, char *);
977static void deh_procPointer(DEHFILE *, FILE*, char *);
978static void deh_procSounds(DEHFILE *, FILE*, char *);
979static void deh_procAmmo(DEHFILE *, FILE*, char *);
980static void deh_procWeapon(DEHFILE *, FILE*, char *);
981static void deh_procSprite(DEHFILE *, FILE*, char *);
982static void deh_procCheat(DEHFILE *, FILE*, char *);
983static void deh_procMisc(DEHFILE *, FILE*, char *);
984static void deh_procText(DEHFILE *, FILE*, char *);
985static void deh_procPars(DEHFILE *, FILE*, char *);
986static void deh_procStrings(DEHFILE *, FILE*, char *);
987static void deh_procError(DEHFILE *, FILE*, char *);
988static void deh_procBexCodePointers(DEHFILE *, FILE*, char *);
989static void deh_procHelperThing(DEHFILE *, FILE *, char *); // haleyjd 9/22/99
990// haleyjd: handlers to fully deprecate the DeHackEd text section
991static void deh_procBexSounds(DEHFILE *, FILE *, char *);
992static void deh_procBexMusic(DEHFILE *, FILE *, char *);
993static void deh_procBexSprites(DEHFILE *, FILE *, char *);
994
995// Structure deh_block is used to hold the block names that can
996// be encountered, and the routines to use to decipher them
997
998typedef struct
999{
1000 const char *key; // a mnemonic block code name // CPhipps - const*
1001 void (*const fptr)(DEHFILE *, FILE*, char *); // handler
1002} deh_block;
1003
1004#define DEH_BUFFERMAX 1024 // input buffer area size, hardcodedfor now
1005// killough 8/9/98: make DEH_BLOCKMAX self-adjusting
1006#define DEH_BLOCKMAX (sizeof deh_blocks/sizeof*deh_blocks) // size of array
1007#define DEH_MAXKEYLEN 32 // as much of any key as we'll look at
1008#define DEH_MOBJINFOMAX 24 // number of ints in the mobjinfo_t structure (!)
1009
1010// Put all the block header values, and the function to be called when that
1011// one is encountered, in this array:
1012static const deh_block deh_blocks[] = { // CPhipps - static const
1013 /* 0 */ {"Thing",deh_procThing},
1014 /* 1 */ {"Frame",deh_procFrame},
1015 /* 2 */ {"Pointer",deh_procPointer},
1016 /* 3 */ {"Sound",deh_procSounds}, // Ty 03/16/98 corrected from "Sounds"
1017 /* 4 */ {"Ammo",deh_procAmmo},
1018 /* 5 */ {"Weapon",deh_procWeapon},
1019 /* 6 */ {"Sprite",deh_procSprite},
1020 /* 7 */ {"Cheat",deh_procCheat},
1021 /* 8 */ {"Misc",deh_procMisc},
1022 /* 9 */ {"Text",deh_procText}, // -- end of standard "deh" entries,
1023
1024 // begin BOOM Extensions (BEX)
1025
1026 /* 10 */ {"[STRINGS]",deh_procStrings}, // new string changes
1027 /* 11 */ {"[PARS]",deh_procPars}, // alternative block marker
1028 /* 12 */ {"[CODEPTR]",deh_procBexCodePointers}, // bex codepointers by mnemonic
1029 /* 13 */ {"[HELPER]", deh_procHelperThing}, // helper thing substitution haleyjd 9/22/99
1030 /* 14 */ {"[SPRITES]", deh_procBexSprites}, // bex style sprites
1031 /* 15 */ {"[SOUNDS]", deh_procBexSounds}, // bex style sounds
1032 /* 16 */ {"[MUSIC]", deh_procBexMusic}, // bex style music
1033 /* 17 */ {"", deh_procError} // dummy to handle anything else
1034};
1035
1036// flag to skip included deh-style text, used with INCLUDE NOTEXT directive
1037static boolean includenotext = false;
1038
1039// MOBJINFO - Dehacked block name = "Thing"
1040// Usage: Thing nn (name)
1041// These are for mobjinfo_t types. Each is an integer
1042// within the structure, so we can use index of the string in this
1043// array to offset by sizeof(int) into the mobjinfo_t array at [nn]
1044// * things are base zero but dehacked considers them to start at #1. ***
1045// CPhipps - static const
1046
1047static const char *deh_mobjinfo[DEH_MOBJINFOMAX] =
1048{
1049 "ID #", // .doomednum
1050 "Initial frame", // .spawnstate
1051 "Hit points", // .spawnhealth
1052 "First moving frame", // .seestate
1053 "Alert sound", // .seesound
1054 "Reaction time", // .reactiontime
1055 "Attack sound", // .attacksound
1056 "Injury frame", // .painstate
1057 "Pain chance", // .painchance
1058 "Pain sound", // .painsound
1059 "Close attack frame", // .meleestate
1060 "Far attack frame", // .missilestate
1061 "Death frame", // .deathstate
1062 "Exploding frame", // .xdeathstate
1063 "Death sound", // .deathsound
1064 "Speed", // .speed
1065 "Width", // .radius
1066 "Height", // .height
1067 "Mass", // .mass
1068 "Missile damage", // .damage
1069 "Action sound", // .activesound
1070 "Bits", // .flags
1071 "Bits2", // .flags
1072 "Respawn frame" // .raisestate
1073};
1074
1075// Strings that are used to indicate flags ("Bits" in mobjinfo)
1076// This is an array of bit masks that are related to p_mobj.h
1077// values, using the smae names without the MF_ in front.
1078// Ty 08/27/98 new code
1079//
1080// killough 10/98:
1081//
1082// Convert array to struct to allow multiple values, make array size variable
1083
1084#define DEH_MOBJFLAGMAX (sizeof deh_mobjflags/sizeof*deh_mobjflags)
1085
1086struct deh_mobjflags_s {
1087 const char *name; // CPhipps - const*
1088 uint_64_t value;
1089};
1090
1091// CPhipps - static const
1092static const struct deh_mobjflags_s deh_mobjflags[] = {
1093 {"SPECIAL", MF_SPECIAL}, // call P_Specialthing when touched
1094 {"SOLID", MF_SOLID}, // block movement
1095 {"SHOOTABLE", MF_SHOOTABLE}, // can be hit
1096 {"NOSECTOR", MF_NOSECTOR}, // invisible but touchable
1097 {"NOBLOCKMAP", MF_NOBLOCKMAP}, // inert but displayable
1098 {"AMBUSH", MF_AMBUSH}, // deaf monster
1099 {"JUSTHIT", MF_JUSTHIT}, // will try to attack right back
1100 {"JUSTATTACKED", MF_JUSTATTACKED}, // take at least 1 step before attacking
1101 {"SPAWNCEILING", MF_SPAWNCEILING}, // initially hang from ceiling
1102 {"NOGRAVITY", MF_NOGRAVITY}, // don't apply gravity during play
1103 {"DROPOFF", MF_DROPOFF}, // can jump from high places
1104 {"PICKUP", MF_PICKUP}, // will pick up items
1105 {"NOCLIP", MF_NOCLIP}, // goes through walls
1106 {"SLIDE", MF_SLIDE}, // keep info about sliding along walls
1107 {"FLOAT", MF_FLOAT}, // allow movement to any height
1108 {"TELEPORT", MF_TELEPORT}, // don't cross lines or look at heights
1109 {"MISSILE", MF_MISSILE}, // don't hit same species, explode on block
1110 {"DROPPED", MF_DROPPED}, // dropped, not spawned (like ammo clip)
1111 {"SHADOW", MF_SHADOW}, // use fuzzy draw like spectres
1112 {"NOBLOOD", MF_NOBLOOD}, // puffs instead of blood when shot
1113 {"CORPSE", MF_CORPSE}, // so it will slide down steps when dead
1114 {"INFLOAT", MF_INFLOAT}, // float but not to target height
1115 {"COUNTKILL", MF_COUNTKILL}, // count toward the kills total
1116 {"COUNTITEM", MF_COUNTITEM}, // count toward the items total
1117 {"SKULLFLY", MF_SKULLFLY}, // special handling for flying skulls
1118 {"NOTDMATCH", MF_NOTDMATCH}, // do not spawn in deathmatch
1119
1120 // killough 10/98: TRANSLATION consists of 2 bits, not 1:
1121
1122 {"TRANSLATION", MF_TRANSLATION1}, // for Boom bug-compatibility
1123 {"TRANSLATION1", MF_TRANSLATION1}, // use translation table for color (players)
1124 {"TRANSLATION2", MF_TRANSLATION2}, // use translation table for color (players)
1125 {"UNUSED1", MF_TRANSLATION2}, // unused bit # 1 -- For Boom bug-compatibility
1126 {"UNUSED2", MF_UNUSED2}, // unused bit # 2 -- For Boom compatibility
1127 {"UNUSED3", MF_UNUSED3}, // unused bit # 3 -- For Boom compatibility
1128 {"UNUSED4", MF_TRANSLUCENT}, // unused bit # 4 -- For Boom compatibility
1129 {"TRANSLUCENT", MF_TRANSLUCENT}, // apply translucency to sprite (BOOM)
1130 {"TOUCHY", MF_TOUCHY}, // dies on contact with solid objects (MBF)
1131 {"BOUNCES", MF_BOUNCES}, // bounces off floors, ceilings and maybe walls (MBF)
1132 {"FRIEND", MF_FRIEND}, // a friend of the player(s) (MBF)
1133};
1134
1135// STATE - Dehacked block name = "Frame" and "Pointer"
1136// Usage: Frame nn
1137// Usage: Pointer nn (Frame nn)
1138// These are indexed separately, for lookup to the actual
1139// function pointers. Here we'll take whatever Dehacked gives
1140// us and go from there. The (Frame nn) after the pointer is the
1141// real place to put this value. The "Pointer" value is an xref
1142// that Dehacked uses and is useless to us.
1143// * states are base zero and have a dummy #0 (TROO)
1144
1145static const char *deh_state[] = // CPhipps - static const*
1146{
1147 "Sprite number", // .sprite (spritenum_t) // an enum
1148 "Sprite subnumber", // .frame (long)
1149 "Duration", // .tics (long)
1150 "Next frame", // .nextstate (statenum_t)
1151 // This is set in a separate "Pointer" block from Dehacked
1152 "Codep Frame", // pointer to first use of action (actionf_t)
1153 "Unknown 1", // .misc1 (long)
1154 "Unknown 2" // .misc2 (long)
1155};
1156
1157// SFXINFO_STRUCT - Dehacked block name = "Sounds"
1158// Sound effects, typically not changed (redirected, and new sfx put
1159// into the pwad, but not changed here. Can you tell that Gregdidn't
1160// know what they were for, mostly? Can you tell that I don't either?
1161// Mostly I just put these into the same slots as they are in the struct.
1162// This may not be supported in our -deh option if it doesn't make sense by then.
1163
1164// * sounds are base zero but have a dummy #0
1165
1166static const char *deh_sfxinfo[] = // CPhipps - static const*
1167{
1168 "Offset", // pointer to a name string, changed in text
1169 "Zero/One", // .singularity (int, one at a time flag)
1170 "Value", // .priority
1171 "Zero 1", // .link (sfxinfo_t*) referenced sound if linked
1172 "Zero 2", // .pitch
1173 "Zero 3", // .volume
1174 "Zero 4", // .data (SAMPLE*) sound data
1175 "Neg. One 1", // .usefulness
1176 "Neg. One 2" // .lumpnum
1177};
1178
1179// MUSICINFO is not supported in Dehacked. Ignored here.
1180// * music entries are base zero but have a dummy #0
1181
1182// SPRITE - Dehacked block name = "Sprite"
1183// Usage = Sprite nn
1184// Sprite redirection by offset into the text area - unsupported by BOOM
1185// * sprites are base zero and dehacked uses it that way.
1186
1187// static const char *deh_sprite[] = // CPhipps - static const*
1188// {
1189// "Offset" // supposed to be the offset into the text section
1190// };
1191
1192// AMMO - Dehacked block name = "Ammo"
1193// usage = Ammo n (name)
1194// Ammo information for the few types of ammo
1195
1196static const char *deh_ammo[] = // CPhipps - static const*
1197{
1198 "Max ammo", // maxammo[]
1199 "Per ammo" // clipammo[]
1200};
1201
1202// WEAPONS - Dehacked block name = "Weapon"
1203// Usage: Weapon nn (name)
1204// Basically a list of frames and what kind of ammo (see above)it uses.
1205
1206static const char *deh_weapon[] = // CPhipps - static const*
1207{
1208 "Ammo type", // .ammo
1209 "Deselect frame", // .upstate
1210 "Select frame", // .downstate
1211 "Bobbing frame", // .readystate
1212 "Shooting frame", // .atkstate
1213 "Firing frame" // .flashstate
1214};
1215
1216// CHEATS - Dehacked block name = "Cheat"
1217// Usage: Cheat 0
1218// Always uses a zero in the dehacked file, for consistency. No meaning.
1219// These are just plain funky terms compared with id's
1220//
1221// killough 4/18/98: integrated into main cheat table now (see st_stuff.c)
1222
1223// MISC - Dehacked block name = "Misc"
1224// Usage: Misc 0
1225// Always uses a zero in the dehacked file, for consistency. No meaning.
1226
1227static const char *deh_misc[] = // CPhipps - static const*
1228{
1229 "Initial Health", // initial_health
1230 "Initial Bullets", // initial_bullets
1231 "Max Health", // maxhealth
1232 "Max Armor", // max_armor
1233 "Green Armor Class", // green_armor_class
1234 "Blue Armor Class", // blue_armor_class
1235 "Max Soulsphere", // max_soul
1236 "Soulsphere Health", // soul_health
1237 "Megasphere Health", // mega_health
1238 "God Mode Health", // god_health
1239 "IDFA Armor", // idfa_armor
1240 "IDFA Armor Class", // idfa_armor_class
1241 "IDKFA Armor", // idkfa_armor
1242 "IDKFA Armor Class", // idkfa_armor_class
1243 "BFG Cells/Shot", // BFGCELLS
1244 "Monsters Infight" // Unknown--not a specific number it seems, but
1245 // the logic has to be here somewhere or
1246 // it'd happen always
1247};
1248
1249// TEXT - Dehacked block name = "Text"
1250// Usage: Text fromlen tolen
1251// Dehacked allows a bit of adjustment to the length (why?)
1252
1253// BEX extension [CODEPTR]
1254// Usage: Start block, then each line is:
1255// FRAME nnn = PointerMnemonic
1256
1257typedef struct {
1258 actionf_t cptr; // actual pointer to the subroutine
1259 const char *lookup; // mnemonic lookup string to be specified in BEX
1260 // CPhipps - const*
1261} deh_bexptr;
1262
1263static const deh_bexptr deh_bexptrs[] = // CPhipps - static const
1264{
1265 {A_Light0, "A_Light0"},
1266 {A_WeaponReady, "A_WeaponReady"},
1267 {A_Lower, "A_Lower"},
1268 {A_Raise, "A_Raise"},
1269 {A_Punch, "A_Punch"},
1270 {A_ReFire, "A_ReFire"},
1271 {A_FirePistol, "A_FirePistol"},
1272 {A_Light1, "A_Light1"},
1273 {A_FireShotgun, "A_FireShotgun"},
1274 {A_Light2, "A_Light2"},
1275 {A_FireShotgun2, "A_FireShotgun2"},
1276 {A_CheckReload, "A_CheckReload"},
1277 {A_OpenShotgun2, "A_OpenShotgun2"},
1278 {A_LoadShotgun2, "A_LoadShotgun2"},
1279 {A_CloseShotgun2, "A_CloseShotgun2"},
1280 {A_FireCGun, "A_FireCGun"},
1281 {A_GunFlash, "A_GunFlash"},
1282 {A_FireMissile, "A_FireMissile"},
1283 {A_Saw, "A_Saw"},
1284 {A_FirePlasma, "A_FirePlasma"},
1285 {A_BFGsound, "A_BFGsound"},
1286 {A_FireBFG, "A_FireBFG"},
1287 {A_BFGSpray, "A_BFGSpray"},
1288 {A_Explode, "A_Explode"},
1289 {A_Pain, "A_Pain"},
1290 {A_PlayerScream, "A_PlayerScream"},
1291 {A_Fall, "A_Fall"},
1292 {A_XScream, "A_XScream"},
1293 {A_Look, "A_Look"},
1294 {A_Chase, "A_Chase"},
1295 {A_FaceTarget, "A_FaceTarget"},
1296 {A_PosAttack, "A_PosAttack"},
1297 {A_Scream, "A_Scream"},
1298 {A_SPosAttack, "A_SPosAttack"},
1299 {A_VileChase, "A_VileChase"},
1300 {A_VileStart, "A_VileStart"},
1301 {A_VileTarget, "A_VileTarget"},
1302 {A_VileAttack, "A_VileAttack"},
1303 {A_StartFire, "A_StartFire"},
1304 {A_Fire, "A_Fire"},
1305 {A_FireCrackle, "A_FireCrackle"},
1306 {A_Tracer, "A_Tracer"},
1307 {A_SkelWhoosh, "A_SkelWhoosh"},
1308 {A_SkelFist, "A_SkelFist"},
1309 {A_SkelMissile, "A_SkelMissile"},
1310 {A_FatRaise, "A_FatRaise"},
1311 {A_FatAttack1, "A_FatAttack1"},
1312 {A_FatAttack2, "A_FatAttack2"},
1313 {A_FatAttack3, "A_FatAttack3"},
1314 {A_BossDeath, "A_BossDeath"},
1315 {A_CPosAttack, "A_CPosAttack"},
1316 {A_CPosRefire, "A_CPosRefire"},
1317 {A_TroopAttack, "A_TroopAttack"},
1318 {A_SargAttack, "A_SargAttack"},
1319 {A_HeadAttack, "A_HeadAttack"},
1320 {A_BruisAttack, "A_BruisAttack"},
1321 {A_SkullAttack, "A_SkullAttack"},
1322 {A_Metal, "A_Metal"},
1323 {A_SpidRefire, "A_SpidRefire"},
1324 {A_BabyMetal, "A_BabyMetal"},
1325 {A_BspiAttack, "A_BspiAttack"},
1326 {A_Hoof, "A_Hoof"},
1327 {A_CyberAttack, "A_CyberAttack"},
1328 {A_PainAttack, "A_PainAttack"},
1329 {A_PainDie, "A_PainDie"},
1330 {A_KeenDie, "A_KeenDie"},
1331 {A_BrainPain, "A_BrainPain"},
1332 {A_BrainScream, "A_BrainScream"},
1333 {A_BrainDie, "A_BrainDie"},
1334 {A_BrainAwake, "A_BrainAwake"},
1335 {A_BrainSpit, "A_BrainSpit"},
1336 {A_SpawnSound, "A_SpawnSound"},
1337 {A_SpawnFly, "A_SpawnFly"},
1338 {A_BrainExplode, "A_BrainExplode"},
1339 {A_Detonate, "A_Detonate"}, // killough 8/9/98
1340 {A_Mushroom, "A_Mushroom"}, // killough 10/98
1341 {A_Die, "A_Die"}, // killough 11/98
1342 {A_Spawn, "A_Spawn"}, // killough 11/98
1343 {A_Turn, "A_Turn"}, // killough 11/98
1344 {A_Face, "A_Face"}, // killough 11/98
1345 {A_Scratch, "A_Scratch"}, // killough 11/98
1346 {A_PlaySound, "A_PlaySound"}, // killough 11/98
1347 {A_RandomJump, "A_RandomJump"}, // killough 11/98
1348 {A_LineEffect, "A_LineEffect"}, // killough 11/98
1349
1350 // This NULL entry must be the last in the list
1351 {NULL, "A_NULL"}, // Ty 05/16/98
1352};
1353
1354// to hold startup code pointers from INFO.C
1355// CPhipps - static
1356static actionf_t deh_codeptr[NUMSTATES];
1357
1358// haleyjd: support for BEX SPRITES, SOUNDS, and MUSIC
1359char *deh_spritenames[NUMSPRITES + 1];
1360char *deh_musicnames[NUMMUSIC + 1];
1361char *deh_soundnames[NUMSFX + 1];
1362
1363void D_BuildBEXTables(void)
1364{
1365 int i;
1366
1367 // moved from ProcessDehFile, then we don't need the static int i
1368 for (i = 0; i < NUMSTATES; i++) // remember what they start as for deh xref
1369 deh_codeptr[i] = states[i].action;
1370
1371 for(i = 0; i < NUMSPRITES; i++)
1372 deh_spritenames[i] = strdup(sprnames[i]);
1373 deh_spritenames[NUMSPRITES] = NULL;
1374
1375 for(i = 1; i < NUMMUSIC; i++)
1376 deh_musicnames[i] = strdup(S_music[i].name);
1377 deh_musicnames[0] = deh_musicnames[NUMMUSIC] = NULL;
1378
1379 for(i = 1; i < NUMSFX; i++)
1380 deh_soundnames[i] = strdup(S_sfx[i].name);
1381 deh_soundnames[0] = deh_soundnames[NUMSFX] = NULL;
1382}
1383
1384// ====================================================================
1385// ProcessDehFile
1386// Purpose: Read and process a DEH or BEX file
1387// Args: filename -- name of the DEH/BEX file
1388// outfilename -- output file (DEHOUT.TXT), appended to here
1389// Returns: void
1390//
1391// killough 10/98:
1392// substantially modified to allow input from wad lumps instead of .deh files.
1393
1394void ProcessDehFile(const char *filename, const char *outfilename, int lumpnum)
1395{
1396 static FILE *fileout; // In case -dehout was used
1397 DEHFILE infile, *filein = &infile; // killough 10/98
1398 char inbuffer[DEH_BUFFERMAX]; // Place to put the primary infostring
1399
1400 // Open output file if we're writing output
1401 if (outfilename && *outfilename && !fileout)
1402 {
1403 static boolean firstfile = true; // to allow append to output log
1404 if (!strcmp(outfilename, "-"))
1405 fileout = stdout;
1406 else
1407 if (!(fileout=fopen(outfilename, firstfile ? "wt" : "at")))
1408 {
1409 lprintf(LO_WARN, "Could not open -dehout file %s\n... using stdout.\n",
1410 outfilename);
1411 fileout = stdout;
1412 }
1413 firstfile = false;
1414 }
1415
1416 // killough 10/98: allow DEH files to come from wad lumps
1417
1418 if (filename)
1419 {
1420 if (!(infile.f = fopen(filename,"rt")))
1421 {
1422 lprintf(LO_WARN, "-deh file %s not found\n",filename);
1423 return; // should be checked up front anyway
1424 }
1425 infile.lump = NULL;
1426 }
1427 else // DEH file comes from lump indicated by third argument
1428 {
1429 infile.size = W_LumpLength(lumpnum);
1430 infile.inp = infile.lump = W_CacheLumpNum(lumpnum);
1431 filename = "(WAD)";
1432 }
1433
1434 lprintf(LO_INFO, "Loading DEH file %s\n",filename);
1435 if (fileout) fprintf(fileout,"\nLoading DEH file %s\n\n",filename);
1436
1437 // move deh_codeptr initialisation to D_BuildBEXTables
1438
1439 // loop until end of file
1440
1441 while (dehfgets(inbuffer,sizeof(inbuffer),filein))
1442 {
1443 unsigned i;
1444
1445 lfstrip(inbuffer);
1446 if (fileout) fprintf(fileout,"Line='%s'\n",inbuffer);
1447 if (!*inbuffer || *inbuffer == '#' || *inbuffer == ' ')
1448 continue; /* Blank line or comment line */
1449
1450 // -- If DEH_BLOCKMAX is set right, the processing is independently
1451 // -- handled based on data in the deh_blocks[] structure array
1452
1453 // killough 10/98: INCLUDE code rewritten to allow arbitrary nesting,
1454 // and to greatly simplify code, fix memory leaks, other bugs
1455
1456 if (!strnicmp(inbuffer,"INCLUDE",7)) // include a file
1457 {
1458 // preserve state while including a file
1459 // killough 10/98: moved to here
1460
1461 char *nextfile;
1462 boolean oldnotext = includenotext; // killough 10/98
1463
1464 // killough 10/98: exclude if inside wads (only to discourage
1465 // the practice, since the code could otherwise handle it)
1466
1467 if (infile.lump)
1468 {
1469 if (fileout)
1470 fprintf(fileout,
1471 "No files may be included from wads: %s\n",inbuffer);
1472 continue;
1473 }
1474
1475 // check for no-text directive, used when including a DEH
1476 // file but using the BEX format to handle strings
1477
1478 if (!strnicmp(nextfile = ptr_lstrip(inbuffer+7),"NOTEXT",6))
1479 includenotext = true, nextfile = ptr_lstrip(nextfile+6);
1480
1481 if (fileout)
1482 fprintf(fileout,"Branching to include file %s...\n", nextfile);
1483
1484 // killough 10/98:
1485 // Second argument must be NULL to prevent closing fileout too soon
1486
1487 ProcessDehFile(nextfile,NULL,0); // do the included file
1488
1489 includenotext = oldnotext;
1490 if (fileout) fprintf(fileout,"...continuing with %s\n",filename);
1491 continue;
1492 }
1493
1494 for (i=0; i<DEH_BLOCKMAX; i++)
1495 if (!strncasecmp(inbuffer,deh_blocks[i].key,strlen(deh_blocks[i].key)))
1496 { // matches one
1497 if (fileout)
1498 fprintf(fileout,"Processing function [%d] for %s\n",
1499 i, deh_blocks[i].key);
1500 deh_blocks[i].fptr(filein,fileout,inbuffer); // call function
1501 break; // we got one, that's enough for this block
1502 }
1503 }
1504
1505 if (infile.lump)
1506 W_UnlockLumpNum(lumpnum); // Mark purgable
1507 else
1508 fclose(infile.f); // Close real file
1509
1510 if (outfilename) // killough 10/98: only at top recursion level
1511 {
1512 if (fileout != stdout)
1513 fclose(fileout);
1514 fileout = NULL;
1515 }
1516}
1517
1518// ====================================================================
1519// deh_procBexCodePointers
1520// Purpose: Handle [CODEPTR] block, BOOM Extension
1521// Args: fpin -- input file stream
1522// fpout -- output file stream (DEHOUT.TXT)
1523// line -- current line in file to process
1524// Returns: void
1525//
1526static void deh_procBexCodePointers(DEHFILE *fpin, FILE* fpout, char *line)
1527{
1528 char key[DEH_MAXKEYLEN];
1529 char inbuffer[DEH_BUFFERMAX];
1530 int indexnum;
1531 char mnemonic[DEH_MAXKEYLEN]; // to hold the codepointer mnemonic
1532 int i; // looper
1533 boolean found; // know if we found this one during lookup or not
1534
1535 // Ty 05/16/98 - initialize it to something, dummy!
1536 strncpy(inbuffer,line,DEH_BUFFERMAX);
1537
1538 // for this one, we just read 'em until we hit a blank line
1539 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1540 {
1541 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1542 lfstrip(inbuffer);
1543 if (!*inbuffer) break; // killough 11/98: really exit on blank line
1544
1545 // killough 8/98: allow hex numbers in input:
1546 if ( (3 != sscanf(inbuffer,"%s %i = %s", key, &indexnum, mnemonic))
1547 || (stricmp(key,"FRAME")) ) // NOTE: different format from normal
1548 {
1549 if (fpout) fprintf(fpout,
1550 "Invalid BEX codepointer line - must start with 'FRAME': '%s'\n",
1551 inbuffer);
1552 return; // early return
1553 }
1554
1555 if (fpout) fprintf(fpout,"Processing pointer at index %d: %s\n",
1556 indexnum, mnemonic);
1557 if (indexnum < 0 || indexnum >= NUMSTATES)
1558 {
1559 if (fpout) fprintf(fpout,"Bad pointer number %d of %d\n",
1560 indexnum, NUMSTATES);
1561 return; // killough 10/98: fix SegViol
1562 }
1563 strcpy(key,"A_"); // reusing the key area to prefix the mnemonic
1564 strcat(key,ptr_lstrip(mnemonic));
1565
1566 found = FALSE;
1567 i= -1; // incremented to start at zero at the top of the loop
1568 do // Ty 05/16/98 - fix loop logic to look for null ending entry
1569 {
1570 ++i;
1571 if (!stricmp(key,deh_bexptrs[i].lookup))
1572 { // Ty 06/01/98 - add to states[].action for new djgcc version
1573 states[indexnum].action = deh_bexptrs[i].cptr; // assign
1574 if (fpout) fprintf(fpout,
1575 " - applied %s from codeptr[%d] to states[%d]\n",
1576 deh_bexptrs[i].lookup,i,indexnum);
1577 found = TRUE;
1578 }
1579 } while (!found && (deh_bexptrs[i].cptr != NULL));
1580
1581 if (!found)
1582 if (fpout) fprintf(fpout,
1583 "Invalid frame pointer mnemonic '%s' at %d\n",
1584 mnemonic, indexnum);
1585 }
1586 return;
1587}
1588
1589//---------------------------------------------------------------------------
1590// To be on the safe, compatible side, we manually convert DEH bitflags
1591// to prboom types - POPE
1592//---------------------------------------------------------------------------
1593static uint_64_t getConvertedDEHBits(uint_64_t bits) {
1594 static const uint_64_t bitMap[32] = {
1595 /* cf linuxdoom-1.10 p_mobj.h */
1596 MF_SPECIAL, // 0 Can be picked up - When touched the thing can be picked up.
1597 MF_SOLID, // 1 Obstacle - The thing is solid and will not let you (or others) pass through it
1598 MF_SHOOTABLE, // 2 Shootable - Can be shot.
1599 MF_NOSECTOR, // 3 Total Invisibility - Invisible, but can be touched
1600 MF_NOBLOCKMAP, // 4 Don't use the blocklinks (inert but displayable)
1601 MF_AMBUSH, // 5 Semi deaf - The thing is a deaf monster
1602 MF_JUSTHIT, // 6 In pain - Will try to attack right back after being hit
1603 MF_JUSTATTACKED, // 7 Steps before attack - Will take at least one step before attacking
1604 MF_SPAWNCEILING, // 8 Hangs from ceiling - When the level starts, this thing will be at ceiling height.
1605 MF_NOGRAVITY, // 9 No gravity - Gravity does not affect this thing
1606 MF_DROPOFF, // 10 Travels over cliffs - Monsters normally do not walk off ledges/steps they could not walk up. With this set they can walk off any height of cliff. Usually only used for flying monsters.
1607 MF_PICKUP, // 11 Pick up items - The thing can pick up gettable items.
1608 MF_NOCLIP, // 12 No clipping - Thing can walk through walls.
1609 MF_SLIDE, // 13 Slides along walls - Keep info about sliding along walls (don't really know much about this one).
1610 MF_FLOAT, // 14 Floating - Thing can move to any height
1611 MF_TELEPORT, // 15 Semi no clipping - Don't cross lines or look at teleport heights. (don't really know much about this one either).
1612 MF_MISSILE, // 16 Projectiles - Behaves like a projectile, explodes when hitting something that blocks movement
1613 MF_DROPPED, // 17 Disappearing weapon - Dropped, not spawned (like an ammo clip) I have not had much success in using this one.
1614 MF_SHADOW, // 18 Partial invisibility - Drawn like a spectre.
1615 MF_NOBLOOD, // 19 Puffs (vs. bleeds) - If hit will spawn bullet puffs instead of blood splats.
1616 MF_CORPSE, // 20 Sliding helpless - Will slide down steps when dead.
1617 MF_INFLOAT, // 21 No auto levelling - float but not to target height (?)
1618 MF_COUNTKILL, // 22 Affects kill % - counted as a killable enemy and affects percentage kills on level summary.
1619 MF_COUNTITEM, // 23 Affects item % - affects percentage items gathered on level summary.
1620 MF_SKULLFLY, // 24 Running - special handling for flying skulls.
1621 MF_NOTDMATCH, // 25 Not in deathmatch - do not spawn in deathmatch (like keys)
1622 MF_TRANSLATION1, // 26 Color 1 (grey / red)
1623 MF_TRANSLATION2, // 27 Color 2 (brown / red)
1624 // Convert bit 28 to MF_TOUCHY, not (MF_TRANSLATION1|MF_TRANSLATION2)
1625 // fixes bug #1576151 (part 1)
1626 MF_TOUCHY, // 28 - explodes on contact (MBF)
1627 MF_BOUNCES, // 29 - bounces off walls and floors (MBF)
1628 MF_FRIEND, // 30 - friendly monster helps players (MBF)
1629 MF_TRANSLUCENT // e6y: Translucency via dehacked/bex doesn't work without it
1630 };
1631 int i;
1632 uint_64_t shiftBits = bits;
1633 uint_64_t convertedBits = 0;
1634 for (i=0; i<32; i++) {
1635 if (shiftBits & 0x1) convertedBits |= bitMap[i];
1636 shiftBits >>= 1;
1637 }
1638 return convertedBits;
1639}
1640
1641//---------------------------------------------------------------------------
1642// See usage below for an explanation of this function's existence - POPE
1643//---------------------------------------------------------------------------
1644static void setMobjInfoValue(int mobjInfoIndex, int keyIndex, uint_64_t value) {
1645 mobjinfo_t *mi;
1646 if (mobjInfoIndex >= NUMMOBJTYPES || mobjInfoIndex < 0) return;
1647 mi = &mobjinfo[mobjInfoIndex];
1648 switch (keyIndex) {
1649 case 0: mi->doomednum = (int)value; return;
1650 case 1: mi->spawnstate = (int)value; return;
1651 case 2: mi->spawnhealth = (int)value; return;
1652 case 3: mi->seestate = (int)value; return;
1653 case 4: mi->seesound = (int)value; return;
1654 case 5: mi->reactiontime = (int)value; return;
1655 case 6: mi->attacksound = (int)value; return;
1656 case 7: mi->painstate = (int)value; return;
1657 case 8: mi->painchance = (int)value; return;
1658 case 9: mi->painsound = (int)value; return;
1659 case 10: mi->meleestate = (int)value; return;
1660 case 11: mi->missilestate = (int)value; return;
1661 case 12: mi->deathstate = (int)value; return;
1662 case 13: mi->xdeathstate = (int)value; return;
1663 case 14: mi->deathsound = (int)value; return;
1664 case 15: mi->speed = (int)value; return;
1665 case 16: mi->radius = (int)value; return;
1666 case 17: mi->height = (int)value; return;
1667 case 18: mi->mass = (int)value; return;
1668 case 19: mi->damage = (int)value; return;
1669 case 20: mi->activesound = (int)value; return;
1670 case 21: mi->flags = value; return;
1671 case 22: return; // "Bits2", unused
1672 case 23: mi->raisestate = (int)value; return;
1673 default: return;
1674 }
1675}
1676
1677// ====================================================================
1678// deh_procThing
1679// Purpose: Handle DEH Thing block
1680// Args: fpin -- input file stream
1681// fpout -- output file stream (DEHOUT.TXT)
1682// line -- current line in file to process
1683// Returns: void
1684//
1685// Ty 8/27/98 - revised to also allow mnemonics for
1686// bit masks for monster attributes
1687//
1688
1689static void deh_procThing(DEHFILE *fpin, FILE* fpout, char *line)
1690{
1691 char key[DEH_MAXKEYLEN];
1692 char inbuffer[DEH_BUFFERMAX];
1693 uint_64_t value; // All deh values are ints or longs
1694 int indexnum;
1695 int ix;
1696 char *strval;
1697
1698 strncpy(inbuffer,line,DEH_BUFFERMAX);
1699 if (fpout) fprintf(fpout,"Thing line: '%s'\n",inbuffer);
1700
1701 // killough 8/98: allow hex numbers in input:
1702 ix = sscanf(inbuffer,"%s %i",key, &indexnum);
1703 if (fpout) fprintf(fpout,"count=%d, Thing %d\n",ix, indexnum);
1704
1705 // Note that the mobjinfo[] array is base zero, but object numbers
1706 // in the dehacked file start with one. Grumble.
1707 --indexnum;
1708
1709 // now process the stuff
1710 // Note that for Things we can look up the key and use its offset
1711 // in the array of key strings as an int offset in the structure
1712
1713 // get a line until a blank or end of file--it's not
1714 // blank now because it has our incoming key in it
1715 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1716 {
1717 // e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
1718 // No more desync on HACX demos.
1719 int bGetData;
1720
1721 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1722 lfstrip(inbuffer); // toss the end of line
1723
1724 // killough 11/98: really bail out on blank lines (break != continue)
1725 if (!*inbuffer) break; // bail out with blank line between sections
1726
1727 // e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
1728 // No more desync on HACX demos.
1729 bGetData = deh_GetData(inbuffer,key,&value,&strval,fpout);
1730 if (!bGetData)
1731 // Old code: if (!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
1732 {
1733 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1734 continue;
1735 }
1736 for (ix=0; ix<DEH_MOBJINFOMAX; ix++) {
1737 if (strcasecmp(key,deh_mobjinfo[ix])) continue;
1738
1739 if (strcasecmp(key,"bits")) {
1740 // standard value set
1741
1742 // The old code here was the cause of a DEH-related bug in prboom.
1743 // When the mobjinfo_t.flags member was graduated to an int64, this
1744 // code was caught unawares and was indexing each property of the
1745 // mobjinfo as if it were still an int32. This caused sets of the
1746 // "raisestate" member to partially overwrite the "flags" member,
1747 // thus screwing everything up and making most DEH patches result in
1748 // unshootable enemy types. Moved to a separate function above
1749 // and stripped of all hairy struct address indexing. - POPE
1750 setMobjInfoValue(indexnum, ix, value);
1751 }
1752 else {
1753 // bit set
1754 // e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
1755 // No more desync on HACX demos.
1756 if (bGetData==1) { // proff
1757 value = getConvertedDEHBits(value);
1758 mobjinfo[indexnum].flags = value;
1759 }
1760 else {
1761 // figure out what the bits are
1762 value = 0;
1763
1764 // killough 10/98: replace '+' kludge with strtok() loop
1765 // Fix error-handling case ('found' var wasn't being reset)
1766 //
1767 // Use OR logic instead of addition, to allow repetition
1768 for (;(strval = strtok(strval,",+| \t\f\r")); strval = NULL) {
1769 size_t iy;
1770 for (iy=0; iy < DEH_MOBJFLAGMAX; iy++) {
1771 if (strcasecmp(strval,deh_mobjflags[iy].name)) continue;
1772 if (fpout) {
1773 fprintf(fpout,
1774 "ORed value 0x%08lX%08lX %s\n",
1775 (unsigned long)(deh_mobjflags[iy].value>>32) & 0xffffffff,
1776 (unsigned long)deh_mobjflags[iy].value & 0xffffffff, strval
1777 );
1778 }
1779 value |= deh_mobjflags[iy].value;
1780 break;
1781 }
1782 if (iy >= DEH_MOBJFLAGMAX && fpout) {
1783 fprintf(fpout, "Could not find bit mnemonic %s\n", strval);
1784 }
1785 }
1786
1787 // Don't worry about conversion -- simply print values
1788 if (fpout) {
1789 fprintf(fpout,
1790 "Bits = 0x%08lX%08lX\n",
1791 (unsigned long)(value>>32) & 0xffffffff,
1792 (unsigned long)value & 0xffffffff
1793 );
1794 }
1795 mobjinfo[indexnum].flags = value; // e6y
1796 }
1797 }
1798 if (fpout) {
1799 fprintf(fpout,
1800 "Assigned 0x%08lx%08lx to %s(%d) at index %d\n",
1801 (unsigned long)(value>>32) & 0xffffffff,
1802 (unsigned long)value & 0xffffffff, key, indexnum, ix
1803 );
1804 }
1805 }
1806 }
1807 return;
1808}
1809
1810// ====================================================================
1811// deh_procFrame
1812// Purpose: Handle DEH Frame block
1813// Args: fpin -- input file stream
1814// fpout -- output file stream (DEHOUT.TXT)
1815// line -- current line in file to process
1816// Returns: void
1817//
1818static void deh_procFrame(DEHFILE *fpin, FILE* fpout, char *line)
1819{
1820 char key[DEH_MAXKEYLEN];
1821 char inbuffer[DEH_BUFFERMAX];
1822 uint_64_t value; // All deh values are ints or longs
1823 int indexnum;
1824
1825 strncpy(inbuffer,line,DEH_BUFFERMAX);
1826
1827 // killough 8/98: allow hex numbers in input:
1828 sscanf(inbuffer,"%s %i",key, &indexnum);
1829 if (fpout) fprintf(fpout,"Processing Frame at index %d: %s\n",indexnum,key);
1830 if (indexnum < 0 || indexnum >= NUMSTATES)
1831 if (fpout) fprintf(fpout,"Bad frame number %d of %d\n",indexnum, NUMSTATES);
1832
1833 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1834 {
1835 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1836 lfstrip(inbuffer);
1837 if (!*inbuffer) break; // killough 11/98
1838 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
1839 {
1840 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1841 continue;
1842 }
1843 if (!strcasecmp(key,deh_state[0])) // Sprite number
1844 {
1845 if (fpout) fprintf(fpout," - sprite = %lld\n",value);
1846 states[indexnum].sprite = (spritenum_t)value;
1847 }
1848 else
1849 if (!strcasecmp(key,deh_state[1])) // Sprite subnumber
1850 {
1851 if (fpout) fprintf(fpout," - frame = %lld\n",value);
1852 states[indexnum].frame = (long)value; // long
1853 }
1854 else
1855 if (!strcasecmp(key,deh_state[2])) // Duration
1856 {
1857 if (fpout) fprintf(fpout," - tics = %lld\n",value);
1858 states[indexnum].tics = (long)value; // long
1859 }
1860 else
1861 if (!strcasecmp(key,deh_state[3])) // Next frame
1862 {
1863 if (fpout) fprintf(fpout," - nextstate = %lld\n",value);
1864 states[indexnum].nextstate = (statenum_t)value;
1865 }
1866 else
1867 if (!strcasecmp(key,deh_state[4])) // Codep frame (not set in Frame deh block)
1868 {
1869 if (fpout) fprintf(fpout," - codep, should not be set in Frame section!\n");
1870 /* nop */ ;
1871 }
1872 else
1873 if (!strcasecmp(key,deh_state[5])) // Unknown 1
1874 {
1875 if (fpout) fprintf(fpout," - misc1 = %lld\n",value);
1876 states[indexnum].misc1 = (long)value; // long
1877 }
1878 else
1879 if (!strcasecmp(key,deh_state[6])) // Unknown 2
1880 {
1881 if (fpout) fprintf(fpout," - misc2 = %lld\n",value);
1882 states[indexnum].misc2 = (long)value; // long
1883 }
1884 else
1885 if (fpout) fprintf(fpout,"Invalid frame string index for '%s'\n",key);
1886 }
1887 return;
1888}
1889
1890// ====================================================================
1891// deh_procPointer
1892// Purpose: Handle DEH Code pointer block, can use BEX [CODEPTR] instead
1893// Args: fpin -- input file stream
1894// fpout -- output file stream (DEHOUT.TXT)
1895// line -- current line in file to process
1896// Returns: void
1897//
1898static void deh_procPointer(DEHFILE *fpin, FILE* fpout, char *line) // done
1899{
1900 char key[DEH_MAXKEYLEN];
1901 char inbuffer[DEH_BUFFERMAX];
1902 uint_64_t value; // All deh values are ints or longs
1903 int indexnum;
1904 int i; // looper
1905
1906 strncpy(inbuffer,line,DEH_BUFFERMAX);
1907 // NOTE: different format from normal
1908
1909 // killough 8/98: allow hex numbers in input, fix error case:
1910 if (sscanf(inbuffer,"%*s %*i (%s %i)",key, &indexnum) != 2)
1911 {
1912 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1913 return;
1914 }
1915
1916 if (fpout) fprintf(fpout,"Processing Pointer at index %d: %s\n",indexnum, key);
1917 if (indexnum < 0 || indexnum >= NUMSTATES)
1918 {
1919 if (fpout)
1920 fprintf(fpout,"Bad pointer number %d of %d\n",indexnum, NUMSTATES);
1921 return;
1922 }
1923
1924 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1925 {
1926 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1927 lfstrip(inbuffer);
1928 if (!*inbuffer) break; // killough 11/98
1929 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
1930 {
1931 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1932 continue;
1933 }
1934
1935 if (value < 0 || value >= NUMSTATES)
1936 {
1937 if (fpout)
1938 fprintf(fpout,"Bad pointer number %lld of %d\n",value, NUMSTATES);
1939 return;
1940 }
1941
1942 if (!strcasecmp(key,deh_state[4])) // Codep frame (not set in Frame deh block)
1943 {
1944 states[indexnum].action = deh_codeptr[value];
1945 if (fpout) fprintf(fpout," - applied from codeptr[%lld] to states[%d]\n",
1946 value,indexnum);
1947 // Write BEX-oriented line to match:
1948 // for (i=0;i<NUMSTATES;i++) could go past the end of the array
1949 for (i=0;i<sizeof(deh_bexptrs)/sizeof(*deh_bexptrs);i++)
1950 {
1951 if (!memcmp(&deh_bexptrs[i].cptr,&deh_codeptr[value],sizeof(actionf_t)))
1952 {
1953 if (fpout) fprintf(fpout,"BEX [CODEPTR] -> FRAME %d = %s\n",
1954 indexnum, &deh_bexptrs[i].lookup[2]);
1955 break;
1956 }
1957 if (deh_bexptrs[i].cptr == NULL) // stop at null entry
1958 break;
1959 }
1960 }
1961 else
1962 if (fpout) fprintf(fpout,"Invalid frame pointer index for '%s' at %lld\n",
1963 key, value);
1964 }
1965 return;
1966}
1967
1968// ====================================================================
1969// deh_procSounds
1970// Purpose: Handle DEH Sounds block
1971// Args: fpin -- input file stream
1972// fpout -- output file stream (DEHOUT.TXT)
1973// line -- current line in file to process
1974// Returns: void
1975//
1976static void deh_procSounds(DEHFILE *fpin, FILE* fpout, char *line)
1977{
1978 char key[DEH_MAXKEYLEN];
1979 char inbuffer[DEH_BUFFERMAX];
1980 uint_64_t value; // All deh values are ints or longs
1981 int indexnum;
1982
1983 strncpy(inbuffer,line,DEH_BUFFERMAX);
1984
1985 // killough 8/98: allow hex numbers in input:
1986 sscanf(inbuffer,"%s %i",key, &indexnum);
1987 if (fpout) fprintf(fpout,"Processing Sounds at index %d: %s\n",
1988 indexnum, key);
1989 if (indexnum < 0 || indexnum >= NUMSFX)
1990 if (fpout) fprintf(fpout,"Bad sound number %d of %d\n",
1991 indexnum, NUMSFX);
1992
1993 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1994 {
1995 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1996 lfstrip(inbuffer);
1997 if (!*inbuffer) break; // killough 11/98
1998 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
1999 {
2000 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2001 continue;
2002 }
2003 if (!strcasecmp(key,deh_sfxinfo[0])) // Offset
2004 /* nop */ ; // we don't know what this is, I don't think
2005 else
2006 if (!strcasecmp(key,deh_sfxinfo[1])) // Zero/One
2007 S_sfx[indexnum].singularity = (int)value;
2008 else
2009 if (!strcasecmp(key,deh_sfxinfo[2])) // Value
2010 S_sfx[indexnum].priority = (int)value;
2011 else
2012 if (!strcasecmp(key,deh_sfxinfo[3])) // Zero 1
2013 S_sfx[indexnum].link = (sfxinfo_t *)value;
2014 else
2015 if (!strcasecmp(key,deh_sfxinfo[4])) // Zero 2
2016 S_sfx[indexnum].pitch = (int)value;
2017 else
2018 if (!strcasecmp(key,deh_sfxinfo[5])) // Zero 3
2019 S_sfx[indexnum].volume = (int)value;
2020 else
2021 if (!strcasecmp(key,deh_sfxinfo[6])) // Zero 4
2022 S_sfx[indexnum].data = (void *) value; // killough 5/3/98: changed cast
2023 else
2024 if (!strcasecmp(key,deh_sfxinfo[7])) // Neg. One 1
2025 S_sfx[indexnum].usefulness = (int)value;
2026 else
2027 if (!strcasecmp(key,deh_sfxinfo[8])) // Neg. One 2
2028 S_sfx[indexnum].lumpnum = (int)value;
2029 else
2030 if (fpout) fprintf(fpout,
2031 "Invalid sound string index for '%s'\n",key);
2032 }
2033 return;
2034}
2035
2036// ====================================================================
2037// deh_procAmmo
2038// Purpose: Handle DEH Ammo block
2039// Args: fpin -- input file stream
2040// fpout -- output file stream (DEHOUT.TXT)
2041// line -- current line in file to process
2042// Returns: void
2043//
2044static void deh_procAmmo(DEHFILE *fpin, FILE* fpout, char *line)
2045{
2046 char key[DEH_MAXKEYLEN];
2047 char inbuffer[DEH_BUFFERMAX];
2048 uint_64_t value; // All deh values are ints or longs
2049 int indexnum;
2050
2051 strncpy(inbuffer,line,DEH_BUFFERMAX);
2052
2053 // killough 8/98: allow hex numbers in input:
2054 sscanf(inbuffer,"%s %i",key, &indexnum);
2055 if (fpout) fprintf(fpout,"Processing Ammo at index %d: %s\n",
2056 indexnum, key);
2057 if (indexnum < 0 || indexnum >= NUMAMMO)
2058 if (fpout) fprintf(fpout,"Bad ammo number %d of %d\n",
2059 indexnum,NUMAMMO);
2060
2061 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2062 {
2063 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2064 lfstrip(inbuffer);
2065 if (!*inbuffer) break; // killough 11/98
2066 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
2067 {
2068 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2069 continue;
2070 }
2071 if (!strcasecmp(key,deh_ammo[0])) // Max ammo
2072 maxammo[indexnum] = (int)value;
2073 else
2074 if (!strcasecmp(key,deh_ammo[1])) // Per ammo
2075 clipammo[indexnum] = (int)value;
2076 else
2077 if (fpout) fprintf(fpout,"Invalid ammo string index for '%s'\n",key);
2078 }
2079 return;
2080}
2081
2082// ====================================================================
2083// deh_procWeapon
2084// Purpose: Handle DEH Weapon block
2085// Args: fpin -- input file stream
2086// fpout -- output file stream (DEHOUT.TXT)
2087// line -- current line in file to process
2088// Returns: void
2089//
2090static void deh_procWeapon(DEHFILE *fpin, FILE* fpout, char *line)
2091{
2092 char key[DEH_MAXKEYLEN];
2093 char inbuffer[DEH_BUFFERMAX];
2094 uint_64_t value; // All deh values are ints or longs
2095 int indexnum;
2096
2097 strncpy(inbuffer,line,DEH_BUFFERMAX);
2098
2099 // killough 8/98: allow hex numbers in input:
2100 sscanf(inbuffer,"%s %i",key, &indexnum);
2101 if (fpout) fprintf(fpout,"Processing Weapon at index %d: %s\n",
2102 indexnum, key);
2103 if (indexnum < 0 || indexnum >= NUMWEAPONS)
2104 if (fpout) fprintf(fpout,"Bad weapon number %d of %d\n",
2105 indexnum, NUMAMMO);
2106
2107 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2108 {
2109 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2110 lfstrip(inbuffer);
2111 if (!*inbuffer) break; // killough 11/98
2112 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
2113 {
2114 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2115 continue;
2116 }
2117 if (!strcasecmp(key,deh_weapon[0])) // Ammo type
2118 weaponinfo[indexnum].ammo = (ammotype_t)value;
2119 else
2120 if (!strcasecmp(key,deh_weapon[1])) // Deselect frame
2121 weaponinfo[indexnum].upstate = (int)value;
2122 else
2123 if (!strcasecmp(key,deh_weapon[2])) // Select frame
2124 weaponinfo[indexnum].downstate = (int)value;
2125 else
2126 if (!strcasecmp(key,deh_weapon[3])) // Bobbing frame
2127 weaponinfo[indexnum].readystate = (int)value;
2128 else
2129 if (!strcasecmp(key,deh_weapon[4])) // Shooting frame
2130 weaponinfo[indexnum].atkstate = (int)value;
2131 else
2132 if (!strcasecmp(key,deh_weapon[5])) // Firing frame
2133 weaponinfo[indexnum].flashstate = (int)value;
2134 else
2135 if (fpout) fprintf(fpout,"Invalid weapon string index for '%s'\n",key);
2136 }
2137 return;
2138}
2139
2140// ====================================================================
2141// deh_procSprite
2142// Purpose: Dummy - we do not support the DEH Sprite block
2143// Args: fpin -- input file stream
2144// fpout -- output file stream (DEHOUT.TXT)
2145// line -- current line in file to process
2146// Returns: void
2147//
2148static void deh_procSprite(DEHFILE *fpin, FILE* fpout, char *line) // Not supported
2149{
2150 char key[DEH_MAXKEYLEN];
2151 char inbuffer[DEH_BUFFERMAX];
2152 int indexnum;
2153
2154 // Too little is known about what this is supposed to do, and
2155 // there are better ways of handling sprite renaming. Not supported.
2156
2157 strncpy(inbuffer,line,DEH_BUFFERMAX);
2158
2159 // killough 8/98: allow hex numbers in input:
2160 sscanf(inbuffer,"%s %i",key, &indexnum);
2161 if (fpout) fprintf(fpout,
2162 "Ignoring Sprite offset change at index %d: %s\n",indexnum, key);
2163 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2164 {
2165 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2166 lfstrip(inbuffer);
2167 if (!*inbuffer) break; // killough 11/98
2168 // ignore line
2169 if (fpout) fprintf(fpout,"- %s\n",inbuffer);
2170 }
2171 return;
2172}
2173
2174// ====================================================================
2175// deh_procPars
2176// Purpose: Handle BEX extension for PAR times
2177// Args: fpin -- input file stream
2178// fpout -- output file stream (DEHOUT.TXT)
2179// line -- current line in file to process
2180// Returns: void
2181//
2182static void deh_procPars(DEHFILE *fpin, FILE* fpout, char *line) // extension
2183{
2184 char key[DEH_MAXKEYLEN];
2185 char inbuffer[DEH_BUFFERMAX];
2186 int indexnum;
2187 int episode, level, partime, oldpar;
2188
2189 // new item, par times
2190 // usage: After [PARS] Par 0 section identifier, use one or more of these
2191 // lines:
2192 // par 3 5 120
2193 // par 14 230
2194 // The first would make the par for E3M5 be 120 seconds, and the
2195 // second one makes the par for MAP14 be 230 seconds. The number
2196 // of parameters on the line determines which group of par values
2197 // is being changed. Error checking is done based on current fixed
2198 // array sizes of[4][10] and [32]
2199
2200 strncpy(inbuffer,line,DEH_BUFFERMAX);
2201
2202 // killough 8/98: allow hex numbers in input:
2203 sscanf(inbuffer,"%s %i",key, &indexnum);
2204 if (fpout) fprintf(fpout,
2205 "Processing Par value at index %d: %s\n",indexnum, key);
2206 // indexnum is a dummy entry
2207 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2208 {
2209 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2210 lfstrip(strlwr(inbuffer)); // lowercase it
2211 if (!*inbuffer) break; // killough 11/98
2212 if (3 != sscanf(inbuffer,"par %i %i %i",&episode, &level, &partime))
2213 { // not 3
2214 if (2 != sscanf(inbuffer,"par %i %i",&level, &partime))
2215 { // not 2
2216 if (fpout) fprintf(fpout,"Invalid par time setting string: %s\n",inbuffer);
2217 }
2218 else
2219 { // is 2
2220 // Ty 07/11/98 - wrong range check, not zero-based
2221 if (level < 1 || level > 32) // base 0 array (but 1-based parm)
2222 {
2223 if (fpout) fprintf(fpout,"Invalid MAPnn value MAP%d\n",level);
2224 }
2225 else
2226 {
2227 oldpar = cpars[level-1];
2228 if (fpout) fprintf(fpout,"Changed par time for MAP%02d from %d to %d\n",level,oldpar,partime);
2229 cpars[level-1] = partime;
2230 deh_pars = TRUE;
2231 }
2232 }
2233 }
2234 else
2235 { // is 3
2236 // note that though it's a [4][10] array, the "left" and "top" aren't used,
2237 // effectively making it a base 1 array.
2238 // Ty 07/11/98 - level was being checked against max 3 - dumb error
2239 // Note that episode 4 does not have par times per original design
2240 // in Ultimate DOOM so that is not supported here.
2241 if (episode < 1 || episode > 3 || level < 1 || level > 9)
2242 {
2243 if (fpout) fprintf(fpout,
2244 "Invalid ExMx values E%dM%d\n",episode, level);
2245 }
2246 else
2247 {
2248 oldpar = pars[episode][level];
2249 pars[episode][level] = partime;
2250 if (fpout) fprintf(fpout,
2251 "Changed par time for E%dM%d from %d to %d\n",
2252 episode,level,oldpar,partime);
2253 deh_pars = TRUE;
2254 }
2255 }
2256 }
2257 return;
2258}
2259
2260// ====================================================================
2261// deh_procCheat
2262// Purpose: Handle DEH Cheat block
2263// Args: fpin -- input file stream
2264// fpout -- output file stream (DEHOUT.TXT)
2265// line -- current line in file to process
2266// Returns: void
2267//
2268static void deh_procCheat(DEHFILE *fpin, FILE* fpout, char *line) // done
2269{
2270 char key[DEH_MAXKEYLEN];
2271 char inbuffer[DEH_BUFFERMAX];
2272 uint_64_t value; // All deh values are ints or longs
2273 char ch = 0; // CPhipps - `writable' null string to initialise...
2274 char *strval = &ch; // pointer to the value area
2275 int ix, iy; // array indices
2276 char *p; // utility pointer
2277
2278 if (fpout) fprintf(fpout,"Processing Cheat: %s\n",line);
2279
2280 strncpy(inbuffer,line,DEH_BUFFERMAX);
2281 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2282 {
2283 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2284 lfstrip(inbuffer);
2285 if (!*inbuffer) break; // killough 11/98
2286 if (!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2287 {
2288 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2289 continue;
2290 }
2291 // Otherwise we got a (perhaps valid) cheat name,
2292 // so look up the key in the array
2293
2294 // killough 4/18/98: use main cheat code table in st_stuff.c now
2295 for (ix=0; cheat[ix].cheat; ix++)
2296 if (cheat[ix].deh_cheat) // killough 4/18/98: skip non-deh
2297 {
2298 if (!stricmp(key,cheat[ix].deh_cheat)) // found the cheat, ignored case
2299 {
2300 // replace it but don't overflow it. Use current length as limit.
2301 // Ty 03/13/98 - add 0xff code
2302 // Deal with the fact that the cheats in deh files are extended
2303 // with character 0xFF to the original cheat length, which we don't do.
2304 for (iy=0; strval[iy]; iy++)
2305 strval[iy] = (strval[iy]==(char)0xff) ? '\0' : strval[iy];
2306
2307 iy = ix; // killough 4/18/98
2308
2309 // Ty 03/14/98 - skip leading spaces
2310 p = strval;
2311 while (*p == ' ') ++p;
2312 // Ty 03/16/98 - change to use a strdup and orphan the original
2313 // Also has the advantage of allowing length changes.
2314 // strncpy(cheat[iy].cheat,p,strlen(cheat[iy].cheat));
2315#if 0
2316 { // killough 9/12/98: disable cheats which are prefixes of this one
2317 int i;
2318 for (i=0; cheat[i].cheat; i++)
2319 if (cheat[i].when & not_deh &&
2320 !strncasecmp(cheat[i].cheat,
2321 cheat[iy].cheat,
2322 strlen(cheat[i].cheat)) && i != iy)
2323 cheat[i].deh_modified = true;
2324 }
2325#endif
2326 cheat[iy].cheat = strdup(p);
2327 if (fpout) fprintf(fpout,
2328 "Assigned new cheat '%s' to cheat '%s'at index %d\n",
2329 p, cheat[ix].deh_cheat, iy); // killough 4/18/98
2330 }
2331 }
2332 if (fpout) fprintf(fpout,"- %s\n",inbuffer);
2333 }
2334 return;
2335}
2336
2337// ====================================================================
2338// deh_procMisc
2339// Purpose: Handle DEH Misc block
2340// Args: fpin -- input file stream
2341// fpout -- output file stream (DEHOUT.TXT)
2342// line -- current line in file to process
2343// Returns: void
2344//
2345static void deh_procMisc(DEHFILE *fpin, FILE* fpout, char *line) // done
2346{
2347 char key[DEH_MAXKEYLEN];
2348 char inbuffer[DEH_BUFFERMAX];
2349 uint_64_t value; // All deh values are ints or longs
2350
2351 strncpy(inbuffer,line,DEH_BUFFERMAX);
2352 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2353 {
2354 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2355 lfstrip(inbuffer);
2356 if (!*inbuffer) break; // killough 11/98
2357 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
2358 {
2359 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2360 continue;
2361 }
2362 // Otherwise it's ok
2363 if (fpout) fprintf(fpout,"Processing Misc item '%s'\n", key);
2364
2365 if (!strcasecmp(key,deh_misc[0])) // Initial Health
2366 initial_health = (int)value;
2367 else
2368 if (!strcasecmp(key,deh_misc[1])) // Initial Bullets
2369 initial_bullets = (int)value;
2370 else
2371 if (!strcasecmp(key,deh_misc[2])) // Max Health
2372 maxhealth = (int)value;
2373 else
2374 if (!strcasecmp(key,deh_misc[3])) // Max Armor
2375 max_armor = (int)value;
2376 else
2377 if (!strcasecmp(key,deh_misc[4])) // Green Armor Class
2378 green_armor_class = (int)value;
2379 else
2380 if (!strcasecmp(key,deh_misc[5])) // Blue Armor Class
2381 blue_armor_class = (int)value;
2382 else
2383 if (!strcasecmp(key,deh_misc[6])) // Max Soulsphere
2384 max_soul = (int)value;
2385 else
2386 if (!strcasecmp(key,deh_misc[7])) // Soulsphere Health
2387 soul_health = (int)value;
2388 else
2389 if (!strcasecmp(key,deh_misc[8])) // Megasphere Health
2390 mega_health = (int)value;
2391 else
2392 if (!strcasecmp(key,deh_misc[9])) // God Mode Health
2393 god_health = (int)value;
2394 else
2395 if (!strcasecmp(key,deh_misc[10])) // IDFA Armor
2396 idfa_armor = (int)value;
2397 else
2398 if (!strcasecmp(key,deh_misc[11])) // IDFA Armor Class
2399 idfa_armor_class = (int)value;
2400 else
2401 if (!strcasecmp(key,deh_misc[12])) // IDKFA Armor
2402 idkfa_armor = (int)value;
2403 else
2404 if (!strcasecmp(key,deh_misc[13])) // IDKFA Armor Class
2405 idkfa_armor_class = (int)value;
2406 else
2407 if (!strcasecmp(key,deh_misc[14])) // BFG Cells/Shot
2408 bfgcells = (int)value;
2409 else
2410 if (!strcasecmp(key,deh_misc[15])) { // Monsters Infight
2411 // e6y: Dehacked support - monsters infight
2412 if (value == 202) monsters_infight = 0;
2413 else if (value == 221) monsters_infight = 1;
2414 else if (fpout) fprintf(fpout,
2415 "Invalid value for 'Monsters Infight': %i", (int)value);
2416
2417 /* No such switch in DOOM - nop */ //e6y ;
2418 } else
2419 if (fpout) fprintf(fpout,
2420 "Invalid misc item string index for '%s'\n",key);
2421 }
2422 return;
2423}
2424
2425// ====================================================================
2426// deh_procText
2427// Purpose: Handle DEH Text block
2428// Notes: We look things up in the current information and if found
2429// we replace it. At the same time we write the new and
2430// improved BEX syntax to the log file for future use.
2431// Args: fpin -- input file stream
2432// fpout -- output file stream (DEHOUT.TXT)
2433// line -- current line in file to process
2434// Returns: void
2435//
2436static void deh_procText(DEHFILE *fpin, FILE* fpout, char *line)
2437{
2438 char key[DEH_MAXKEYLEN];
2439 char inbuffer[DEH_BUFFERMAX*2]; // can't use line -- double size buffer too.
2440 int i; // loop variable
2441 int fromlen, tolen; // as specified on the text block line
2442 int usedlen; // shorter of fromlen and tolen if not matched
2443 boolean found = FALSE; // to allow early exit once found
2444 char* line2 = NULL; // duplicate line for rerouting
2445
2446 // Ty 04/11/98 - Included file may have NOTEXT skip flag set
2447 if (includenotext) // flag to skip included deh-style text
2448 {
2449 if (fpout) fprintf(fpout,
2450 "Skipped text block because of notext directive\n");
2451 strcpy(inbuffer,line);
2452 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2453 dehfgets(inbuffer, sizeof(inbuffer), fpin); // skip block
2454 // Ty 05/17/98 - don't care if this fails
2455 return; // ************** Early return
2456 }
2457
2458 // killough 8/98: allow hex numbers in input:
2459 sscanf(line,"%s %i %i",key,&fromlen,&tolen);
2460 if (fpout) fprintf(fpout,
2461 "Processing Text (key=%s, from=%d, to=%d)\n",
2462 key, fromlen, tolen);
2463
2464 // killough 10/98: fix incorrect usage of feof
2465 {
2466 int c, totlen = 0;
2467 while (totlen < fromlen + tolen && (c = dehfgetc(fpin)) != EOF)
2468 if (c != '\r')
2469 inbuffer[totlen++] = c;
2470 inbuffer[totlen]='\0';
2471 }
2472
2473 // if the from and to are 4, this may be a sprite rename. Check it
2474 // against the array and process it as such if it matches. Remember
2475 // that the original names are (and should remain) uppercase.
2476 // Future: this will be from a separate [SPRITES] block.
2477 if (fromlen==4 && tolen==4)
2478 {
2479 i=0;
2480 while (sprnames[i]) // null terminated list in info.c //jff 3/19/98
2481 { //check pointer
2482 if (!strnicmp(sprnames[i],inbuffer,fromlen)) //not first char
2483 {
2484 if (fpout) fprintf(fpout,
2485 "Changing name of sprite at index %d from %s to %*s\n",
2486 i,sprnames[i],tolen,&inbuffer[fromlen]);
2487 // Ty 03/18/98 - not using strdup because length is fixed
2488
2489 // killough 10/98: but it's an array of pointers, so we must
2490 // use strdup unless we redeclare sprnames and change all else
2491 {
2492 // CPhipps - fix constness problem
2493 char *s;
2494 sprnames[i] = s = strdup(sprnames[i]);
2495
2496 strncpy(s,&inbuffer[fromlen],tolen);
2497 }
2498 found = TRUE;
2499 break; // only one will match--quit early
2500 }
2501 ++i; // next array element
2502 }
2503 }
2504 else
2505 if (fromlen < 7 && tolen < 7) // lengths of music and sfx are 6 or shorter
2506 {
2507 usedlen = (fromlen < tolen) ? fromlen : tolen;
2508 if (fromlen != tolen)
2509 if (fpout) fprintf(fpout,
2510 "Warning: Mismatched lengths from=%d, to=%d, used %d\n",
2511 fromlen, tolen, usedlen);
2512 // Try sound effects entries - see sounds.c
2513 for (i=1; i<NUMSFX; i++)
2514 {
2515 // avoid short prefix erroneous match
2516 if (strlen(S_sfx[i].name) != (size_t)fromlen) continue;
2517 if (!strnicmp(S_sfx[i].name,inbuffer,fromlen))
2518 {
2519 if (fpout) fprintf(fpout,
2520 "Changing name of sfx from %s to %*s\n",
2521 S_sfx[i].name,usedlen,&inbuffer[fromlen]);
2522
2523 S_sfx[i].name = strdup(&inbuffer[fromlen]);
2524 found = TRUE;
2525 break; // only one matches, quit early
2526 }
2527 }
2528 if (!found) // not yet
2529 {
2530 // Try music name entries - see sounds.c
2531 for (i=1; i<NUMMUSIC; i++)
2532 {
2533 // avoid short prefix erroneous match
2534 if (strlen(S_music[i].name) != (size_t)fromlen) continue;
2535 if (!strnicmp(S_music[i].name,inbuffer,fromlen))
2536 {
2537 if (fpout) fprintf(fpout,
2538 "Changing name of music from %s to %*s\n",
2539 S_music[i].name,usedlen,&inbuffer[fromlen]);
2540
2541 S_music[i].name = strdup(&inbuffer[fromlen]);
2542 found = TRUE;
2543 break; // only one matches, quit early
2544 }
2545 }
2546 } // end !found test
2547 }
2548
2549 if (!found) // Nothing we want to handle here--see if strings can deal with it.
2550 {
2551 if (fpout) fprintf(fpout,"Checking text area through strings for '%.12s%s' from=%d to=%d\n",inbuffer, (strlen(inbuffer) > 12) ? "..." : "",fromlen,tolen);
2552 if ((size_t)fromlen <= strlen(inbuffer))
2553 {
2554 line2 = strdup(&inbuffer[fromlen]);
2555 inbuffer[fromlen] = '\0';
2556 }
2557
2558 deh_procStringSub(NULL, inbuffer, line2, fpout);
2559 }
2560 free(line2); // may be NULL, ignored by free()
2561 return;
2562}
2563
2564static void deh_procError(DEHFILE *fpin, FILE* fpout, char *line)
2565{
2566 char inbuffer[DEH_BUFFERMAX];
2567
2568 strncpy(inbuffer,line,DEH_BUFFERMAX);
2569 if (fpout) fprintf(fpout,"Unmatched Block: '%s'\n",inbuffer);
2570 return;
2571}
2572
2573// ====================================================================
2574// deh_procStrings
2575// Purpose: Handle BEX [STRINGS] extension
2576// Args: fpin -- input file stream
2577// fpout -- output file stream (DEHOUT.TXT)
2578// line -- current line in file to process
2579// Returns: void
2580//
2581static void deh_procStrings(DEHFILE *fpin, FILE* fpout, char *line)
2582{
2583 char key[DEH_MAXKEYLEN];
2584 char inbuffer[DEH_BUFFERMAX];
2585 uint_64_t value; // All deh values are ints or longs
2586 char *strval; // holds the string value of the line
2587 static int maxstrlen = 128; // maximum string length, bumped 128 at
2588 // a time as needed
2589 // holds the final result of the string after concatenation
2590 static char *holdstring = NULL;
2591 boolean found = false; // looking for string continuation
2592
2593 if (fpout) fprintf(fpout,"Processing extended string substitution\n");
2594
2595 if (!holdstring) holdstring = malloc(maxstrlen*sizeof(*holdstring));
2596
2597 *holdstring = '\0'; // empty string to start with
2598 strncpy(inbuffer,line,DEH_BUFFERMAX);
2599 // Ty 04/24/98 - have to allow inbuffer to start with a blank for
2600 // the continuations of C1TEXT etc.
2601 while (!dehfeof(fpin) && *inbuffer) /* && (*inbuffer != ' ') */
2602 {
2603 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2604 if (*inbuffer == '#') continue; // skip comment lines
2605 lfstrip(inbuffer);
2606 if (!*inbuffer) break; // killough 11/98
2607 if (!*holdstring) // first one--get the key
2608 {
2609 if (!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2610 {
2611 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2612 continue;
2613 }
2614 }
2615 while (strlen(holdstring) + strlen(inbuffer) > (size_t)maxstrlen) // Ty03/29/98 - fix stupid error
2616 {
2617 // killough 11/98: allocate enough the first time
2618 maxstrlen += strlen(holdstring) + strlen(inbuffer) - maxstrlen;
2619 if (fpout) fprintf(fpout,
2620 "* increased buffer from to %d for buffer size %d\n",
2621 maxstrlen,(int)strlen(inbuffer));
2622 holdstring = realloc(holdstring,maxstrlen*sizeof(*holdstring));
2623 }
2624 // concatenate the whole buffer if continuation or the value iffirst
2625 strcat(holdstring,ptr_lstrip(((*holdstring) ? inbuffer : strval)));
2626 rstrip(holdstring);
2627 // delete any trailing blanks past the backslash
2628 // note that blanks before the backslash will be concatenated
2629 // but ones at the beginning of the next line will not, allowing
2630 // indentation in the file to read well without affecting the
2631 // string itself.
2632 if (holdstring[strlen(holdstring)-1] == '\\')
2633 {
2634 holdstring[strlen(holdstring)-1] = '\0';
2635 continue; // ready to concatenate
2636 }
2637 if (*holdstring) // didn't have a backslash, trap above would catch that
2638 {
2639 // go process the current string
2640 found = deh_procStringSub(key, NULL, holdstring, fpout); // supply keyand not search string
2641
2642 if (!found)
2643 if (fpout) fprintf(fpout,
2644 "Invalid string key '%s', substitution skipped.\n",key);
2645
2646 *holdstring = '\0'; // empty string for the next one
2647 }
2648 }
2649 return;
2650}
2651
2652// ====================================================================
2653// deh_procStringSub
2654// Purpose: Common string parsing and handling routine for DEH and BEX
2655// Args: key -- place to put the mnemonic for the string if found
2656// lookfor -- original value string to look for
2657// newstring -- string to put in its place if found
2658// fpout -- file stream pointer for log file (DEHOUT.TXT)
2659// Returns: boolean: True if string found, false if not
2660//
2661boolean deh_procStringSub(char *key, char *lookfor, char *newstring, FILE *fpout)
2662{
2663 boolean found; // loop exit flag
2664 int i; // looper
2665
2666 found = false;
2667 for (i=0;i<deh_numstrlookup;i++)
2668 {
2669 found = lookfor ?
2670 !stricmp(*deh_strlookup[i].ppstr,lookfor) :
2671 !stricmp(deh_strlookup[i].lookup,key);
2672
2673 if (found)
2674 {
2675 char *t;
2676 *deh_strlookup[i].ppstr = t = strdup(newstring); // orphan originalstring
2677 found = true;
2678 // Handle embedded \n's in the incoming string, convert to 0x0a's
2679 {
2680 const char *s;
2681 for (s=*deh_strlookup[i].ppstr; *s; ++s, ++t)
2682 {
2683 if (*s == '\\' && (s[1] == 'n' || s[1] == 'N')) //found one
2684 ++s, *t = '\n'; // skip one extra for second character
2685 else
2686 *t = *s;
2687 }
2688 *t = '\0'; // cap off the target string
2689 }
2690
2691 if (key)
2692 if (fpout) fprintf(fpout,
2693 "Assigned key %s => '%s'\n",key,newstring);
2694
2695 if (!key)
2696 if (fpout) fprintf(fpout,
2697 "Assigned '%.12s%s' to'%.12s%s' at key %s\n",
2698 lookfor, (strlen(lookfor) > 12) ? "..." : "",
2699 newstring, (strlen(newstring) > 12) ? "..." :"",
2700 deh_strlookup[i].lookup);
2701
2702 if (!key) // must have passed an old style string so showBEX
2703 if (fpout) fprintf(fpout,
2704 "*BEX FORMAT:\n%s = %s\n*END BEX\n",
2705 deh_strlookup[i].lookup,
2706 dehReformatStr(newstring));
2707
2708 break;
2709 }
2710 }
2711 if (!found)
2712 if (fpout) fprintf(fpout,
2713 "Could not find '%.12s'\n",key ? key: lookfor);
2714
2715 return found;
2716}
2717
2718//========================================================================
2719// haleyjd 9/22/99
2720//
2721// deh_procHelperThing
2722//
2723// Allows handy substitution of any thing for helper dogs. DEH patches
2724// are being made frequently for this purpose and it requires a complete
2725// rewiring of the DOG thing. I feel this is a waste of effort, and so
2726// have added this new [HELPER] BEX block
2727
2728static void deh_procHelperThing(DEHFILE *fpin, FILE *fpout, char *line)
2729{
2730 char key[DEH_MAXKEYLEN];
2731 char inbuffer[DEH_BUFFERMAX];
2732 uint_64_t value; // All deh values are ints or longs
2733
2734 strncpy(inbuffer,line,DEH_BUFFERMAX);
2735 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2736 {
2737 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
2738 lfstrip(inbuffer);
2739 if (!*inbuffer) break;
2740 if (!deh_GetData(inbuffer,key,&value,NULL,fpout)) // returns TRUE if ok
2741 {
2742 if (fpout) fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2743 continue;
2744 }
2745 // Otherwise it's ok
2746 if (fpout)
2747 {
2748 fprintf(fpout,"Processing Helper Thing item '%s'\n", key);
2749 fprintf(fpout,"value is %i", (int)value);
2750 }
2751 if (!strncasecmp(key, "type", 4))
2752 HelperThing = (int)value;
2753 }
2754 return;
2755}
2756
2757//
2758// deh_procBexSprites
2759//
2760// Supports sprite name substitutions without requiring use
2761// of the DeHackEd Text block
2762//
2763static void deh_procBexSprites(DEHFILE *fpin, FILE *fpout, char *line)
2764{
2765 char key[DEH_MAXKEYLEN];
2766 char inbuffer[DEH_BUFFERMAX];
2767 uint_64_t value; // All deh values are ints or longs
2768 char *strval; // holds the string value of the line
2769 char candidate[5];
2770 int rover;
2771
2772 if(fpout)
2773 fprintf(fpout,"Processing sprite name substitution\n");
2774
2775 strncpy(inbuffer,line,DEH_BUFFERMAX);
2776
2777 while(!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2778 {
2779 if(!dehfgets(inbuffer, sizeof(inbuffer), fpin))
2780 break;
2781 if(*inbuffer == '#')
2782 continue; // skip comment lines
2783 lfstrip(inbuffer);
2784 if(!*inbuffer)
2785 break; // killough 11/98
2786 if(!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2787 {
2788 if(fpout)
2789 fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2790 continue;
2791 }
2792 // do it
2793 memset(candidate, 0, sizeof(candidate));
2794 strncpy(candidate, ptr_lstrip(strval), 4);
2795 if(strlen(candidate) != 4)
2796 {
2797 if(fpout)
2798 fprintf(fpout, "Bad length for sprite name '%s'\n",
2799 candidate);
2800 continue;
2801 }
2802
2803 rover = 0;
2804 while(deh_spritenames[rover])
2805 {
2806 if(!strncasecmp(deh_spritenames[rover], key, 4))
2807 {
2808 if(fpout)
2809 fprintf(fpout, "Substituting '%s' for sprite '%s'\n",
2810 candidate, deh_spritenames[rover]);
2811
2812 sprnames[rover] = strdup(candidate);
2813 break;
2814 }
2815 rover++;
2816 }
2817 }
2818}
2819
2820// ditto for sound names
2821static void deh_procBexSounds(DEHFILE *fpin, FILE *fpout, char *line)
2822{
2823 char key[DEH_MAXKEYLEN];
2824 char inbuffer[DEH_BUFFERMAX];
2825 uint_64_t value; // All deh values are ints or longs
2826 char *strval; // holds the string value of the line
2827 char candidate[7];
2828 int rover, len;
2829
2830 if(fpout)
2831 fprintf(fpout,"Processing sound name substitution\n");
2832
2833 strncpy(inbuffer,line,DEH_BUFFERMAX);
2834
2835 while(!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2836 {
2837 if(!dehfgets(inbuffer, sizeof(inbuffer), fpin))
2838 break;
2839 if(*inbuffer == '#')
2840 continue; // skip comment lines
2841 lfstrip(inbuffer);
2842 if(!*inbuffer)
2843 break; // killough 11/98
2844 if(!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2845 {
2846 if(fpout)
2847 fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2848 continue;
2849 }
2850 // do it
2851 memset(candidate, 0, 7);
2852 strncpy(candidate, ptr_lstrip(strval), 6);
2853 len = strlen(candidate);
2854 if(len < 1 || len > 6)
2855 {
2856 if(fpout)
2857 fprintf(fpout, "Bad length for sound name '%s'\n",
2858 candidate);
2859 continue;
2860 }
2861
2862 rover = 1;
2863 while(deh_soundnames[rover])
2864 {
2865 if(!strncasecmp(deh_soundnames[rover], key, 6))
2866 {
2867 if(fpout)
2868 fprintf(fpout, "Substituting '%s' for sound '%s'\n",
2869 candidate, deh_soundnames[rover]);
2870
2871 S_sfx[rover].name = strdup(candidate);
2872 break;
2873 }
2874 rover++;
2875 }
2876 }
2877}
2878
2879// ditto for music names
2880static void deh_procBexMusic(DEHFILE *fpin, FILE *fpout, char *line)
2881{
2882 char key[DEH_MAXKEYLEN];
2883 char inbuffer[DEH_BUFFERMAX];
2884 uint_64_t value; // All deh values are ints or longs
2885 char *strval; // holds the string value of the line
2886 char candidate[7];
2887 int rover, len;
2888
2889 if(fpout)
2890 fprintf(fpout,"Processing music name substitution\n");
2891
2892 strncpy(inbuffer,line,DEH_BUFFERMAX);
2893
2894 while(!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2895 {
2896 if(!dehfgets(inbuffer, sizeof(inbuffer), fpin))
2897 break;
2898 if(*inbuffer == '#')
2899 continue; // skip comment lines
2900 lfstrip(inbuffer);
2901 if(!*inbuffer)
2902 break; // killough 11/98
2903 if(!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2904 {
2905 if(fpout)
2906 fprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2907 continue;
2908 }
2909 // do it
2910 memset(candidate, 0, 7);
2911 strncpy(candidate, ptr_lstrip(strval), 6);
2912 len = strlen(candidate);
2913 if(len < 1 || len > 6)
2914 {
2915 if(fpout)
2916 fprintf(fpout, "Bad length for music name '%s'\n",
2917 candidate);
2918 continue;
2919 }
2920
2921 rover = 1;
2922 while(deh_musicnames[rover])
2923 {
2924 if(!strncasecmp(deh_musicnames[rover], key, 6))
2925 {
2926 if(fpout)
2927 fprintf(fpout, "Substituting '%s' for music '%s'\n",
2928 candidate, deh_musicnames[rover]);
2929
2930 S_music[rover].name = strdup(candidate);
2931 break;
2932 }
2933 rover++;
2934 }
2935 }
2936}
2937
2938// ====================================================================
2939// General utility function(s)
2940// ====================================================================
2941
2942// ====================================================================
2943// dehReformatStr
2944// Purpose: Convert a string into a continuous string with embedded
2945// linefeeds for "\n" sequences in the source string
2946// Args: string -- the string to convert
2947// Returns: the converted string (converted in a static buffer)
2948//
2949char *dehReformatStr(char *string)
2950{
2951 static char buff[DEH_BUFFERMAX]; // only processing the changed string,
2952 // don't need double buffer
2953 char *s, *t;
2954
2955 s = string; // source
2956 t = buff; // target
2957 // let's play...
2958
2959 while (*s)
2960 {
2961 if (*s == '\n')
2962 ++s, *t++ = '\\', *t++ = 'n', *t++ = '\\', *t++='\n';
2963 else
2964 *t++ = *s++;
2965 }
2966 *t = '\0';
2967 return buff;
2968}
2969
2970// ====================================================================
2971// lfstrip
2972// Purpose: Strips CR/LF off the end of a string
2973// Args: s -- the string to work on
2974// Returns: void -- the string is modified in place
2975//
2976// killough 10/98: only strip at end of line, not entire string
2977
2978void lfstrip(char *s) // strip the \r and/or \n off of a line
2979{
2980 char *p = s+strlen(s);
2981 while (p > s && (*--p=='\r' || *p=='\n'))
2982 *p = 0;
2983}
2984
2985// ====================================================================
2986// rstrip
2987// Purpose: Strips trailing blanks off a string
2988// Args: s -- the string to work on
2989// Returns: void -- the string is modified in place
2990//
2991void rstrip(char *s) // strip trailing whitespace
2992{
2993 char *p = s+strlen(s); // killough 4/4/98: same here
2994 while (p > s && isspace(*--p)) // break on first non-whitespace
2995 *p='\0';
2996}
2997
2998// ====================================================================
2999// ptr_lstrip
3000// Purpose: Points past leading whitespace in a string
3001// Args: s -- the string to work on
3002// Returns: char * pointing to the first nonblank character in the
3003// string. The original string is not changed.
3004//
3005char *ptr_lstrip(char *p) // point past leading whitespace
3006{
3007 while (isspace(*p))
3008 p++;
3009 return p;
3010}
3011
3012// e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
3013// No more desync on HACX demos.
3014// FIXME!!! (lame)
3015static boolean StrToInt(char *s, long *l)
3016{
3017 return (
3018 (sscanf(s, " 0x%lx", l) == 1) ||
3019 (sscanf(s, " 0X%lx", l) == 1) ||
3020 (sscanf(s, " 0%lo", l) == 1) ||
3021 (sscanf(s, " %ld", l) == 1)
3022 );
3023}
3024
3025// ====================================================================
3026// deh_GetData
3027// Purpose: Get a key and data pair from a passed string
3028// Args: s -- the string to be examined
3029// k -- a place to put the key
3030// l -- pointer to a long integer to store the number
3031// strval -- a pointer to the place in s where the number
3032// value comes from. Pass NULL to not use this.
3033// fpout -- stream pointer to output log (DEHOUT.TXT)
3034// Notes: Expects a key phrase, optional space, equal sign,
3035// optional space and a value, mostly an int but treated
3036// as a long just in case. The passed pointer to hold
3037// the key must be DEH_MAXKEYLEN in size.
3038
3039boolean deh_GetData(char *s, char *k, uint_64_t *l, char **strval, FILE *fpout)
3040{
3041 char *t; // current char
3042 long val; // to hold value of pair
3043 char buffer[DEH_MAXKEYLEN]; // to hold key in progress
3044 // e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
3045 // No more desync on HACX demos.
3046 boolean okrc = 1; // assume good unless we have problems
3047 int i; // iterator
3048
3049 *buffer = '\0';
3050 val = 0; // defaults in case not otherwise set
3051 for (i=0, t=s; *t && i < DEH_MAXKEYLEN; t++, i++)
3052 {
3053 if (*t == '=') break;
3054 buffer[i] = *t; // copy it
3055 }
3056 buffer[--i] = '\0'; // terminate the key before the '='
3057 if (!*t) // end of string with no equal sign
3058 {
3059 okrc = FALSE;
3060 }
3061 else
3062 {
3063 if (!*++t)
3064 {
3065 val = 0; // in case "thiskey =" with no value
3066 okrc = FALSE;
3067 }
3068 // we've incremented t
3069 // e6y: Correction of wrong processing of Bits parameter if its value is equal to zero
3070 // No more desync on HACX demos.
3071 // Old code: e6y val = strtol(t,NULL,0); // killough 8/9/98: allow hex or octal input
3072 if (!StrToInt(t,&val))
3073 {
3074 val = 0;
3075 okrc = 2;
3076 }
3077 }
3078
3079 // go put the results in the passed pointers
3080 *l = val; // may be a faked zero
3081
3082 // if spaces between key and equal sign, strip them
3083 strcpy(k,ptr_lstrip(buffer)); // could be a zero-length string
3084
3085 if (strval != NULL) // pass NULL if you don't want this back
3086 *strval = t; // pointer, has to be somewhere in s,
3087 // even if pointing at the zero byte.
3088
3089 return(okrc);
3090}