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