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