A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita
audio
rust
zig
deno
mpris
rockbox
mpd
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 *
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.
16 *
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.
21 *
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.
26 *
27 * DESCRIPTION:
28 * Dehacked file support
29 * New for the TeamTNT "Boom" engine
30 *
31 * Author: Ty Halderman, TeamTNT
32 *
33 *--------------------------------------------------------------------*/
34
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"
46
47#include <stdio.h> /* sscanf */
48#include "rockmacros.h"
49
50#define TRUE 1
51#define FALSE 0
52
53char* strlwr(char* str)
54{
55 char* p;
56 for (p=str; *p; p++) *p = tolower(*p);
57 return str;
58}
59
60// killough 10/98: new functions, to allow processing DEH files in-memory
61// (e.g. from wads)
62
63typedef struct {
64 const byte *inp; // Pointer to string
65 size_t size; // Bytes remaining in string
66 int fd; // Current file descriptor
67} DEHFILE;
68
69// killough 10/98: emulate IO whether input really comes from a file or not
70
71char *dehfgets(char *buf, size_t n, DEHFILE *fp)
72{
73 char *p;
74
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;
79 }
80
81 n = MIN(fp->size, n);
82
83 if (n == 0 || *fp->inp == '\0') // If no more characters
84 return NULL;
85
86 p = buf;
87
88 while (n-- > 0)
89 {
90 unsigned char c = *fp->inp++;
91 fp->size--;
92
93 if ( c == '\n' )
94 break;
95
96 if ( c != '\r' )
97 *p++ = c;
98 }
99
100 *p = '\0';
101
102 return buf; // Return buffer pointer
103}
104
105int dehfeof(DEHFILE *fp)
106{
107 if (fp->fd >= 0)
108 {
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;
112 }
113
114 return (fp->size <= 0 || *fp->inp == '\0') ? 1 : 0;
115}
116
117int dehfgetc(DEHFILE *fp)
118{
119 if (fp->fd >= 0)
120 {
121 unsigned char c;
122 if (read(fp->fd, &c, 1) == 1)
123 return (unsigned int)c;
124 }
125 else if (fp->size > 0)
126 {
127 return fp->size--, *fp->inp++;
128 }
129
130 return EOF;
131}
132
133
134// variables used in other routines
135boolean deh_pars = FALSE; // in wi_stuff to allow pars in modified games
136
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.
143
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.
149 */
150const char *s_D_DEVSTR = D_DEVSTR;
151const char *s_D_CDROM = D_CDROM;
152const char *s_PRESSKEY = PRESSKEY;
153const char *s_PRESSYN = PRESSYN;
154const char *s_QUITMSG = QUITMSG;
155const char *s_QSAVESPOT = QSAVESPOT; // PRESSKEY;
156const char *s_SAVEDEAD = SAVEDEAD; // PRESSKEY; // remove duplicate y/n
157const char *s_QSPROMPT = QSPROMPT; // PRESSYN;
158const char *s_QLPROMPT = QLPROMPT; // PRESSYN;
159const char *s_NEWGAME = NEWGAME; // PRESSKEY;
160const char *s_RESTARTLEVEL= RESTARTLEVEL; // PRESSYN;
161const char *s_NIGHTMARE = NIGHTMARE; // PRESSYN;
162const char *s_SWSTRING = SWSTRING; // PRESSKEY;
163const char *s_MSGOFF = MSGOFF;
164const char *s_MSGON = MSGON;
165const char *s_NETEND = NETEND; // PRESSKEY;
166const char *s_ENDGAME = ENDGAME; // PRESSYN; // killough 4/4/98: end
167const char *s_DOSY = DOSY;
168const char *s_DETAILHI = DETAILHI;
169const char *s_DETAILLO = DETAILLO;
170const char *s_GAMMALVL0 = GAMMALVL0;
171const char *s_GAMMALVL1 = GAMMALVL1;
172const char *s_GAMMALVL2 = GAMMALVL2;
173const char *s_GAMMALVL3 = GAMMALVL3;
174const char *s_GAMMALVL4 = GAMMALVL4;
175const char *s_EMPTYSTRING = EMPTYSTRING;
176const char *s_GOTARMOR = GOTARMOR;
177const char *s_GOTMEGA = GOTMEGA;
178const char *s_GOTHTHBONUS = GOTHTHBONUS;
179const char *s_GOTARMBONUS = GOTARMBONUS;
180const char *s_GOTSTIM = GOTSTIM;
181const char *s_GOTMEDINEED = GOTMEDINEED;
182const char *s_GOTMEDIKIT = GOTMEDIKIT;
183const char *s_GOTSUPER = GOTSUPER;
184const char *s_GOTBLUECARD = GOTBLUECARD;
185const char *s_GOTYELWCARD = GOTYELWCARD;
186const char *s_GOTREDCARD = GOTREDCARD;
187const char *s_GOTBLUESKUL = GOTBLUESKUL;
188const char *s_GOTYELWSKUL = GOTYELWSKUL;
189const char *s_GOTREDSKULL = GOTREDSKULL;
190const char *s_GOTINVUL = GOTINVUL;
191const char *s_GOTBERSERK = GOTBERSERK;
192const char *s_GOTINVIS = GOTINVIS;
193const char *s_GOTSUIT = GOTSUIT;
194const char *s_GOTMAP = GOTMAP;
195const char *s_GOTVISOR = GOTVISOR;
196const char *s_GOTMSPHERE = GOTMSPHERE;
197const char *s_GOTCLIP = GOTCLIP;
198const char *s_GOTCLIPBOX = GOTCLIPBOX;
199const char *s_GOTROCKET = GOTROCKET;
200const char *s_GOTROCKBOX = GOTROCKBOX;
201const char *s_GOTCELL = GOTCELL;
202const char *s_GOTCELLBOX = GOTCELLBOX;
203const char *s_GOTSHELLS = GOTSHELLS;
204const char *s_GOTSHELLBOX = GOTSHELLBOX;
205const char *s_GOTBACKPACK = GOTBACKPACK;
206const char *s_GOTBFG9000 = GOTBFG9000;
207const char *s_GOTCHAINGUN = GOTCHAINGUN;
208const char *s_GOTCHAINSAW = GOTCHAINSAW;
209const char *s_GOTLAUNCHER = GOTLAUNCHER;
210const char *s_GOTPLASMA = GOTPLASMA;
211const char *s_GOTSHOTGUN = GOTSHOTGUN;
212const char *s_GOTSHOTGUN2 = GOTSHOTGUN2;
213const char *s_PD_BLUEO = PD_BLUEO;
214const char *s_PD_REDO = PD_REDO;
215const char *s_PD_YELLOWO = PD_YELLOWO;
216const char *s_PD_BLUEK = PD_BLUEK;
217const char *s_PD_REDK = PD_REDK;
218const char *s_PD_YELLOWK = PD_YELLOWK;
219const char *s_PD_BLUEC = PD_BLUEC;
220const char *s_PD_REDC = PD_REDC;
221const char *s_PD_YELLOWC = PD_YELLOWC;
222const char *s_PD_BLUES = PD_BLUES;
223const char *s_PD_REDS = PD_REDS;
224const char *s_PD_YELLOWS = PD_YELLOWS;
225const char *s_PD_ANY = PD_ANY;
226const char *s_PD_ALL3 = PD_ALL3;
227const char *s_PD_ALL6 = PD_ALL6;
228const char *s_GGSAVED = GGSAVED;
229const char *s_HUSTR_MSGU = HUSTR_MSGU;
230const char *s_HUSTR_E1M1 = HUSTR_E1M1;
231const char *s_HUSTR_E1M2 = HUSTR_E1M2;
232const char *s_HUSTR_E1M3 = HUSTR_E1M3;
233const char *s_HUSTR_E1M4 = HUSTR_E1M4;
234const char *s_HUSTR_E1M5 = HUSTR_E1M5;
235const char *s_HUSTR_E1M6 = HUSTR_E1M6;
236const char *s_HUSTR_E1M7 = HUSTR_E1M7;
237const char *s_HUSTR_E1M8 = HUSTR_E1M8;
238const char *s_HUSTR_E1M9 = HUSTR_E1M9;
239const char *s_HUSTR_E2M1 = HUSTR_E2M1;
240const char *s_HUSTR_E2M2 = HUSTR_E2M2;
241const char *s_HUSTR_E2M3 = HUSTR_E2M3;
242const char *s_HUSTR_E2M4 = HUSTR_E2M4;
243const char *s_HUSTR_E2M5 = HUSTR_E2M5;
244const char *s_HUSTR_E2M6 = HUSTR_E2M6;
245const char *s_HUSTR_E2M7 = HUSTR_E2M7;
246const char *s_HUSTR_E2M8 = HUSTR_E2M8;
247const char *s_HUSTR_E2M9 = HUSTR_E2M9;
248const char *s_HUSTR_E3M1 = HUSTR_E3M1;
249const char *s_HUSTR_E3M2 = HUSTR_E3M2;
250const char *s_HUSTR_E3M3 = HUSTR_E3M3;
251const char *s_HUSTR_E3M4 = HUSTR_E3M4;
252const char *s_HUSTR_E3M5 = HUSTR_E3M5;
253const char *s_HUSTR_E3M6 = HUSTR_E3M6;
254const char *s_HUSTR_E3M7 = HUSTR_E3M7;
255const char *s_HUSTR_E3M8 = HUSTR_E3M8;
256const char *s_HUSTR_E3M9 = HUSTR_E3M9;
257const char *s_HUSTR_E4M1 = HUSTR_E4M1;
258const char *s_HUSTR_E4M2 = HUSTR_E4M2;
259const char *s_HUSTR_E4M3 = HUSTR_E4M3;
260const char *s_HUSTR_E4M4 = HUSTR_E4M4;
261const char *s_HUSTR_E4M5 = HUSTR_E4M5;
262const char *s_HUSTR_E4M6 = HUSTR_E4M6;
263const char *s_HUSTR_E4M7 = HUSTR_E4M7;
264const char *s_HUSTR_E4M8 = HUSTR_E4M8;
265const char *s_HUSTR_E4M9 = HUSTR_E4M9;
266const char *s_HUSTR_1 = HUSTR_1;
267const char *s_HUSTR_2 = HUSTR_2;
268const char *s_HUSTR_3 = HUSTR_3;
269const char *s_HUSTR_4 = HUSTR_4;
270const char *s_HUSTR_5 = HUSTR_5;
271const char *s_HUSTR_6 = HUSTR_6;
272const char *s_HUSTR_7 = HUSTR_7;
273const char *s_HUSTR_8 = HUSTR_8;
274const char *s_HUSTR_9 = HUSTR_9;
275const char *s_HUSTR_10 = HUSTR_10;
276const char *s_HUSTR_11 = HUSTR_11;
277const char *s_HUSTR_12 = HUSTR_12;
278const char *s_HUSTR_13 = HUSTR_13;
279const char *s_HUSTR_14 = HUSTR_14;
280const char *s_HUSTR_15 = HUSTR_15;
281const char *s_HUSTR_16 = HUSTR_16;
282const char *s_HUSTR_17 = HUSTR_17;
283const char *s_HUSTR_18 = HUSTR_18;
284const char *s_HUSTR_19 = HUSTR_19;
285const char *s_HUSTR_20 = HUSTR_20;
286const char *s_HUSTR_21 = HUSTR_21;
287const char *s_HUSTR_22 = HUSTR_22;
288const char *s_HUSTR_23 = HUSTR_23;
289const char *s_HUSTR_24 = HUSTR_24;
290const char *s_HUSTR_25 = HUSTR_25;
291const char *s_HUSTR_26 = HUSTR_26;
292const char *s_HUSTR_27 = HUSTR_27;
293const char *s_HUSTR_28 = HUSTR_28;
294const char *s_HUSTR_29 = HUSTR_29;
295const char *s_HUSTR_30 = HUSTR_30;
296const char *s_HUSTR_31 = HUSTR_31;
297const char *s_HUSTR_32 = HUSTR_32;
298const char *s_PHUSTR_1 = PHUSTR_1;
299const char *s_PHUSTR_2 = PHUSTR_2;
300const char *s_PHUSTR_3 = PHUSTR_3;
301const char *s_PHUSTR_4 = PHUSTR_4;
302const char *s_PHUSTR_5 = PHUSTR_5;
303const char *s_PHUSTR_6 = PHUSTR_6;
304const char *s_PHUSTR_7 = PHUSTR_7;
305const char *s_PHUSTR_8 = PHUSTR_8;
306const char *s_PHUSTR_9 = PHUSTR_9;
307const char *s_PHUSTR_10 = PHUSTR_10;
308const char *s_PHUSTR_11 = PHUSTR_11;
309const char *s_PHUSTR_12 = PHUSTR_12;
310const char *s_PHUSTR_13 = PHUSTR_13;
311const char *s_PHUSTR_14 = PHUSTR_14;
312const char *s_PHUSTR_15 = PHUSTR_15;
313const char *s_PHUSTR_16 = PHUSTR_16;
314const char *s_PHUSTR_17 = PHUSTR_17;
315const char *s_PHUSTR_18 = PHUSTR_18;
316const char *s_PHUSTR_19 = PHUSTR_19;
317const char *s_PHUSTR_20 = PHUSTR_20;
318const char *s_PHUSTR_21 = PHUSTR_21;
319const char *s_PHUSTR_22 = PHUSTR_22;
320const char *s_PHUSTR_23 = PHUSTR_23;
321const char *s_PHUSTR_24 = PHUSTR_24;
322const char *s_PHUSTR_25 = PHUSTR_25;
323const char *s_PHUSTR_26 = PHUSTR_26;
324const char *s_PHUSTR_27 = PHUSTR_27;
325const char *s_PHUSTR_28 = PHUSTR_28;
326const char *s_PHUSTR_29 = PHUSTR_29;
327const char *s_PHUSTR_30 = PHUSTR_30;
328const char *s_PHUSTR_31 = PHUSTR_31;
329const char *s_PHUSTR_32 = PHUSTR_32;
330const char *s_THUSTR_1 = THUSTR_1;
331const char *s_THUSTR_2 = THUSTR_2;
332const char *s_THUSTR_3 = THUSTR_3;
333const char *s_THUSTR_4 = THUSTR_4;
334const char *s_THUSTR_5 = THUSTR_5;
335const char *s_THUSTR_6 = THUSTR_6;
336const char *s_THUSTR_7 = THUSTR_7;
337const char *s_THUSTR_8 = THUSTR_8;
338const char *s_THUSTR_9 = THUSTR_9;
339const char *s_THUSTR_10 = THUSTR_10;
340const char *s_THUSTR_11 = THUSTR_11;
341const char *s_THUSTR_12 = THUSTR_12;
342const char *s_THUSTR_13 = THUSTR_13;
343const char *s_THUSTR_14 = THUSTR_14;
344const char *s_THUSTR_15 = THUSTR_15;
345const char *s_THUSTR_16 = THUSTR_16;
346const char *s_THUSTR_17 = THUSTR_17;
347const char *s_THUSTR_18 = THUSTR_18;
348const char *s_THUSTR_19 = THUSTR_19;
349const char *s_THUSTR_20 = THUSTR_20;
350const char *s_THUSTR_21 = THUSTR_21;
351const char *s_THUSTR_22 = THUSTR_22;
352const char *s_THUSTR_23 = THUSTR_23;
353const char *s_THUSTR_24 = THUSTR_24;
354const char *s_THUSTR_25 = THUSTR_25;
355const char *s_THUSTR_26 = THUSTR_26;
356const char *s_THUSTR_27 = THUSTR_27;
357const char *s_THUSTR_28 = THUSTR_28;
358const char *s_THUSTR_29 = THUSTR_29;
359const char *s_THUSTR_30 = THUSTR_30;
360const char *s_THUSTR_31 = THUSTR_31;
361const char *s_THUSTR_32 = THUSTR_32;
362const char *s_HUSTR_CHATMACRO1 = HUSTR_CHATMACRO1;
363const char *s_HUSTR_CHATMACRO2 = HUSTR_CHATMACRO2;
364const char *s_HUSTR_CHATMACRO3 = HUSTR_CHATMACRO3;
365const char *s_HUSTR_CHATMACRO4 = HUSTR_CHATMACRO4;
366const char *s_HUSTR_CHATMACRO5 = HUSTR_CHATMACRO5;
367const char *s_HUSTR_CHATMACRO6 = HUSTR_CHATMACRO6;
368const char *s_HUSTR_CHATMACRO7 = HUSTR_CHATMACRO7;
369const char *s_HUSTR_CHATMACRO8 = HUSTR_CHATMACRO8;
370const char *s_HUSTR_CHATMACRO9 = HUSTR_CHATMACRO9;
371const char *s_HUSTR_CHATMACRO0 = HUSTR_CHATMACRO0;
372const char *s_HUSTR_TALKTOSELF1 = HUSTR_TALKTOSELF1;
373const char *s_HUSTR_TALKTOSELF2 = HUSTR_TALKTOSELF2;
374const char *s_HUSTR_TALKTOSELF3 = HUSTR_TALKTOSELF3;
375const char *s_HUSTR_TALKTOSELF4 = HUSTR_TALKTOSELF4;
376const char *s_HUSTR_TALKTOSELF5 = HUSTR_TALKTOSELF5;
377const char *s_HUSTR_MESSAGESENT = HUSTR_MESSAGESENT;
378const char *s_HUSTR_PLRGREEN = HUSTR_PLRGREEN;
379const char *s_HUSTR_PLRINDIGO = HUSTR_PLRINDIGO;
380const char *s_HUSTR_PLRBROWN = HUSTR_PLRBROWN;
381const 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;
386const char *s_AMSTR_FOLLOWON = AMSTR_FOLLOWON;
387const char *s_AMSTR_FOLLOWOFF = AMSTR_FOLLOWOFF;
388const char *s_AMSTR_GRIDON = AMSTR_GRIDON;
389const char *s_AMSTR_GRIDOFF = AMSTR_GRIDOFF;
390const char *s_AMSTR_MARKEDSPOT = AMSTR_MARKEDSPOT;
391const char *s_AMSTR_MARKSCLEARED = AMSTR_MARKSCLEARED;
392// CPhipps - automap rotate & overlay
393const char* s_AMSTR_ROTATEON = AMSTR_ROTATEON;
394const char* s_AMSTR_ROTATEOFF = AMSTR_ROTATEOFF;
395const char* s_AMSTR_OVERLAYON = AMSTR_OVERLAYON;
396const char* s_AMSTR_OVERLAYOFF = AMSTR_OVERLAYOFF;
397const char *s_STSTR_MUS = STSTR_MUS;
398const char *s_STSTR_NOMUS = STSTR_NOMUS;
399const char *s_STSTR_DQDON = STSTR_DQDON;
400const char *s_STSTR_DQDOFF = STSTR_DQDOFF;
401const char *s_STSTR_KFAADDED = STSTR_KFAADDED;
402const char *s_STSTR_FAADDED = STSTR_FAADDED;
403const char *s_STSTR_NCON = STSTR_NCON;
404const char *s_STSTR_NCOFF = STSTR_NCOFF;
405const char *s_STSTR_BEHOLD = STSTR_BEHOLD;
406const char *s_STSTR_BEHOLDX = STSTR_BEHOLDX;
407const char *s_STSTR_CHOPPERS = STSTR_CHOPPERS;
408const char *s_STSTR_CLEV = STSTR_CLEV;
409const char *s_STSTR_COMPON = STSTR_COMPON;
410const char *s_STSTR_COMPOFF = STSTR_COMPOFF;
411const char *s_E1TEXT = E1TEXT;
412const char *s_E2TEXT = E2TEXT;
413const char *s_E3TEXT = E3TEXT;
414const char *s_E4TEXT = E4TEXT;
415const char *s_C1TEXT = C1TEXT;
416const char *s_C2TEXT = C2TEXT;
417const char *s_C3TEXT = C3TEXT;
418const char *s_C4TEXT = C4TEXT;
419const char *s_C5TEXT = C5TEXT;
420const char *s_C6TEXT = C6TEXT;
421const char *s_P1TEXT = P1TEXT;
422const char *s_P2TEXT = P2TEXT;
423const char *s_P3TEXT = P3TEXT;
424const char *s_P4TEXT = P4TEXT;
425const char *s_P5TEXT = P5TEXT;
426const char *s_P6TEXT = P6TEXT;
427const char *s_T1TEXT = T1TEXT;
428const char *s_T2TEXT = T2TEXT;
429const char *s_T3TEXT = T3TEXT;
430const char *s_T4TEXT = T4TEXT;
431const char *s_T5TEXT = T5TEXT;
432const char *s_T6TEXT = T6TEXT;
433const char *s_CC_ZOMBIE = CC_ZOMBIE;
434const char *s_CC_SHOTGUN = CC_SHOTGUN;
435const char *s_CC_HEAVY = CC_HEAVY;
436const char *s_CC_IMP = CC_IMP;
437const char *s_CC_DEMON = CC_DEMON;
438const char *s_CC_LOST = CC_LOST;
439const char *s_CC_CACO = CC_CACO;
440const char *s_CC_HELL = CC_HELL;
441const char *s_CC_BARON = CC_BARON;
442const char *s_CC_ARACH = CC_ARACH;
443const char *s_CC_PAIN = CC_PAIN;
444const char *s_CC_REVEN = CC_REVEN;
445const char *s_CC_MANCU = CC_MANCU;
446const char *s_CC_ARCH = CC_ARCH;
447const char *s_CC_SPIDER = CC_SPIDER;
448const char *s_CC_CYBER = CC_CYBER;
449const char *s_CC_HERO = CC_HERO;
450// Ty 03/30/98 - new substitutions for background textures
451// during int screens
452const char *bgflatE1 = "FLOOR4_8"; // end of DOOM Episode 1
453const char *bgflatE2 = "SFLR6_1"; // end of DOOM Episode 2
454const char *bgflatE3 = "MFLR8_4"; // end of DOOM Episode 3
455const char *bgflatE4 = "MFLR8_3"; // end of DOOM Episode 4
456const char *bgflat06 = "SLIME16"; // DOOM2 after MAP06
457const char *bgflat11 = "RROCK14"; // DOOM2 after MAP11
458const char *bgflat20 = "RROCK07"; // DOOM2 after MAP20
459const char *bgflat30 = "RROCK17"; // DOOM2 after MAP30
460const char *bgflat15 = "RROCK13"; // DOOM2 going MAP15 to MAP31
461const char *bgflat31 = "RROCK19"; // DOOM2 going MAP31 to MAP32
462const char *bgcastcall = "BOSSBACK"; // Panel behind cast call
463
464const char *startup1 = ""; // blank lines are default and are not printed
465const char *startup2 = "";
466const char *startup3 = "";
467const char *startup4 = "";
468const char *startup5 = "";
469
470/* Ty 05/03/98 - externalized
471 * cph - updated for prboom */
472const char *savegamename = "prbmsav";
473
474// end d_deh.h variable declarations
475// ====================================================================
476
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.
481
482// CPhipps - make strings pointed to const
483typedef struct {
484 const char **ppstr; // doubly indirect pointer to string
485 const char *lookup; // pointer to lookup string name
486} deh_strs;
487
488/* CPhipps - const, static
489 * - removed redundant "Can't XXX in a netgame" strings
490 */
491static 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
807 };
808
809static int deh_numstrlookup =
810 sizeof(deh_strlookup)/sizeof(deh_strlookup[0]);
811
812const char *deh_newlevel = "NEWLEVEL"; // CPhipps - const
813
814// DOOM shareware/registered/retail (Ultimate) names.
815// CPhipps - const**const
816const char **const mapnames[] =
817 {
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,
827
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,
837
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,
847
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,
857
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
867 };
868
869// CPhipps - const**const
870const char **const mapnames2[] = // DOOM 2 map names.
871 {
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,
883
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,
893
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,
906 };
907
908// CPhipps - const**const
909const char **const mapnamesp[] = // Plutonia WAD map names.
910 {
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,
922
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,
932
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,
945 };
946
947// CPhipps - const**const
948const char **const mapnamest[] = // TNT WAD map names.
949 {
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,
961
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,
971
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,
984 };
985
986// Function prototypes
987void rstrip(char *); // strip trailing whitespace
988char * ptr_lstrip(char *); // point past leading whitespace
989boolean deh_GetData(char *, char *, uint_64_t *, char **, int );
990boolean deh_procStringSub(char *, char *, char *, int );
991char * dehReformatStr(char *);
992
993// Prototypes for block processing functions
994// Pointers to these functions are used as the blocks are encountered.
995
996void deh_procThing(DEHFILE *, int, char *);
997void deh_procFrame(DEHFILE *, int, char *);
998void deh_procPointer(DEHFILE *, int, char *);
999void deh_procSounds(DEHFILE *, int, char *);
1000void deh_procAmmo(DEHFILE *, int, char *);
1001void deh_procWeapon(DEHFILE *, int, char *);
1002void deh_procSprite(DEHFILE *, int, char *);
1003void deh_procCheat(DEHFILE *, int, char *);
1004void deh_procMisc(DEHFILE *, int, char *);
1005void deh_procText(DEHFILE *, int, char *);
1006void deh_procPars(DEHFILE *, int, char *);
1007void deh_procStrings(DEHFILE *, int, char *);
1008void deh_procError(DEHFILE *, int, char *);
1009void deh_procBexCodePointers(DEHFILE *, int, char *);
1010
1011// Structure deh_block is used to hold the block names that can
1012// be encountered, and the routines to use to decipher them
1013
1014typedef struct
1015{
1016 const char *key; // a mnemonic block code name // CPhipps - const*
1017 void (*const fptr)(DEHFILE *, int, char *); // handler
1018} deh_block;
1019
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 (!)
1025
1026// Put all the block header values, and the function to be called when that
1027// one is encountered, in this array:
1028static 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,
1039
1040 // begin BOOM Extensions (BEX)
1041
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
1046 };
1047
1048// flag to skip included deh-style text, used with INCLUDE NOTEXT directive
1049static boolean includenotext = false;
1050
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
1058
1059static const char *deh_mobjinfo[DEH_MOBJINFOMAX] =
1060 {
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
1085 };
1086
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
1091//
1092// killough 10/98:
1093//
1094// Convert array to struct to allow multiple values, make array size variable
1095
1096#define DEH_MOBJFLAGMAX (sizeof deh_mobjflags/sizeof*deh_mobjflags)
1097
1098struct deh_mobjflags_s {
1099 const char *name; // CPhipps - const*
1100 uint_64_t value;
1101};
1102
1103// CPhipps - static const
1104static 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
1131
1132 // killough 10/98: TRANSLATION consists of 2 bits, not 1:
1133
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)
1149 };
1150
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)
1160
1161static const char *deh_state[] = // CPhipps - static const*
1162 {
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)
1171 };
1172
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.
1179
1180// * sounds are base zero but have a dummy #0
1181
1182static const char *deh_sfxinfo[] = // CPhipps - static const*
1183 {
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
1193 };
1194
1195// MUSICINFO is not supported in Dehacked. Ignored here.
1196// * music entries are base zero but have a dummy #0
1197
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.
1204
1205static const char *deh_sprite[] = // CPhipps - static const*
1206 {
1207 "Offset" // supposed to be the offset into the text section
1208 };
1209#endif
1210
1211// AMMO - Dehacked block name = "Ammo"
1212// usage = Ammo n (name)
1213// Ammo information for the few types of ammo
1214
1215static const char *deh_ammo[] = // CPhipps - static const*
1216 {
1217 "Max ammo", // maxammo[]
1218 "Per ammo" // clipammo[]
1219 };
1220
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.
1224
1225static const char *deh_weapon[] = // CPhipps - static const*
1226 {
1227 "Ammo type", // .ammo
1228 "Deselect frame", // .upstate
1229 "Select frame", // .downstate
1230 "Bobbing frame", // .readystate
1231 "Shooting frame", // .atkstate
1232 "Firing frame" // .flashstate
1233 };
1234
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
1239//
1240// killough 4/18/98: integrated into main cheat table now (see st_stuff.c)
1241
1242// MISC - Dehacked block name = "Misc"
1243// Usage: Misc 0
1244// Always uses a zero in the dehacked file, for consistency. No meaning.
1245
1246static const char *deh_misc[] = // CPhipps - static const*
1247 {
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
1266 };
1267
1268// TEXT - Dehacked block name = "Text"
1269// Usage: Text fromlen tolen
1270// Dehacked allows a bit of adjustment to the length (why?)
1271
1272// BEX extension [CODEPTR]
1273// Usage: Start block, then each line is:
1274// FRAME nnn = PointerMnemonic
1275
1276// External references to action functions scattered about the code
1277
1278extern void A_Light0();
1279extern void A_WeaponReady();
1280extern void A_Lower();
1281extern void A_Raise();
1282extern void A_Punch();
1283extern void A_ReFire();
1284extern void A_FirePistol();
1285extern void A_Light1();
1286extern void A_FireShotgun();
1287extern void A_Light2();
1288extern void A_FireShotgun2();
1289extern void A_CheckReload();
1290extern void A_OpenShotgun2();
1291extern void A_LoadShotgun2();
1292extern void A_CloseShotgun2();
1293extern void A_FireCGun();
1294extern void A_GunFlash();
1295extern void A_FireMissile();
1296extern void A_Saw();
1297extern void A_FirePlasma();
1298extern void A_BFGsound();
1299extern void A_FireBFG();
1300extern void A_BFGSpray();
1301extern void A_Explode();
1302extern void A_Pain();
1303extern void A_PlayerScream();
1304extern void A_Fall();
1305extern void A_XScream();
1306extern void A_Look();
1307extern void A_Chase();
1308extern void A_FaceTarget();
1309extern void A_PosAttack();
1310extern void A_Scream();
1311extern void A_SPosAttack();
1312extern void A_VileChase();
1313extern void A_VileStart();
1314extern void A_VileTarget();
1315extern void A_VileAttack();
1316extern void A_StartFire();
1317extern void A_Fire();
1318extern void A_FireCrackle();
1319extern void A_Tracer();
1320extern void A_SkelWhoosh();
1321extern void A_SkelFist();
1322extern void A_SkelMissile();
1323extern void A_FatRaise();
1324extern void A_FatAttack1();
1325extern void A_FatAttack2();
1326extern void A_FatAttack3();
1327extern void A_BossDeath();
1328extern void A_CPosAttack();
1329extern void A_CPosRefire();
1330extern void A_TroopAttack();
1331extern void A_SargAttack();
1332extern void A_HeadAttack();
1333extern void A_BruisAttack();
1334extern void A_SkullAttack();
1335extern void A_Metal();
1336extern void A_SpidRefire();
1337extern void A_BabyMetal();
1338extern void A_BspiAttack();
1339extern void A_Hoof();
1340extern void A_CyberAttack();
1341extern void A_PainAttack();
1342extern void A_PainDie();
1343extern void A_KeenDie();
1344extern void A_BrainPain();
1345extern void A_BrainScream();
1346extern void A_BrainDie();
1347extern void A_BrainAwake();
1348extern void A_BrainSpit();
1349extern void A_SpawnSound();
1350extern void A_SpawnFly();
1351extern void A_BrainExplode();
1352extern void A_Detonate(); // killough 8/9/98
1353extern void A_Mushroom(); // killough 10/98
1354extern void A_Die(); // killough 11/98
1355extern void A_Spawn(); // killough 11/98
1356extern void A_Turn(); // killough 11/98
1357extern void A_Face(); // killough 11/98
1358extern void A_Scratch(); // killough 11/98
1359extern void A_PlaySound(); // killough 11/98
1360extern void A_RandomJump(); // killough 11/98
1361extern void A_LineEffect(); // killough 11/98
1362
1363typedef 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;
1368
1369static const deh_bexptr deh_bexptrs[] = // CPhipps - static const
1370 {
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
1455
1456 // This NULL entry must be the last in the list
1457 {NULL, "A_NULL"}, // Ty 05/16/98
1458 };
1459
1460// to hold startup code pointers from INFO.C
1461// CPhipps - static
1462static actionf_t deh_codeptr[NUMSTATES];
1463
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
1470//
1471// killough 10/98:
1472// substantially modified to allow input from wad lumps instead of .deh files.
1473
1474void ProcessDehFile(const char *filename, const char *outfilename, int lumpnum)
1475{
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
1479
1480 // Open output file if we're writing output
1481 if (outfilename && *outfilename && fileout < 0)
1482 {
1483 static boolean firstfile = true; // to allow append to output log
1484 if (strcmp(outfilename, "-"))
1485 {
1486 fileout = open(outfilename, firstfile ? O_WRONLY | O_CREAT :
1487 O_WRONLY | O_APPEND, 0666);
1488 if (fileout < 0)
1489 {
1490 printf( "Could not open -dehout file %s\n... using stdout.\n",
1491 outfilename);
1492 }
1493 }
1494 firstfile = false;
1495 }
1496
1497 // killough 10/98: allow DEH files to come from wad lumps
1498 if (filename)
1499 {
1500 if ((infile.fd = open(filename,O_RDONLY)) < 0)
1501 {
1502 printf( "-deh file %s not found\n",filename);
1503 return; // should be checked up front anyway
1504 }
1505 infile.inp = NULL;
1506 }
1507 else // DEH file comes from lump indicated by third argument
1508 {
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)";
1514 }
1515
1516 printf("Loading DEH file %s\n",filename);
1517 if (fileout >= 0)
1518 fdprintf(fileout,"\nLoading DEH file %s\n\n",filename);
1519
1520 {
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;
1524 }
1525
1526 // loop until end of file
1527
1528 while (dehfgets(inbuffer,sizeof(inbuffer),filein))
1529 {
1530 unsigned int i;
1531
1532 if (fileout >= 0)
1533 fdprintf(fileout,"Line='%s'\n",inbuffer);
1534
1535 if (!*inbuffer || *inbuffer == '#' || *inbuffer == ' ')
1536 continue; /* Blank line or comment line */
1537
1538 // -- If DEH_BLOCKMAX is set right, the processing is independently
1539 // -- handled based on data in the deh_blocks[] structure array
1540
1541 // killough 10/98: INCLUDE code rewritten to allow arbitrary nesting,
1542 // and to greatly simplify code, fix memory leaks, other bugs
1543
1544 if (!strncasecmp(inbuffer,"INCLUDE",7)) // include a file
1545 {
1546 // preserve state while including a file
1547 // killough 10/98: moved to here
1548
1549 char *nextfile;
1550 boolean oldnotext = includenotext; // killough 10/98
1551
1552 // killough 10/98: exclude if inside wads (only to discourage
1553 // the practice, since the code could otherwise handle it)
1554
1555 if (infile.inp)
1556 {
1557 if (fileout >= 0)
1558 fdprintf(fileout,
1559 "No files may be included from wads: %s\n",
1560 inbuffer);
1561 continue;
1562 }
1563
1564 // check for no-text directive, used when including a DEH
1565 // file but using the BEX format to handle strings
1566
1567 if (!strncasecmp(nextfile = ptr_lstrip(inbuffer+7),"NOTEXT",6))
1568 includenotext = true, nextfile = ptr_lstrip(nextfile+6);
1569
1570 if (fileout >= 0)
1571 fdprintf(fileout,"Branching to include file %s...\n", nextfile);
1572
1573 // killough 10/98:
1574 // Second argument must be NULL to prevent closing fileout too soon
1575
1576 ProcessDehFile(nextfile,NULL,0); // do the included file
1577
1578 includenotext = oldnotext;
1579 if (fileout >= 0)
1580 fdprintf(fileout,"...continuing with %s\n",filename);
1581 continue;
1582 }
1583
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
1592 }
1593 }
1594
1595 if (infile.inp)
1596 {
1597 W_UnlockLumpNum(lumpnum); // Mark purgable
1598 }
1599
1600 if (infile.fd >= 0)
1601 {
1602 close(infile.fd); // Close real file
1603 infile.fd = -1;
1604 }
1605
1606 if (fileout >= 0)
1607 {
1608 close(fileout);
1609 fileout = -1;
1610 }
1611}
1612
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
1620//
1621void deh_procBexCodePointers(DEHFILE *fpin, int fpout, char *line)
1622{
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
1629
1630 // Ty 05/16/98 - initialize it to something, dummy!
1631 strncpy(inbuffer,line,DEH_BUFFERMAX);
1632
1633 // for this one, we just read 'em until we hit a blank line
1634 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1635 {
1636 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1637 if (!*inbuffer) break; // killough 11/98: really exit on blank line
1638
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
1642 {
1643 if (fpout) fdprintf(fpout,
1644 "Invalid BEX codepointer line - must start with 'FRAME': '%s'\n",
1645 inbuffer);
1646 return; // early return
1647 }
1648
1649 if (fpout) fdprintf(fpout,"Processing pointer at index %d: %s\n",
1650 indexnum, mnemonic);
1651 if (indexnum < 0 || indexnum >= NUMSTATES)
1652 {
1653 if (fpout) fdprintf(fpout,"Bad pointer number %d of %d\n",
1654 indexnum, NUMSTATES);
1655 return; // killough 10/98: fix SegViol
1656 }
1657 strcpy(key,"A_"); // reusing the key area to prefix the mnemonic
1658 strcat(key,ptr_lstrip(mnemonic));
1659
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
1663 {
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;
1672 }
1673 } while (!found && (deh_bexptrs[i].cptr != NULL));
1674
1675 if (!found)
1676 if (fpout) fdprintf(fpout,
1677 "Invalid frame pointer mnemonic '%s' at %d\n",
1678 mnemonic, indexnum);
1679 }
1680 return;
1681}
1682
1683//---------------------------------------------------------------------------
1684// To be on the safe, compatible side, we manually convert DEH bitflags
1685// to prboom types - POPE
1686//---------------------------------------------------------------------------
1687uint_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,
1720 0,
1721 0
1722 };
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;
1729 }
1730 return convertedBits;
1731}
1732
1733//---------------------------------------------------------------------------
1734// See usage below for an explanation of this function's existence - POPE
1735//---------------------------------------------------------------------------
1736void 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;
1765 }
1766}
1767
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
1775//
1776// Ty 8/27/98 - revised to also allow mnemonics for
1777// bit masks for monster attributes
1778//
1779
1780void deh_procThing(DEHFILE *fpin, int fpout, char *line)
1781{
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;
1788
1789 strncpy(inbuffer,line,DEH_BUFFERMAX);
1790 if (fpout) fdprintf(fpout,"Thing line: '%s'\n",inbuffer);
1791
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);
1795
1796 // Note that the mobjinfo[] array is base zero, but object numbers
1797 // in the dehacked file start with one. Grumble.
1798 --indexnum;
1799
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
1803
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 != ' '))
1807 {
1808 if (!dehfgets(inbuffer, sizeof(inbuffer), fpin)) break;
1809
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
1813 {
1814 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1815 continue;
1816 }
1817 for (ix=0; ix<DEH_MOBJINFOMAX; ix++) {
1818 if (strcasecmp(key,deh_mobjinfo[ix])) continue;
1819
1820 if (strcasecmp(key,"bits")) {
1821 // standard value set
1822
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);
1832 }
1833 else {
1834 // bit set
1835 if (value) { // proff
1836 value = getConvertedDEHBits(value);
1837 mobjinfo[indexnum].flags = value;
1838 }
1839 else {
1840 // figure out what the bits are
1841 value = 0;
1842
1843 // killough 10/98: replace '+' kludge with strtok() loop
1844 // Fix error-handling case ('found' var wasn't being reset)
1845 //
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
1856 );
1857 }
1858 value |= deh_mobjflags[iy].value;
1859 break;
1860 }
1861 if (iy >= DEH_MOBJFLAGMAX && fpout) {
1862 fdprintf(fpout, "Could not find bit mnemonic %s\n", strval);
1863 }
1864 }
1865
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
1872 );
1873 }
1874 }
1875 }
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
1881 );
1882 }
1883 }
1884 }
1885 return;
1886}
1887
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
1895//
1896void deh_procFrame(DEHFILE *fpin, int fpout, char *line)
1897{
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;
1902
1903 strncpy(inbuffer,line,DEH_BUFFERMAX);
1904
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);
1910
1911 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
1912 {
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
1916 {
1917 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1918 continue;
1919 }
1920 if (!strcasecmp(key,deh_state[0])) // Sprite number
1921 {
1922 if (fpout) fdprintf(fpout," - sprite = %ld\n",(long)value);
1923 states[indexnum].sprite = (spritenum_t)value;
1924 }
1925 else
1926 if (!strcasecmp(key,deh_state[1])) // Sprite subnumber
1927 {
1928 if (fpout) fdprintf(fpout," - frame = %ld\n",(long)value);
1929 states[indexnum].frame = (long)value; // long
1930 }
1931 else
1932 if (!strcasecmp(key,deh_state[2])) // Duration
1933 {
1934 if (fpout) fdprintf(fpout," - tics = %ld\n",(long)value);
1935 states[indexnum].tics = (long)value; // long
1936 }
1937 else
1938 if (!strcasecmp(key,deh_state[3])) // Next frame
1939 {
1940 if (fpout) fdprintf(fpout," - nextstate = %ld\n",(long)value);
1941 states[indexnum].nextstate = (statenum_t)value;
1942 }
1943 else
1944 if (!strcasecmp(key,deh_state[4])) // Codep frame (not set in Frame deh block)
1945 {
1946 if (fpout) fdprintf(fpout," - codep, should not be set in Frame section!\n");
1947 /* nop */ ;
1948 }
1949 else
1950 if (!strcasecmp(key,deh_state[5])) // Unknown 1
1951 {
1952 if (fpout) fdprintf(fpout," - misc1 = %ld\n",(long)value);
1953 states[indexnum].misc1 = (long)value; // long
1954 }
1955 else
1956 if (!strcasecmp(key,deh_state[6])) // Unknown 2
1957 {
1958 if (fpout) fdprintf(fpout," - misc2 = %ld\n",(long)value);
1959 states[indexnum].misc2 = (long)value; // long
1960 }
1961 else
1962 if (fpout) fdprintf(fpout,"Invalid frame string index for '%s'\n",key);
1963 }
1964 return;
1965}
1966
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
1974//
1975void deh_procPointer(DEHFILE *fpin, int fpout, char *line) // done
1976{
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
1982
1983 strncpy(inbuffer,line,DEH_BUFFERMAX);
1984 // NOTE: different format from normal
1985
1986 // killough 8/98: allow hex numbers in input, fix error case:
1987 if (sscanf(inbuffer,"%*s %*d (%s %d)",key, &indexnum) != 2)
1988 {
1989 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
1990 return;
1991 }
1992
1993 if (fpout) fdprintf(fpout,"Processing Pointer at index %d: %s\n",indexnum, key);
1994 if (indexnum < 0 || indexnum >= NUMSTATES)
1995 {
1996 if (fpout)
1997 fdprintf(fpout,"Bad pointer number %d of %d\n",indexnum, NUMSTATES);
1998 return;
1999 }
2000
2001 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2002 {
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
2006 {
2007 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2008 continue;
2009 }
2010
2011 if ((signed)value < 0 || value >= NUMSTATES)
2012 {
2013 if (fpout)
2014 fdprintf(fpout,"Bad pointer number %lld of %d\n",value, NUMSTATES);
2015 return;
2016 }
2017
2018 if (!strcasecmp(key,deh_state[4])) // Codep frame (not set in Frame deh block)
2019 {
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++)
2025 {
2026 if (!memcmp(&deh_bexptrs[i].cptr,&deh_codeptr[value],sizeof(actionf_t)))
2027 {
2028 if (fpout) fdprintf(fpout,"BEX [CODEPTR] -> FRAME %d = %s\n",
2029 indexnum, &deh_bexptrs[i].lookup[2]);
2030 break;
2031 }
2032 }
2033 }
2034 else
2035 if (fpout) fdprintf(fpout,"Invalid frame pointer index for '%s' at %lld\n",
2036 key, value);
2037 }
2038 return;
2039}
2040
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
2048//
2049void deh_procSounds(DEHFILE *fpin, int fpout, char *line)
2050{
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;
2055
2056 strncpy(inbuffer,line,DEH_BUFFERMAX);
2057
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);
2065
2066 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2067 {
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
2071 {
2072 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2073 continue;
2074 }
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 *)((intptr_t) 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 *) ((intptr_t) 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);
2104 }
2105 return;
2106}
2107
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
2115//
2116void deh_procAmmo(DEHFILE *fpin, int fpout, char *line)
2117{
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;
2122
2123 strncpy(inbuffer,line,DEH_BUFFERMAX);
2124
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);
2132
2133 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2134 {
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
2138 {
2139 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2140 continue;
2141 }
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);
2149 }
2150 return;
2151}
2152
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
2160//
2161void deh_procWeapon(DEHFILE *fpin, int fpout, char *line)
2162{
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;
2167
2168 strncpy(inbuffer,line,DEH_BUFFERMAX);
2169
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);
2177
2178 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2179 {
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
2183 {
2184 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2185 continue;
2186 }
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);
2206 }
2207 return;
2208}
2209
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
2217//
2218void deh_procSprite(DEHFILE *fpin, int fpout, char *line) // Not supported
2219{
2220 char key[DEH_MAXKEYLEN];
2221 char inbuffer[DEH_BUFFERMAX];
2222 int indexnum;
2223
2224 // Too little is known about what this is supposed to do, and
2225 // there are better ways of handling sprite renaming. Not supported.
2226
2227 strncpy(inbuffer,line,DEH_BUFFERMAX);
2228
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 != ' '))
2234 {
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);
2239 }
2240 return;
2241}
2242
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
2250//
2251void deh_procPars(DEHFILE *fpin, int fpout, char *line) // extension
2252{
2253 char key[DEH_MAXKEYLEN];
2254 char inbuffer[DEH_BUFFERMAX];
2255 int indexnum;
2256 int episode, level, partime, oldpar;
2257
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]
2268
2269 strncpy(inbuffer,line,DEH_BUFFERMAX);
2270
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 != ' '))
2277 {
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);
2286 }
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)
2291 {
2292 if (fpout) fdprintf(fpout,"Invalid MAPnn value MAP%d\n",level);
2293 }
2294 else
2295 {
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;
2300 }
2301 }
2302 }
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)
2311 {
2312 if (fpout) fdprintf(fpout,
2313 "Invalid ExMx values E%dM%d\n",episode, level);
2314 }
2315 else
2316 {
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;
2323 }
2324 }
2325 }
2326 return;
2327}
2328
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
2336//
2337void deh_procCheat(DEHFILE *fpin, int fpout, char *line) // done
2338{
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
2349
2350 if (fpout) fdprintf(fpout,"Processing Cheat: %s\n",line);
2351
2352 strncpy(inbuffer,line,DEH_BUFFERMAX);
2353 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2354 {
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
2358 {
2359 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2360 continue;
2361 }
2362 // Otherwise we got a (perhaps valid) cheat name,
2363 // so look up the key in the array
2364
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
2368 {
2369 if (!stricmp(key,cheat[ix].deh_cheat)) // found the cheat, ignored case
2370 {
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];
2377
2378 iy = ix; // killough 4/18/98
2379
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;
2395 }
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
2401 }
2402 }
2403 if (fpout) fdprintf(fpout,"- %s\n",inbuffer);
2404 }
2405 return;
2406*/
2407}
2408
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
2416//
2417void deh_procMisc(DEHFILE *fpin, int fpout, char *line) // done
2418{
2419 char key[DEH_MAXKEYLEN];
2420 char inbuffer[DEH_BUFFERMAX];
2421 uint_64_t value; // All deh values are ints or longs
2422
2423 strncpy(inbuffer,line,DEH_BUFFERMAX);
2424 while (!dehfeof(fpin) && *inbuffer && (*inbuffer != ' '))
2425 {
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
2429 {
2430 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2431 continue;
2432 }
2433 // Otherwise it's ok
2434 if (fpout) fdprintf(fpout,"Processing Misc item '%s'\n", key);
2435
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);
2486 }
2487 return;
2488}
2489
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
2500//
2501void deh_procText(DEHFILE *fpin, int fpout, char *line)
2502{
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
2510
2511 // Ty 04/11/98 - Included file may have NOTEXT skip flag set
2512 if (includenotext) // flag to skip included deh-style text
2513 {
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
2521 }
2522
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);
2528
2529 // killough 10/98: fix incorrect usage of feof
2530 {
2531 int c, totlen = 0;
2532 while (totlen < fromlen + tolen && (c = dehfgetc(fpin)) != EOF)
2533 inbuffer[totlen++] = c;
2534 inbuffer[totlen]='\0';
2535 }
2536
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)
2542 {
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
2547 {
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
2552
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
2555 {
2556 // CPhipps - fix constness problem
2557 char *s;
2558 sprnames[i] = s = strdup(sprnames[i]);
2559
2560 strncpy(s,&inbuffer[fromlen],tolen);
2561 }
2562 found = TRUE;
2563 break; // only one will match--quit early
2564 }
2565 ++i; // next array element
2566 }
2567 }
2568 else
2569 if (fromlen < 7 && tolen < 7) // lengths of music and sfx are 6 or shorter
2570 {
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++)
2578 {
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))
2582 {
2583 if (fpout) fdprintf(fpout,
2584 "Changing name of sfx from %s to %*s\n",
2585 S_sfx[i].name,usedlen,&inbuffer[fromlen]);
2586
2587 S_sfx[i].name = strdup(&inbuffer[fromlen]);
2588 found = TRUE;
2589 break; // only one matches, quit early
2590 }
2591 }
2592 if (!found) // not yet
2593 {
2594 // Try music name entries - see sounds.c
2595 for (i=1; i<NUMMUSIC; i++)
2596 {
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))
2600 {
2601 if (fpout) fdprintf(fpout,
2602 "Changing name of music from %s to %*s\n",
2603 S_music[i].name,usedlen,&inbuffer[fromlen]);
2604
2605 S_music[i].name = strdup(&inbuffer[fromlen]);
2606 found = TRUE;
2607 break; // only one matches, quit early
2608 }
2609 }
2610 } // end !found test
2611 }
2612
2613 if (!found) // Nothing we want to handle here--see if strings can deal with it.
2614 {
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))
2617 {
2618 line2 = strdup(&inbuffer[fromlen]);
2619 inbuffer[fromlen] = '\0';
2620 }
2621
2622 deh_procStringSub(NULL, inbuffer, line2, fpout);
2623 }
2624 free(line2); // may be NULL, ignored by free()
2625 return;
2626}
2627
2628void deh_procError(DEHFILE *fpin, int fpout, char *line)
2629{
2630 (void)fpin;
2631 char inbuffer[DEH_BUFFERMAX];
2632
2633 strncpy(inbuffer,line,DEH_BUFFERMAX);
2634 if (fpout) fdprintf(fpout,"Unmatched Block: '%s'\n",inbuffer);
2635 return;
2636}
2637
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
2645//
2646void deh_procStrings(DEHFILE *fpin, int fpout, char *line)
2647{
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
2657
2658 if (fpout) fdprintf(fpout,"Processing extended string substitution\n");
2659
2660 if (!holdstring) holdstring = malloc(maxstrlen*sizeof(*holdstring));
2661
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 != ' ') */
2667 {
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
2672 {
2673 if (!deh_GetData(inbuffer,key,&value,&strval,fpout)) // returns TRUE if ok
2674 {
2675 if (fpout) fdprintf(fpout,"Bad data pair in '%s'\n",inbuffer);
2676 continue;
2677 }
2678 }
2679 while (strlen(holdstring) + strlen(inbuffer) > (size_t)maxstrlen) // Ty03/29/98 - fix stupid error
2680 {
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));
2687 }
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] == '\\')
2697 {
2698 holdstring[strlen(holdstring)-1] = '\0';
2699 continue; // ready to concatenate
2700 }
2701 if (*holdstring) // didn't have a backslash, trap above would catch that
2702 {
2703 // go process the current string
2704 found = deh_procStringSub(key, NULL, holdstring, fpout); // supply keyand not search string
2705
2706 if (!found)
2707 if (fpout) fdprintf(fpout,
2708 "Invalid string key '%s', substitution skipped.\n",key);
2709
2710 *holdstring = '\0'; // empty string for the next one
2711 }
2712 }
2713 return;
2714}
2715
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
2724//
2725boolean deh_procStringSub(char *key, char *lookfor, char *newstring, int fpout)
2726{
2727 boolean found; // loop exit flag
2728 int i; // looper
2729
2730 found = false;
2731 for (i=0;i<deh_numstrlookup;i++)
2732 {
2733 found = lookfor ?
2734 !strcasecmp(*deh_strlookup[i].ppstr,lookfor) :
2735 !strcasecmp(deh_strlookup[i].lookup,key);
2736
2737 if (found)
2738 {
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
2743 {
2744 const char *s;
2745 for (s=*deh_strlookup[i].ppstr; *s; ++s, ++t)
2746 {
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;
2751 }
2752 *t = '\0'; // cap off the target string
2753 }
2754
2755 if (key)
2756 if (fpout) fdprintf(fpout,
2757 "Assigned key %s => '%s'\n",key,newstring);
2758
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);
2765
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));
2771
2772 break;
2773 }
2774 }
2775 if (!found)
2776 if (fpout) fdprintf(fpout,
2777 "Could not find '%s'\n",key ? key: lookfor);
2778
2779 return found;
2780}
2781
2782// ====================================================================
2783// General utility function(s)
2784// ====================================================================
2785
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)
2792//
2793char *dehReformatStr(char *string)
2794{
2795 static char buff[DEH_BUFFERMAX]; // only processing the changed string,
2796 // don't need double buffer
2797 char *s, *t;
2798
2799 s = string; // source
2800 t = buff; // target
2801 // let's play...
2802
2803 while (*s)
2804 {
2805 if (*s == '\n')
2806 ++s, *t++ = '\\', *t++ = 'n', *t++ = '\\', *t++='\n';
2807 else
2808 *t++ = *s++;
2809 }
2810 *t = '\0';
2811 return buff;
2812}
2813
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
2819//
2820void rstrip(char *s) // strip trailing whitespace
2821{
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';
2825}
2826
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.
2833//
2834char *ptr_lstrip(char *p) // point past leading whitespace
2835{
2836 while (isspace(*p))
2837 p++;
2838 return p;
2839}
2840
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.
2854
2855boolean deh_GetData(char *s, char *k, uint_64_t *l, char **strval, int fpout)
2856{
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
2863
2864 *buffer = '\0';
2865 val = 0; // defaults in case not otherwise set
2866 for (i=0, t=s; *t && i < DEH_MAXKEYLEN; t++, i++)
2867 {
2868 if (*t == '=') break;
2869 buffer[i] = *t; // copy it
2870 }
2871 if (i == 0) i = 1; /* Just in case */
2872 buffer[--i] = '\0'; // terminate the key before the '='
2873 if (!*t) // end of string with no equal sign
2874 {
2875 okrc = FALSE;
2876 }
2877 else
2878 {
2879 if (!*++t)
2880 {
2881 val = 0; // in case "thiskey =" with no value
2882 okrc = FALSE;
2883 }
2884 // we've incremented t
2885 val = atoi(t);//strtol(t,NULL,0); // killough 8/9/98: allow hex or octal input
2886 }
2887
2888 // go put the results in the passed pointers
2889 *l = val; // may be a faked zero
2890
2891 // if spaces between key and equal sign, strip them
2892 strcpy(k,ptr_lstrip(buffer)); // could be a zero-length string
2893
2894 if (strval != NULL) // pass NULL if you don't want this back
2895 *strval = t; // pointer, has to be somewhere in s,
2896 // even if pointing at the zero byte.
2897
2898 return(okrc);
2899}