d_deh.c 114 KB

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