home *** CD-ROM | disk | FTP | other *** search
- "Hacking the DOOM.EXE file"
-
- by Matt Fell (matt.burnett@acebbs.com)
- June 13, 1994
- ===========================================================================
-
- Many of the characteristics of the DOOM environment are determined by the
- data in the DOOM.WAD file: the maps data, the picture data, the sounds, etc.
- Almost all of this has been explained in the Unofficial DOOM Specs. But
- there is also a host of variables and possibilities in the DOOM.EXE file,
- and in this article I will explain all I know about it. I'll probably
- include a new chapter in the 1.4 specs, to contain this info. This is kind
- of a trial run...
- Many simple variables can be changed in the manner that the classic
- "HOCKEY" wad does it - by using the HACK.EXE program to patch doom.exe
- in the specified places. I once thought I would write a program that would
- enable easy editing of the "thing table" described below, for such cool
- effects as invisble Barons and floating imps. But I never did finish it.
- I get distracted easily :-), also I just love letting others do all the
- real work :-).
- I freely mix hex and decimal numbers below. Hopefully you can tell from
- the context :-). All of this refers to the registered version 1.2 DOOM.EXE
- file. When 1.4 comes out, I'll need to change the numbers, obviously. Some
- of the data could be located by using search patterns, since much of it
- doesn't change from version to version. But using the actual numbers is
- probably better, although less flexible.
- By far, the most possibilities are in the thing table, but I included
- just about the entireity of my notes, for completeness' sake. I'm compiling
- a list of ideas of what can be done by patching the exe, please contribute
- your thoughts! Example: reduce the damage done by the missles, for longer
- deathmatch battles. Another example: the entries in the thing table for
- demons and spectres are IDENTICAL except for the bit that makes spectres
- "inviso". Suppose one replaces the numbers for the "grey tree" with the
- numbers from the "Baron"'s entry, and change the invisible bit. Then one
- would have ADDED another monster, an invisible Baron, without having "taken
- away" the original non-inviso Baron. Of course, one would no longer have
- grey trees :-). I would really like to be able to expand the size of the
- thing table, the frame table, and the sprite name list, but I have looked
- for the appropriate pointers in vain. If someone could figure this out...
- Also, please report any interesting results gained by experimenting,
- any errors, etc. Thanks.
-
- The data begins at $6f414 (455700) and continues to the end of the file,
- $8db27 (580391). Here's an overview of the sections:
-
- start length what
-
- 6f414 3d30 TEXT STRINGS
- 73412 1a34 various unknowns, probably to do with I/O, sound, mouse, etc.
- 74bf8 10000 looks like hard-coded math tables, for speed?
- 84bf8 148 misc.
- 84d40 82 gamma correction messages
- 84dc2 280 "are you sure you want to quit" messages
- 85042 3a2 MENUS (new game, load game, etc.)
- 853e4 140 ?
- 85524 36c configuration options and defaults, like in DEFAULT.CFG
- 85890 174 ?
- 85a04 60 ?
- 85a64 54 ?
- 85ab8 c4 ?
- 85b7c 20 max ammo at start, and ammo per thing
- 85b9c c0 ammo type and frame #s for the weapons
- 85c5c 188 ANIMATED WALLS and FLOORS
- 85de4 258 SWITCH-WALLS
- 8603c c0 ?
- 860fc d4 ?
- 861d0 500 5 colormaps for use with the gamma correction setting 0-4
- 866e4 fc ?
- 867e0 40 pointers to chatmacros, "Green:", etc.
- 86820 88 pointers to level names, used on Automap
- 868a8 d8 splat mark coordinates for end-level screen
- 86980 5a8 wimap patch animations for end-level screen
- 86f28 224 SONG NAMES list of pointers
- 8714c 8b8 SOUND TABLE
- 87a04 1a4 SPRITE NAMES list of pointers
- 87ba8 3800 FRAME TABLE
- 8b3a8 20 ?
- 8b3c8 2368 THING TABLE
- 8d730 3fd ?
-
- For readable lists of the TEXT STRINGS, THING TABLE, FRAME TABLE,
- SPRITE NAMES, and SOUND TABLE, see the accompanying (or appended below)
- Qbasic programs DEHACK. Instead of distributing a few hundred k of text
- files, I decided to use simple programs that you can run to get the same
- lists and tables that I use. Why Qbasic? Because everyone who has dos has
- it, and if you don't, you're smart enough to write little programs yourself.
- This is one of the things I need feedback on - should I include these
- mini-programs in the chapter in the 1.4 specs? Or should I just have the
- descriptions and offset numbers, as below?
- Unless noted differently, "integer" means a 4-byte integer.
-
- 6f414
- START OF DATA. Several times I'll refer to pointers. All these pointers
- are integers. Add the values of these pointers to $6f414 and you'll get the
- location of what's being pointed to.
- Note: there's also at least one other kind of pointer in here, with larger
- values, that seem to point to a location in the code, NOT the data. I call
- these "code-pointers" for now. I know it's a lame term.
-
- 6f414
- TEXT STRINGS. They all start on 4-byte boundaries, i.e. at xxxx0/4/8/c.
- $00 ends the string. Then the next one starts at the next boundary, so a 4
- byte string is followed by $00, then 3 bytes of random junk, then the next
- string. The first string is 01 01 01, then "ULTRADIR", and so on. See
- DEHACK1.BAS for a program to extract a list of all the text strings,
- DEHACK1.TXT will be about 72k.
-
- 73140
- I think this is the last string, "TZ"
-
- 73144
- Misc. stuff I haven't investigated. Some of it has to do with sound card
- stuff and mice and joysticks, because at 7384c is "DMXGUS.INI" and at 74ba8
- are pointers which point to the strings "None", "PC_Speaker", "Adlib", etc.
-
- 74bf8
- 64k of precisely ordered numbers, which leads me to believe they are
- pre-calculated math tables, to speed up some floating point operations
- used in the screen draw routine. Any other guesses?
-
- 84bfc
- 3 pointers to the episode 1/2/3 end texts, "Once you beat...", "You've
- done it...", and "The loathsome Spiderdemon is dead..."
-
- 84c24
- pointer to the string "doom.wad"
-
- 84c74
- pointer to the string "default.cfg"
-
- 84c78
- 8 integers: 1, 25, 50, 24, 40, 640, 1280, 320
-
- 84c98
- 2 code-pointers
-
- 84ccc
- 29 integers, with values like 90 and 135 and 180. Angles?
-
- 84d40
- "Gamma correction OFF", 00s, "Gamma correction level 1", ... 4. Each
- occupies $1a bytes.
-
- 84dc2
- 8 text messages used to confirm quitting, each uses $50 bytes
-
- 85042
- MENUS. I know this controls to some extent which menu pictures are used
- for which menu, but I haven't figured it all out yet.
-
- 853e4
- 14 ints: 42, 22, 23, 24, 28, 29, 31, 40, zeros
-
- 8541c
- 256 bytes, values from 00-ff, no two the same, "random" order.
-
- 85524
- The configuration options. Each is 5 integers: a pointer to a string,
- like "mouse_sensitivity", a code-pointer, the default value for that
- option, a 0 or 1 (1 for all the "key_" options), and a 0. It would be
- pretty dense to do anything with this, I think.
-
- 85890
- About 117 integers, with a definite structure, but I can't figure it
- out, and changing/experimenting seems to do nothing.
-
- 85a64
- 21 sets of 4 bytes: 0, 0, 1, 0, 320, 168, "33", 0, 1, $(b2 26 26 2e),
- $(ff 63 fd ff), a pointer that points to the $(b2...), 0, 1, "ema", 0, 0,
- 1, 0, 1, "xma". All these are unchanged from version 0.99 through 1.2,
- except the pointer obviously.
-
- 85ab8
- Ints: 0, -1, -1, 0, 0, 0, 0, 4, 7, 10, 12, 14, 15, 15, 0, 0, 112, 96, 64,
- 176, then 16 that are members of this set {-65536, -47000, 0, 47000, 65536},
- then 4, 5, 6, 7, 0, 1, 2, 3, 8, 3, 1, 5, 7
-
- 85b7c
- AMMO AMOUNTS. 8 integers: 200, 50, 300, 50, 10, 4, 20, 1. The first four
- are the maximum initial capacity for ammo, shells, cells, and rockets. The
- backpack doubles these amounts. The second four are how many ammo in a
- clip, shells, rockets/rocket, and cells/cell item. Boxes have 5x as much.
-
- 859bc
- AMMO TABLE. 8 sets of 6 integers:
-
- Punch 5 4 3 2 5 0
- Pistol 0 12 11 10 13 17
- Shotgun 1 20 19 18 21 30
- Chaingun 0 34 33 32 35 38
- Laucher 3 42 41 40 43 46
- Plasma 2 59 58 57 60 62
- BFG 2 66 65 64 67 71
- Chainsaw 5 53 52 50 54 0
-
- The first number of each set is the ammo type. Type 5 never runs out. The
- next three numbers are 3 frame #s (see the FRAME TABLE below) for the pics
- displayed when moving while holding that weapon. You know, the "bobbing
- weapon" effect? Fifth is the first frame of the "shoot" sequence for that
- weapon, and last is the first frame of the "firing" sequence. The "firing"
- pics are the ones that are lit up, fire coming out, etc.
-
- 85c5c
- ANIMATED WALLS and FLOORS. Each is 26 bytes: an integer, a 8-byte string,
- $00, a 8-byte string, $00, and a final int.
-
- 0 NUKAGE3 NUKAGE1 8
- 0 FWATER4 FWATER1 8
- 0 SWATER4 SWATER1 8
- 0 LAVA4 LAVA1 8
- 0 BLOOD4 BLOOD1 8
- 1 BLODGR4 BLODGR1 8
- 1 SLADRIP4 SLADRIP1 8
- 1 BLODRIP4 BLODRIP1 8
- 1 FIREWALL FIREWALA 8
- 1 GSTFONT3 GSTFONT1 8
- 1 FIRELAVA FIRELAV3 8
- 1 FIREBLU2 FIREBLU1 8
- 1 ROCKRED3 ROCKRED1 8
-
- Obviously the 0/1 means floor or wall. The first string is the name of
- the animation cycle's LAST listed texture, the second string is the FIRST
- listed texture. The cycle includes them and all entries between them in
- whichever wad file is in effect (It doesn't have to be DOOM.WAD, a pwad
- with new TEXTURE1 and 2 resources works quite nicely. I'm doing it myself,
- for my levels). The final 08 doesn't seem to mean much.
-
- 85dc8
- A -1 then a bunch of zeros, maybe space for another animation cycle?
-
- 85de4
- SWITCH WALL NAMES. Each is 20 bytes: an 8-byte string, 00, another string,
- 00, and a 2-byte integer. There are 28 switches here, from (SW1BRCOM
- SW2BRCOM 1) to (SW1WOOD SW2WOOD 2). When a switch is pulled, the game
- checks to see if the wall texture is on this list. If it is, it changes
- the wall texture to the corresponding alternate texture. The 2-byte integer
- 1 or 2 tells it to look in either TEXTURE1 or TEXTURE2.
-
- 86028
- 20 zeros, again, room for one more?
-
- 8603c
- 48 integers: 3 0 2 1 3 0 2 0 3 1 2 0 0 0 0 0
- 2 0 2 1 0 0 0 0 3 1 3 0 0 0 0 0
- 2 0 3 1 2 1 3 1 2 1 3 0 0 0 0 0
-
- 860fc
- 50 integers, all are either 50 or -50.
-
- 861d0
- 5 sets of 256 bytes, each is a COLORMAP, for the gamma correction
- settings OFF, 1, 2, 3, 4.
-
- 866d0
- 5 integers: 1, 0, -1, 0, 0
-
- 866e4
- 13 sets of 5 - 10 bytes, each set terminated by a $FF
-
- 8675e
- $74 $20
-
- 86760
- 13 pointers to the stuff at 866e4. An integer '0' between each pointer.
-
- 867c8
- 6 integers: -1, -1, 0, -1, 0, 1
-
- 867e0
- 10 pointers to the 10 default chatmacros, then 4 pointers, to "Green:",
- "Indigo:", "Brown:", "Red:"
-
- 86820
- AUTOMAP LEVEL NAMES. 27 pointers to the level names used on the automap.
-
- 8689c
- The ascii letters "gibr" - the keys for sending messages in multiplayer.
-
- 868a8
- SPLAT MARK COORDINATES. At what screen coordinates to place the WISPLAT
- picture on the end-level screen, for th 27 levels. 54 integers, 27 pairs.
- e1m1 x, e1m1 y, ..., e3m9 y.
-
- 86980, 86bb0, 86da8
- END-LEVEL MAP ANIMATIONS. Each is 14 integers. The first one is (0, 11,
- 3, 224, 104, 0, 0, 0, 0, 0, 0, 0, 0, 0). The first number is 0 for all the
- ones on maps 0 and 2 (episodes 1 and 3), and it's 2 for map 1. The 11 is
- always 11 except the last one of map 2 is 8. The 3 means 3 pictures are
- involved in the animation, e.g WIA00100, WIA00101, and WIA00102. 224 and 104
- are the x and y coordinates. The sixth number is not 0 for map 1 - it's
- from 1 to 8. This controls the way the Tower of Mystery "appears". All the
- other numbers are always 0.
-
- 86ef8
- Three integers, how many animations for WIMAP0, 1, 2 respectively.
-
- 86f04
- Three pointers, to the starts of the animations for WIMAP0, 1, 2
- respectively.
-
- 8714c
- SOUND TABLE. 61 and 1/2 sounds are listed here. Each is 9 integers: a
- pointer to the string which is the sound's "name", then a 0 or 1, then
- a value ranging from 32 to 128, then 0, -1, -1, 0, 0, 0. The names are
- "pistol", "shotgn", ... "hoof", "metal", "chgun". Prefix DS or DP and you
- get the entries in DOOM.WAD for the sound data. The "chgun" is the 1/2 -
- there's no "DSCHGUN" in doom.wad, and the entry in this table is incomplete
- anyway, lacking the all-important 0, -1, -1, 0, 0, 0 ending :-). There seem
- to be a few glitches in the way the sounds were fit into the whole scheme,
- this is just one of them. See DEHACK5.BAS for how to extract the whole
- table and list of sound names
-
- 879ec
- pointer to start of SOUND TABLE.
-
- 879f0
- Integer = 150. 150 whats?
-
- 87a04
- SPRITE NAME LIST. 105 pointers to the strings "TROO", "SHTG", ...,
- "SMRT". See DEHACK4.BAS to extract the whole list.
-
- 87ba8
- FRAME TABLE. 512 entries, each is 28 bytes:
-
- longint sprite number 0-104, lookup in sprite name list pointers
- longint sprite subnumber, 0 = "A", 1 = "B", in for example, SMRTA0.
- longint duration, how many timeslices until it looks for the next
- frame in the sequence. -1 means forever.
- 2-byte int ?
- 2-byte int ?
- longint next frame in sequence. 0 means no next frame, sequence done.
- longint always 0, has no effect
- longint always 0
-
- See DEHACK3.BAS to extract the whole table
-
- 8b3a8
- Two integers: 1, 0, then 6 code-pointers.
-
- 8b3c8
- THING TABLE. 103 entries, each is 88 bytes, or 21 integers. See
- DEHACK2.BAS to extract the table. Here's a list of what the 21 ints do:
-
- 1. Thing number. 3001 is an imp, 5 is a blue key, etc. Some of them are
- -1, e.g. the very first entry (players), the fireballs, ...
- 2. First frame number of the thing's frame sequence, for 'regular' items.
- For monsters, it's the first frame of the standing-in-place sequence.
- 3. Toughness/hit points.
- 4. 'moving' first frame #, monsters/player only
- 5. 'see player' sound # for monsters, or 'first' sound for projectiles.
- Note the sounds are 1-61, not 0-60. 0 indicates no sound.
- 6. Always 8, except for player. What does it do?
- 7. 'attack' sound #, monsters only.
- 8. 'injury' first frame #, monsters/player only.
- 9. ???. monsters/player only.
- 10. 'pain' sound #, monsters/player only.
- 11. 'close attack' frame #, monsters/player.
- 12. 'distance attack' frame #, monsters/player.
- 13. 'death' frame # for monsters, 'explode' frame # for projectiles.
- 14. 'explosive death' frame #, only PLAY, POSS, SPOS, TROO are this weak.
- 15. 'death' sound # for monsters, 'explode' sound # for projectiles.
- 16. Speed of movement. Projectiles' speeds are * 65536 (or split this
- into two 2-byte integers.
- 17. Horizontal size * 65536
- 18. Height * 65536
- 19. Point value? Not implemented.
- 20. Missle damage. Also, SKUL has a 3 here, I presume it turns into a
- projectile when attacking.
- 21. 'act' sound #, monsters.
- 22. Attributes, controlled by bits. Bit set = condition true. bit0 =
- 1/0, bit8 = 256/0, bit16 = 65536/0, ...
-
- bit0 a gettable thing
- bit1 an obstacle to players and monsters (but not projectiles)
- bit2 can be hurt (note barrels have this set)
- bit3 ? teleport destination is only one with it set
- bit4 'automatics' like PUFF, TFOG, BLUD, projectiles
- bit5-7 unused?
- bit8 hung from ceiling
- bit9 floating monsters and not-on-ground things
- bit10 projectiles and player
- bit11 ? player only
- bit12-13 unused?
- bit14 floating monsters
- bit15 unused?
- bit16 projectiles
- bit17 unused?
- bit18 'Inviso' like Spectres!
- bit19 ? barrel only
- bit20-21 unused?
- bit22 Monster: counts towards KILL % at end-of-level screen
- bit23 Artifact: counts towards ITEM %
- bit24 unused?
- bit25 the 6 keys and the player
- bit26-31 unused?
-
- 8d730
- Misc junk I can't figure out.
-
- 8db27
- End of doom.exe
-