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