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