----------------------------------------------------------------------------- T H E U N O F F I C I A L *-D-*-*-O-*-*-O-*-*-M-* S P E C S Release v1.1 - February 19, 1994 Written by: Matt Fell (matt.burnett@acebbs.com) Released by: Hank Leukart (ap641@cleveland.freenet.edu) "DOOM: Where hackers gnaw the bones left from the banquet of data prepared by the mighty wizards of id." "The poets talk about love, but what I talk about is DOOM, because in the end, DOOM is all that counts." - Alex Machine/George Stark/Stephen King, _The Dark Half_ ----------------------------------------------------------------------------- ---------- DISCLAIMER ---------- These specs are to aid in informing the public about the game DOOM, by id Software. In no way should this promote your killing yourself, killing others, or killing in any other fashion. Additionally, neither Hank Leukart nor Matt Fell claim ANY responsibility regarding ANY illegal activity concerning this file, or indirectly related to this file. The information contained in this file only reflects id Software indirectly, and questioning id Software regarding any information in this file is not recommended. --------- COPYRIGHT --------- You may NOT distribute this work by any non-electronic media, including but not limited to books, newsletters, magazines, manuals, catalogs, and speech. You may NOT distribute this work in electronic magazines, or within computer software without prior written explicit permission. These rights are temporary and revocable upon written, oral, or other notice by Hank Leukart. This copyright notice shall be governed by the laws of the state of Ohio. If you would like additional rights beyond those granted above, write to the distributor at "ap641@cleveland.freenet.edu" on the Internet. ------------ INTRODUCTION ------------ Here are the long awaited unofficial specs for DOOM. These specs should be used for creating add-on software for the game. I would like to request that these specs be used in making utilities that ONLY work on the registered version of DOOM. You may not use these for modifing, translating, disassembling, decompiling, reverse engineering, or creating derivative works based upon DOOM. Notwithstanding the foregoing, you may create a map editor, modify maps and make your own maps (collectively referenced as the "Permitted Derivative Works") for the Software. You may not sell or distribute any Permitted Derivative Works but you may exchange the Permitted Derivative Works at no charge amongst other end-users. I do not understand much of what is contained in this file, so if you have any questions about the information, write to Matt Fell at "matt.burnett@acebbs.com" on the Internet. If you would like to request a copy of this file, or have any questions about its distribution, write to me, Hank Leukart, at "ap641@cleveland.freenet.edu" on the Internet. -------------------- (LONG) AUTHOR'S NOTE -------------------- This document is a summary and explanation of almost all the data structures in the DOOM.WAD file. ALMOST all. The structure of the NODES/SSECTOR/SEGS objects is apparent, but their exact purpose is proving elusive. Everything else is fairly easy. Thankfully, there is no compression or encryption used, that would really complicate things. All of this information is true to the best of my knowledge at this time, which means that there's certainly a few things in here which are WRONG! So here's the obligatory reminder to back up your DOOM.WAD file and any other files you intend to change, unless you enjoy re-installing the whole package [ Hope you have 11 megs just lying around :-) ]. If you aren't experienced with programming and/or data structures, you probably shouldn't be fooling around anyway. And remember, id Software will NOT give technical support for modifications. Whatever you do, do NOT distribute any data extracted from the original doom.wad file. It is COPYRIGHTED. This includes pictures, sounds, and the original maps. I don't know about the technicality of it, but I'm also, especially, referring to distributing changed versions of the original maps. E.g. you change one or two of the items on a level, or you move some walls around. Great! But don't distribute it! It's still THEIR level. As far as I can determine at this point in time, here is the preferred method of handling third-party additions: If you are writing a utility that will operate on DOOM, have it first check the WAD file for the existence of an "E3M1" entry in the directory (explained below), or some other entry that will only be in the registered version. If you are going to be distributing a modified map, plan on using the -file parameter. At the command line, the user will type DOOM -DEVPARM -FILE yourfile.wad (in addition to any other command line parameters they are using). This causes doom to use any resources in the "yourfile.wad" instead of the originals in the "doom.wad" file. Thus, if you only make one level (good luck on even making one!), you can distribute a wad file which will be very small compared to the full wad file. Your external wad file for a single level would have just eleven entries in its directory. When doom loads, the doom OS will say "adding external file (whatever).wad" Call your file something like JOELEVEL.WAD or XMENRULE.WAD; if you use a name like E1M1.WAD or E3M6.WAD or probably any real name from the real directory, it will either not work, or lock-up. By the way, I've known most of this info for weeks now, but have been "sitting" on it for various reasons....And if you like difficult levels oriented towards combat and thinking, remember me. When I get good enough tools, I guarantee I will make some interesting levels. The desire to create levels is what really got me started on this whole thing; my resume includes some critically acclaimed levels for wolf and spear. If you have any comments, or even better, possible additions, please send me e-mail. Questions will be gladly answered also, no matter how trivial, unless I get too many, which I doubt. Please note, however, that if it's not in here, I'm either working on it or I just don't know it. If YOU know "it", tell me! -------- CONTENTS -------- [1] Basics [2] Directory Overview [3] The Maps, The Levels [3-1] ExMy [3-2] THINGS [3-2-1] Thing Types [3-3] LINEDEFS [3-3-1] Linedef Attributes [3-3-2] Linedef Types [3-4] SIDEDEFS [3-5] VERTEXES [3-6] SEGS [3-7] SSECTORS [3-8] NODES [3-9] SECTORS [3-10] REJECT [3-11] BLOCKMAP [4] Pictures' Format [4-1] Headers [4-2] Pointers [4-3] Pixel Data [5] Floor and Ceiling Textures [6] Songs and Sounds [6-1] Songs [6-2] Sounds [7] Miscellaneous Non-Picture Resources [7-1] PLAYPAL [7-2] COLORMAP [7-3] DEMOs [7-4] TEXTURE1 and TEXTURE2 [7-5] PNAMES ------------------- CHAPTER [1]: Basics ------------------- The first twelve bytes of a *.WAD file are as follows: Bytes 0 to 3 - contain the ASCII letters "IWAD" may also contain "PWAD", which will give the "modified game" message during the Doom OS startup. Therefore, I recommend that all modified WAD files have PWAD instead of IWAD. I have been unable to find out what ID thinks about this, they are so busy... Bytes 4 to 7 - contain a long integer which is the number of entries in the "directory" Bytes 8 to 11 - contain a pointer to the first byte of the "directory" (Bytes 12 to the start of the directory contain resource data) The directory referred to is a list, located at the end of the WAD file, which contains the pointers, lengths, and names of all the resources in the WAD file. The resources in the wad: item pictures, enemies' pictures for animation, wall patches, floor and ceiling textures, songs, sound effects, map data, and many others. Specifically, the first 12 bytes of the DOOM.WAD file in version 1.1, which I am working with, are: 49 57 41 44 1a 08 00 00 be 20 9e 00 This is "IWAD", then 81a hex (=2074 decimal) for the number of directory entries, then 9e20be (=10363070 decimal) for the first byte of the directory. Each directory entry is 16 bytes long, arranged this way: First four bytes: pointer to start of resource (a long integer) Next four bytes: length of resource (another long integer) Last eight bytes: name of resource, in ASCII capitals, ending with 00s if less than eight bytes. ------------------------------- CHAPTER [2]: Directory Overview ------------------------------- PLAYPAL contains fourteen 256 color palettes, used while playing Doom. COLORMAP maps colors in the palette down to darker ones, for areas of less than maximum brightness (quite a few of these places, huh?) ENDOOM is the text message displayed when you exit to DOS. DEMO[1-3] are the demos which will play if you just sit and watch. E1M1 etc, to E3M9, along with its 10 subsequent entries, defines the map data for a single level or mission. More on this below. TEXTURE1 is a list of wall type names used in the SIDEDEF portion of each level's data, and their composition data, i.e. what wall patches make up each "meta-wall". TEXTURE2 contains the walls that are only in the registered version. PNAMES is the list of wall patches, which are referenced by number in the TEXTURE1/2 objects. GENMIDI has some instrument names in it, and obviously has to do with the MIDI mappings used for the songs...? DMXGUS has to do with Gravis Ultra Sound, I suppose. D_xxxxxx is a song DP_xxxxx DP and DS come in pairs and are the sound effects. DS_xxxxx DP_ are the PC speaker sounds, DS_ are the sound card sounds. all the remaining entries in the directory, except the floor textures at the end, and the "separators" like S_START, refer to resources which are pictures in the doom/wad picture format described in chapter 6. I could've listed here what every single one of them is, e.g. WIMSTBP3 is text "FOUR" in grey, but I figured it to be a waste of time. HELP[1-2] These are full screen (320 by 200 pixel) pictures. TITLEPIC CREDIT VICTORY2 PFUB[1-2] END[0-6] "THE END" text, with 0 to 6 bullet holes. AMMNUM[0-9] are the grey digits used in the status bar for ammo count. STxxxxxx are small pictures and text used on the status bar. M_xxxxxx are text messages (yes, in picture format), used in the menus. BRDR_xxx are tiny two pixel wide pictures use to frame the viewing window when it is not full screen. WIxxxxxx are pictures and messages used on the summary screen done after the completion of a level. WIMAP[0-2] are full screen, 320 by 200. S_START has 0 length and is right before the item/enemy section S_END is immediately after the last "frame" P_START the beginning of the wall patches P1_START before the first of the shareware wall patches P1_END after the last of the shareware wall patches P2_START before the first of the registered wall patches P2_END before the first of the registered wall patches P_END the end of the wall patches F_START the beginnning of the floors F1_START before the first shareware floor texture F1_END after the last shareware floor texture F2_START before the first registered floor texture F2_END after the last registered floor texture F_END the end of the floors And that's the end of the directory. Detailed info on specific resources follows... --------------------------------- CHAPTER [3]: The Maps, The Levels --------------------------------- Each level has eleven resources/directory entries: E[x]M[y] (where x is a single digit 1-3 for the episode number and y is 1-9 for the mission/level #),THINGS, LINEDEFS, SIDEDEFS, VERTEXES, SEGS, SSECTORS, NODES, SECTORS, REJECT, BLOCKMAP. [3-1]: ExMy =========== This is just the name resource for a (single) level, and has zero length. The next 10 entries in the directory after one of these must be THINGS...BLOCKMAP. [3-2]: THINGS ============= Each thing is ten bytes, consisting of five (integer) fields: 1. X coordinate of thing 2. Y coordinate of thing Each level has a different "range" to its coordinates. On E1M1, X ranges from (c.) -288 to +3440, and Y ranges from (c.) -4832 to -2144. On the automap within the game, with the grid on (press 'G'), the lines are hex 80 (decimal 128) apart, two lines = hex 100, dec 256. 3. Angle the thing faces, 0 is west (according to automap). May be 0,45,90,135,180,225,270,315. Only important for enemies. 4. Type of thing, see next subsection 5. Attributes of thing, which are set by bits: bit 0 is set if the THING is present at skill 1 and 2 bit 1 is set if the THING is on skill 3 (hurt me plenty) bit 2 is set if the THING is on skill 4 (ultra-violence) bit 3 is set to indicate a deaf guard. This only has meaning for enemies, who will not attack until they see a player if they are "deaf". Otherwise, they will activate when they hear gunshots, etc. Sound does not travel through solid walls (walls that are solid at the time of the noise). bit 4 makes the THING only appear in multiplayer mode. bits 5-15 are never set in any THING , and have no effect. The skill settings are most used with the ENEMIES, of course...the most common skill level settings are hex 07/0f (on all skills), 06/0e (on skill 3-4), and 04/0c (only on skill 4). [3-2-1]: Thing Types -------------------- Bytes 6-7 of each thing are an integer which means the thing at that x,y location is one of these: 1 Player 1 start 2 Player 2 start 3 Player 3 start 4 Player 4 start 5 Blue keycard 6 Yellow keycard 7 SPIDER BOSS (SPID) 8 Backpack 9 FORMER HUMAN SERGEANT (SPOS) 10 Bloody mess 11 The possible start positions for players in deathmatch mode. There must be at least FOUR 11s on each level. 12 Bloody mess 2 13 Red Keycard 14 Marks the spot where a player (or enemy) lands when they teleport to the SECTOR that contains this thing. 15 Dead player 16 CYBER-BOSS (CYBR) 17 Cell charge pack 18 Dead former human 19 Dead former sargeant 20 Dead imp 21 Dead demon 22 Dead cacodemon 23 ? 24 Pool of blood 25 Impaled human 26 Twitching impaled human 27 Skulltop pole 28 Head shishkebob 29 Pile of skulls with candle 30 Tall green pillar 31 Short green pillar 32 Tall red pillar 33 Short red pillar 34 Candle 35 Candelabra 36 Pedestal w/heart 37 Short red pillar with skull 38 Red skullkey 39 Yellow skullkey 40 Blue skullkey 41 Eye in symbol 42 Flaming skull-rock 43 Grey tree 44 Tall blue firestick 45 Tall green firestick 46 Tall red firestick 47 Small brown scrub 48 Tall, techno column 49 Swaying body 50 Hung by ankle, arms out 51 Hanging 1-legged human 52 Hanging torso 53 Severed Leg 54 Large brown tree 55 Short blue firestick 56 Short green firestick 57 Short red firestick 58 SPECTRE (SARG) 59 Hanging torso 60 Severed leg 61 Hanging 1-legged human 62 Hung by ankle, arms out 63 Swaying body 2001 Shotgun 2002 Chaingun 2003 Rocket launcher 2004 Plasma gun 2005 Chainsaw 2006 BFG9000 2007 Ammo clip 2008 4 shotgun shells 2010 1 rocket 2011 Stimpak 2012 Medikit 2013 Soulsphere = +100% health 2014 Health bonus 2015 Armor bonus 2018 Green armor 100% 2019 Blue armor 200% 2022 Invlnerability 2023 Berserk Strength 2024 Invisibility 2025 Radiation suit 2026 Computer map 2028 Floor lamp 2035 Barrel 2045 Lite goggles 2046 Box of Rockets 2047 Cell charge 2048 Box of Ammo 2049 Box of Shells 3001 IMP (TROO) 3002 DEMON (SARG) 3003 GOAT BOSS (BOSS) 3004 FORMER HUMAN (POSS) 3005 CACODEMON (HEAD) 3006 LOST SOUL (SKUL) [3-3]: LINEDEFS =============== Each linedef represents a line from one of the VERTEXES to another, and each has 7 (integer) fields: 1. from the VERTEX with this number (the first vertex is 0) 2. to the VERTEX with this number (31 is the 32nd vertex) 3. attributes, see below 4. types, see below 5. is a "trigger" number which ties crossing this line to the SECTOR with this same number as its last field. 6. SIDEDEF one (always present, since this line adjoins at least 1 SECTOR) 7. SIDEDEF two, if this line adjoins 2 SECTORS [3-3-1]: Linedef Attributes --------------------------- The third field of each linedef is an integer which controls that line's attributes, as follows: bit# = condition if it is set (=1) bit0 = impassibile (by players). Only really matters for lines between 2 sectors, lines adjoining just one sector are impassible regardless. bit1 = ?, has to do with the above/below. bit2 = may shoot through; also, "transparent", meaning the "above" and "below" wall textures are displayed as appropriate. bit3 = ?, has to do with the above/below. bit4 = enemies do not cross this line (I think) bit5 = a secret. this is NOT what determines the SECRET ratio at the end of a level, that is done by special sectors (#9). So this bit is only really useful for mapping. bit6 = ?, to do with being high up/overhang. bit7 = the "above" part is transparent to the sky behind. this one is usually used in the outside courtyard areas. bit8-15 unused. [3-3-2]: Linedef Types ---------------------- The integers in field 4 of a linedef control various special characteristics of that line, mostly to do with what happens to a "triggered" SECTOR when the line is crossed by a player. The * means the linedef needs a trigger # (in field 5) to link it to the appropriate sector(s). $ and & mean the player activates the function by pressing spacebar: $ is for switches which operate once only, & is for doors which can be used over and over. And yes, some of the switches can be used over and over, which ones are they? @ means I'm not sure yet if it is one-time or repeatable. Value = Effect -1 0 Nothing special. 1 & Door. Sector ceiling rises. 2 * removes/raises sector permanently 3 5 * 7 *$ staircase rises up from floor in appropriate sectors. 8 * stairs 9 *@ 10 11 $ End level. Go to next level. 13 14 16 * 18 *$ floor of sector rises to equal height of neighbor sector. The first sector height it finds "on the way up", amongst its neighbors, is where it stops. 19 20 *$ floor rises to equal neighbor, and the floor's texture changes to match that neighbor also. 21 22 23 24 26 & Door. Need blue key to open. 27 & Door. Yellow key. 28 & Door. Red key. 29 30 31 32 $ Door. Blue key. Stays open. 33 $ Door. Yellow key. Stays open. 34 $ Door. Red key. Stays open. 35 * sector's brightness goes to 0. 36 * sector's floor drops to 8 above neighbor. 37 38 39 * teleport to sector 40 41 42 44 46 * Shoot this line, then sector ceiling rises to neighbor 48 Animated, horizontal scrolling wall. 51 $ End level. Go to secret level 9. 52 56 58 59 61 62 63 70 *@ sector floor drops to just above neighbor 73 74 75 76 77 * Crushing ceiling! 82 86 87 88 * sector floor drops to match neighbor 89 90 91 97 * Teleport to... 98 102 103 104 Obviously, I'm still working on this list. These are all the values that occur anywhere in the registered version, but I haven't tested many of them yet. [3-4]: SIDEDEFS =============== A sidedef is a definition of what wall meta-textures to draw along the various LINEDEFS, and a group of sidedefs define a SECTOR. There will be one sidedef for a line that borders only one sector, since it is not necessary to define what the doom player would see from the "other" side of that line because the doom player can't go there. The doom player can only "go" where there is a sector (unless you use the no clipping cheat, which will cause the screen to freak out if you go "outside" to a non-sector area). Each SIDEDEF has 2 (integer) fields, then 3 (8-byte string) fields, then a final (integer) field: 1. X offset for pasting the appropriate wall texture onto the wall's "space": positive offset moves "into" the texture, so the left portion gets cut off (# of columns off left side = offset). negative offset moves texture farther right, in the wall's "space" 2. Y offset: analogous to the X, for vertical. 3. name of wall type 1 = the part "above" the juncture with a lower ceiling of an adjacent SECTOR. 4. name of wall type 2 = the part "below" a juncture with a higher floored adjacent SECTOR 5. name of wall type 3 = the regular part of the wall 6. SECTOR that this sidedef "helps to surround" The wall type fields will be "-" if nothing, thus the sidedef for looking IN a "window" is "-" "-" "-". A typical sidedef, with no above or below, is "-" "-" "WALLNAME". 00s fill the space after a wall name that is less than 8 characters. The wall names are from the TEXTURE1/2 objects. The names in the DIRECTORY are not directly used, they are referenced through PNAMES. [3-5]: VERTEXES =============== These are the beginnings and ends for LINEDEFS and SEGS, each has 2 (integer) fields: 1. X coordinate 2. Y coordinate [3-6]: SEGS =========== Each SEG has 6 (integer) fields 1. from vertex # 2. to vertex # 3. angle: 0= east, 16384=north, -16384=south, -32768=west. In hex, it's 0000=east, 4000=north, 8000=west, c000=south. 4. linedef that this seg goes along 5. 0 if it goes in the same direction as the linedef it is on. 1 if it goes the opposite direction. "direction" is indicated by which vertex is first. 6. Is the distance along the linedef that the seg begins. If the seg begins at one of the two endpoints of the linedef, this will be 0. If the seg and linedef are a "diagonal" line, the length will be according to the distance in the coordinate plane of the vertexes, i.e. SQR((X2 - X1)^2 + (Y2 - Y1)^2). Actually, it seems to be off by 1 or 2 from what it should be, like they are using ABS(X2 - X1) values that are 1 less than the "real" value should be. [3-7]: SSECTORS =============== each SSECTOR has 2 (integer) fields 1. # of SEGS in this SSECTOR 2. starting with this SEG # The segs that make up a ssector are the sides (or parts of the sides) of a polygon, SOMETIMES. Many of the ssectors are only 1 SEG. [3-8]: NODES ============ There are ((number of SSECTORS) - 1) NODES. Each NODE has 14 (integer) fields: 1. X coordinate of nodeline's start 2. Y coordinate of nodeline's start 3. X offset to end of nodeline 4. Y offset to end of nodeline thus 64, 128, -64, -64 would be a nodeline from (64,128) to (0,64) 5/6. Y coordinates bounding the nodesq1 on the right side of the nodeline. 7/8. X coordinates bounding the nodesq1 on the right side of the nodeline. 9/10. Y coords bounding the nodesq2 on the left side of the nodeline. 11/12. X coords bounding the nodesq2 on the left side of the nodeline. 13. Is a NODE or SSECTOR number for nodesq1. If bit15 of this 2-byte field is set, it means that the nodesq1 contains the SSECTOR whose number is in the remaining bits. If the bit15 is not set, then nodesq1 is a previously listed NODE. 14. As with field 13, for nodesq2 on the left. Each node is thus a "sum" of two other rectangular horizontal spaces, each of which contains either a NODE or a SSECTOR. So there is a heavy iterative aspect to this structure. The final NODE is always the size of the entire level. When a SSECTOR is being "contained", the X and Y coordinates of the nodesq are such that every SEG in that SSECTOR is completely within the nodesq. If a NODE is being "contained", then the coordinates will bound the furthest extent of that (recursed) NODE. So what are the nodes for? I don't know yet. Stopped working on it a while back. Will finish sooner or later. Also, need to create an algorithm to generate the segs, ssectors, and nodes, given the vertexes and linedefs. [3-9]: SECTORS ============== A SECTOR is a horizontal (east-west and north-south) area of the map where a floor height and ceiling height is defined, so a doom player may go there. Any change in floor or ceiling "altitude" or texture requires a new SECTOR (and therefore separating LINEDEF(s) and SIDEDEF(s)). Each is 2 (integer) fields, 2 (8-byte string) fields, then 3 (integer) fields: 1. floor is at this "altitude" for this sector 2. ceiling altitude the altitudes range from -264 to 264. a difference of 28 between the floor heights of two adjacent sectors is passable (upwards), but a difference of 32 is "too high". The player may fall any amount. 3. name of floor texture, from the DIRECTORY 4. name of ceiling texture, from DIRECTORY (note: all the ones listed in the DIRECTORY work as either floors or ceilings) 5. brightness of this sector: 0=total dark, 255=maximum bright 6. special sector: 0 is normal 1 light level "blinks" randomly 2 light quickly pulsates 3 blinks: off for a while, then on quickly 4 pulsates AND take 10/20% health hit when stand here 5 -5/10% health (-5% at skill 1, -10% at higher skills) 6 UNKNOWN SPECIAL SECTOR, causes program to exit to DOS 7 -2/5% 8 ?, light pulsates usually, but not always. 9 SECRET (player must walk into this sector to get credit for discovering this "secret") 10 ? 11 -10/20% health 12 blink 13 quick pulsate 14 ? 15 UNKNOWN SPECIAL SECTOR, useless 16 -10/20% 17 and up are all UNKNOWN 7. is a "trigger" number corresponding to a certain LINEDEF with the same "trigger" number. When that LINEDEF is crossed, something happens to this SECTOR - it goes up or down, etc... [3-10]: REJECT ============== Reject is an array of bits. It's size in bytes is (number of SECTORS ^ 2) / 8, rounded up. "It is used for optimization and all the bits may be set to 0" - this is from John Carmack at id software. In fact, the length of the object may be made 0 (same as making it all 0s), and the only thing different about the level is that sometimes enemies seem to "float" when they walk off a step or platform to a lower one. [3-11]: BLOCKMAP ================ All of BLOCKMAP's fields are integers. The whole level is cut into "blocks", each hex 8 k will go something like: 0 330 331 333 -1. This means that LINEDEFS 330, 331, and 333 are "in" that block. Part of each of those line segments lies within the (hex 80 by 80) boundaries of that block. What about the block that has LINEDEF 0? It goes: 0 0 ... etc ... -1. If you don't have a BLOCKMAP, the level displays fine, but everybody walks through walls, and no one can hurt anyone else with their gunfire. ----------------------------- CHAPTER [4]: Pictures' Format ----------------------------- The great majority of the entries if the directory reference resources that are in a special "picture" format. The same format is used for the pictures of items (like medikits), the frames that make up enemies (like demons), the wall patches, and various miscellaneous pictures for the status bar, menu text, inter-level map, and etc. The floor and ceiling textures are NOT in this format, they are raw data; see chapter 5. Each picture has three sections, basically. First, a four-integer header. Then a number of long-integer pointers. Then the picture pixel color data. [4-1]: Header ============= The header has four fields: 1. The number of columns of picture data 2. The number of rows this defines a rectangular "space" or limits for drawing a picture within 3. leftwards x offset from the center to begin the first column. positive value moves left. 4. upwards y offset from the bottom to begin the first row. positive value moves up. To be "centered", #3 is usually about half of the total width. If the picture had 30 columns, and #3 was 0, then it would be off-center to the right, especially when the player is standing right in front of it, looking at it. If a picture has 30 rows, and #4 is 60, it will appear to "float" like a blue soul-sphere. If #4 equals the number of rows, it will appear to rest on the ground. If #4 is more than 5 less than #2, the bottom part of the picture looks akward. With walls patches, #3 is always (columns/2)-1, and #4 is always (rows)-5. This is because the walls are drawn consistently within their own space. (There are two integers in each SIDEDEF which can offset the beginning of a wall) Finally, if #3 and #4 are NEGATIVE integers, then they are the absolute coordinates from the top-left corner of the screen, to begin drawing the picture, assuming the VIEW is FULL-SCREEN (the full 320x200). This is only done with the pictures of the weapons of the doom player - fist, chainsaw, bfg9000, etc. The game engine scales the picture down appropriately if the view is less than full-screen. [4-2]: Pointers =============== After the header, there are N = (# of columns) long integers (4 bytes each). These are pointers to the data for each COLUMN. The value of the pointer represents the offset from the first byte of that picture. [4-3]: Pixel Data ================= Each column is composed of some number of BYTES (NOT integers), arranged in sets: The first byte is the row to begin drawing this set at. 0 means whatever height the header#4 upwards-offset describes. The second byte is how many colored pixels (non-transparent) to draw, going downwards. Then follow (# of pixels) + 2 bytes, which define what color each pixel is, using the game palette. The first and last bytes AREN'T drawn, and I don't know why they are there. Probably just leftovers from the creation process on the NeXT machines. Only the middle (# of pixels in this set) are drawn, starting at the row specified in byte 1 of the set. After the last byte of a set, either the column ends, or there is another set, which will start as stated above. 255 (hex FF) ends the column, so a column that starts this way is a null column, all "transparent". Goes to the next column. Thus, transparent areas can be defined for either items or walls (but you should only use a wall with transparent parts on a SIDEDEF between two SECTORS): Note that all the item and enemy pictures names are in the DIRECTORY between the S_START and S_END entries, and all the wall patches are between the P_START and P_END entries. --------------------------------------- CHAPTER [5]: Floor and Ceiling Textures --------------------------------------- All the names for these textures are in the DIRECTORY between the F_START and F_END entries. There is no look-up or meta-structure as with the walls. Each texture is 4096 raw bytes, making a square 64 by 64 pixels, which is pasted onto a BLOCK's floor or ceiling, with the same orientation as the automap would imply, i.e. the first byte is the color at the NW corner, the 64th is the color at the NE, etc. The data in F_SKY1 isn't even used since the game engine interprets that "special" ceiling as see-thru to the SKY texture beyond. So the F_SKY1 entry can have zero length. ----------------------------- CHAPTER [6]: Sounds and Songs ----------------------------- Not much detail necessary here, since I'm just guessing at the song format anyway. [6-1]: D_[xxxxxx] ================= Songs, probably in general MIDI format. It's obvious what each song is for, from their names. [6-2]: DP[xxxxxx] and DS[xxxxxx] ================================ These are the sound effects. They come in pairs - DP for pc speaker sounds, DS for sound cards. The DS sounds are in RAW format: they have a four integer header, then the sound samples (each sample is 1 byte). The headers' four integers are: 3, then 11025 (the sample rate), then the # of samples, then 0. ------------------------------------------------ CHAPTER [7]: Miscellaneous Non-picture Resources ------------------------------------------------ [7-1]: PLAYPAL ============== There are 14 palettes here, each is 768 bytes = 256 rgb triples. That is, the first three bytes of a palette are the red, green, and blue portions of color 0. And so on. Palette 0 is the one that is used for almost everything. Palette 10-12 are used (briefly) when an item is picked up, the more items that are picked up in quick succession, the brighter it gets, palette 12 being the brightest. Palette 13 is used while wearing a rad suit. Palettes 3, then 2, are used after getting beserk strength. If the player is hurt, then the palette shifts up to X, then comes "down" one every half second or so, to palette 2, then palette 0 (normal) again. What X is depends on how badly the player got hurt: Over 100% damage (add health loss and armor loss), X=8. 93%, X=7. 81%, X=6. 55%, X=5. 35%, X=4. 16%, X=2. Palettes 1 and 9 contain the secret codes which allow you to play Commercial Doom eight months before it gets released. Just kidding! [7-2]: COLORMAP =============== This resource contains 34 sets of 256 bytes, which "map" the colors "down" in brightness. (Brightness is controlled by the 5th field in the SECTORS, see chapter 3-9 above). E.g. at very low brightness, almost all the colors are "mapped" to black, the darkest grey, green, blue, etc. In each set of 256 bytes, byte 0 will have the number of the palette color to which original color 0 gets mapped. Etc. Which set of 34 corresponds to which exact brightness level is something I haven't bothered to figure out. Better things to do...like the maps. [7-3]: DEMOs ============== These are the demos that will be shown if you start doom, but don't play an episode. Each has a record of the keystrokes. Didn't bother to figure the formats out, since demos can be created using the devparm parameter: DOOM -devparm -record DEMONAME The extension .LMP is automatically added to the DEMONAME. Other parameters may be used simultaneously, such as -skill [1-4], -warp [1-3] [1-9]. The demos in the WAD are in exactly the same format as these LMP files, so a LMP file may be simply pasted or assembled into a WAD, and if its length and pointer directory entries are correct, it will work. [7-4]: TEXTURE1 and TEXTURE2 ============================ These resources contains a list of the wall names used in the various SIDEDEFS sections of the level data. Each wall name actually references a meta-structure, defined in this list. TEXTURE2 has all the walls that are only in the registered version. Each entry in this list begins with a 8-byte "name" field, but then each entry has variable length. All the remaining fields of an entry are integers. The second and third fields are always 0 and 0. Purpose is unknown. The fourth and fifth fields define the width in columns and height in rows, for this entry, thus defining a "space" (usually 32 by 128 or 64 by 72 or etc...) in which individual wall textures are "placed" to form the overall picture. This is done because there are some wall patches that are used in several different walls, like computer screens, etc. The sixth and seventh fields are 0 and 0. Purpose unknown. The eigth field is the number of 5-integer "sets" that follow. Each "set" defines a wall texture for placement, and the integers within each set mean this: 1. x offset from top-left corner of "space" (size defined in field 4/5) to start placement of this "patch" 2. y offset 3. number, from 0 to 349, of the entry in the PNAMES object, which contains the name from the DIRECTORY, of the wall patch to use... 4. always 1 5. always 0 Some of the entries have 1 "patch", one has 64 "patches"! [7-5]: PNAMES ============= This is a lookup table for the numbers in TEXTURE[1 or 2] to reference to an actual entry in the DIRECTORY which is a wall patch (in the picture format described in chapter 4). The middle integer of each 5-integer "set" of a TEXTURE1 entry is something from 0 to 349. Number 0 means the first entry in this PNAMES list, 1 is the second, etc... Every entry in this list is eight bytes, and exactly duplicates an entry in the DIRECTORY.