Decoding Doom RPG

I first played Doom RPG on a Sony Ericsson j300a in late 2006. I wasn't expecting much more than a functional Doom-themed Wolfenstein port with finicky controls. (I clearly didn't know much about it before buying it!) What I got was so much more than I thought possible from a feature phone game.

Unfortunately, Doom RPG never found its way to smartphones, or any other platform. EA Mobile doesn't even seem to have it listed in their 'Legacy' section. There aren't many games in the Doom franchise, so it's surprising to see this one get so little attention.

Actually playing the game today is a bit tricky. I've had success running it on KEmulat0r, configuring it as a Sony Ericsson k800. Of course, KEmulat0r appears to be a dead project, nearly 9 years without an update. I couldn't get it to run at all in Microemulator (an open source project), but that hardly matters as it also appears to be dead.

Doom RPG isn't nearly as popular as its older siblings, Doom and Doom II, but there does seem to be some interest. Kyle873 and Kate Fox (Pink Silver) developed a GZDoom Mod inspired by the game. While they're not the same type of game, DoomRL (now just DRL) and Jupiter Hell both offer turn-based gameplay in a Doom-like setting.

The goal here is to puzzle-out and document as much of Doom RPG as possible to empower interested modders and other developers looking to get Doom RPG running on modern systems. There's a lot of stuff here, so I won't say much, if anything, about the disovery process.

Contents

Before we begin

Some important things to remember before we get started:

Doom RPG uses three coordinate systems. If you're familiar with raycasting engines like the one used in Wolfenstein 3D and other early first-person games, you'll likely be familiar with the "coarse grid" and "fine grid" they employ. The coarse grid represents the "blocks" or "grid squares" that compose the level. In Doom RPG, the coarse grid is 32x32. The fine grid divides each coarse grid square in to smaller blocks, typically matching our texture width. In Doom RPG, the fine grid divides coarse grid blocks in to 64x64 blocks and, consequently, the map in to 2048x2048 blocks.

Doom RPG places objects and enemies (things) on a third grid we'll call the "medium grid", which is somewhere between the coarse grid and fine grid. This divides the map in to 256x256 blocks. You can convert medium grid coordinates to fine grid coordinates by multiplying them by 8.

Wall Textures (wtexels.bin)

All the wall textures are stored in wtexels.bin Textures are all 64x64 pixels in size. Each pixel is represented by a 4-bit index in to a color palette.

The first four bytes in wtexels.bin represent a uInt32 that tells us the remaining length of the file. As each texture is 2048 bytes in size, dividing 53248 by 2048 tells us that there are 26 textures in the file.

There is no palette information associated with the textures in this file.

Doom RPG renders textures in vertical strips, from left to right, just like old raycasters like Wolfenstein 3D and Doom. It would be convenient, then, to store the textures on their side, beginning with the left-most strip, so that each strip could be read sequentially, which is precisely how they're laid out. A naive rendering (each pixel in sequence from left-to-right, top-to-bottom) will produce a mirror image of the texture, rotated 90-degrees to the left.

One additional quirk: While each pixel is represented by 4-bits, meaning each byte contains the color index for two pixels, they're reversed from what you'd expect. The least significant nybble represents the left-most pixel in the group and the most significant nybble represents the right-most pixel.

0 1 2 3 4 5 6 7 1 0 3 2 5 4 7 6

For example: If you encounter [01 23 45 67], the output would look like [1 0 3 2 5 4 7 6]

Sprites (stexels.bin, bitshapes.bin)

Sprites are more complicated than textures, as they're spread out across two files: stexels.bin and bitshapes.bin

stexels.bin, like wtexels.bin has a 4-byte header, which is just a uInt32 that tells us the remaining length of the file. The rest is just pixel data, 4-bits per pixel, with the same quirks we saw in wtexels.bin In a confusing twist, only the visible pixels are included. There isn't a value to represent a 'transparent' color, so only the visible parts of the sprite have texels. To produce the sprites, we need to know where those invisible pixels belong. This is where bitshapes.bin comes in.

bitshapes.bin contains the "shape" of our sprites. In the sprite data segments, each bit represents one pixel with a 0 meaning transparent and a 1 meaning colored. The file itself starts of with 4 bytes, a uInt32, representing the remaining length of the file. This is followed by a bunch of variable length records representing individual sprites. Each sprite record contains a 12-byte header followed by the sprite shape data.

I've only managed to decipher one small part of the Sprite Record Header, the length of the data segment + 4, which is enough to move to the next record. The rest is unknown:

Sprite Record Header (12 bytes):

	4 bytes (unknown)
	2 bytes (uInt16) Length of Sprite Shape Data + 4
	6 bytes (unknown)

Sprites are of variable size. They aren't all 64x64 like the wall textures. In order to properly render the sprite, you'll need to know how many bytes are used per vertical strip, as well as the number of strips. This information does not seem to be in the header, but I've managed to work-out the correct sizes for all the sprites. This is included in the Sprite Data Appendix.

To clarify, each 1 bit represents 4-bits in stexels.bin. You'll need to read them together to compose an entire sprite. Additionally, if a sprite in bitshapes.bin contains an odd number of 1's, you'll need to advance your pointer to the next byte for the next sprite. That is, a sprite with an odd-number of visible pixels will waste four bits in stexels.bin.

There is one additional quirk. Like the nybbles in our wall texture data, the individual bits composing our sprite shape are reversed for each byte, with the least significant bit representing the left-most pixel and the most significant bit representing the right-most pixel.

Conveniently, like textures, a naive rendering (each pixel in sequence from left-to-right, top-to-bottom) will produce a mirror image of the sprite, rotated 90-degrees to the left.

You'll notice that neither stexels.bin or bitshapes.bin contain an index of offsets for sprite records. While you can rather quickly walk through bitshapes.bin to find the sprite you want, you won't know where to start reading stexels.bin to get the texels. That data doesn't appear to be anywhere. You can find it by walking through each sprite shape in sequence in tandem with stexels.bin and making a note of each offset. I've done this already and included those values in the Sprite Data Appendix under "stexels.bin Offset".

Again, like textures, no palette information is included. This makes sense as sprites are frequently used with different palettes.

Palettes (palettes.bin)

The first four bytes of palettes.bin gives us the remaining length of the file. This is immediately followed by the palette records, each of which are 32 bytes in length.

Each palette contains 16 colors. Each color is 16 bits, in BGR565 format (not RGB565). You'll want to convert this in to the more familiar 24 or 32 bit color.

The red and blue components are 5 bits wide. The green component is 6 bits wide. We need to do more than just copy the values, as our colors would be very dark. White (0xFFFF) would become 0x1F3F1F, which is a very dark green. Shifting the components up gets us a lot closer, but they still won't be quite correct. White would turn in to 0xF8FCF8, which is both duller, and a little green.

The most obvious way to do this is to find the ratio between 0x1F and 0xFF and 0x3F and 0xFF and multiply the values. This is better, but with integer multipication we still end up with a very slightly green white (0xF8FCF8). If we try to correct this by adding 1, multiplying, and subtracting one, we preserve white, but end up with the same problem for black (0x0000), which will turn in to a slightly purple 0x070307.

While you could work around those problems, there is a much faster and simpler way. For red and blue, after shifting the values left by 3, copy the three most-significant bits to the least significant positions. Do the same for green, but with the two most significant bits. Whites and blacks are preserved, and none of our colors are tinted green. This is the way the game does this internally:

color >> 11 & 0x1F color >> 5 & 0x3F color & 0x1F blue green red blue << 3 green << 2 red << 3 blue >> 2 green >> 4 red >> 2 or or or
	// separate each component
	red   = color & 0x1F;
	green = (color >> 5 ) & 0x3F;
	blue  = (color >> 11) & 0x1F;
	
	// convert to RGB888
	red   =   (red << 3) | (red >> 2);
	green = (green << 2) | (green >> 4);
	blue  =  (blue << 3) | (blue >> 2);

	// put them back together
	color24 = (red << 16) & (green << 8)  &  blue;

There are 143 palettes contained in palettes.bin

Entities

Some entity information is stored in entities.db and entities.str. Not all in-game 'things' are stored here, with 'wall decorations' and 'fences' being the more obvious omissions. No sprite or palette information is included in either file.

The entities.str file contains the in-game description of each entity. The file begins with a uInt16 that tells us the number of records in the file. Records are variable length. Each record begins with a uInt16 that tells us the length of the string data that follows. These records are matched with the records in entities.db by the order in which they appear.

	entities.str
		uInt16: number of Records to follow
		
	Records:
		uInt16: length of string
		varies: string data

The entities.db file contains some information about in-game entities. What information it contains varies by entity type. The file begins with a uInt16 that tells us the number of records in the file. Records are 8 bytes in length.

	entities.db
		uInt16: number of Records to follow
	Records
		uInt16: id
		uInt8:  type
		uInt8:  p1
		uInt32: p2

Entity records are divided in to 4 parts: a 2-byte id, a type, and two parameters. The id's match the id's used for 'things' in .bsp files. The 'type' field groups related entities. Entities with a shared type (mostly) share the same purpose for p1 and p2 (keys and medkits being exceptions).

	Type 0 - Doors
		P1: Normal: 0, Locked: 1, Unlocked: 2
		P2: not used

	Type 1 - Enemy
		P1: Class
		P2: Enemy 'level' within each class Level1: 0x126, Level2: 0x1D3, Level3: 0x280

	Type 2 - Humans
		P1: not used
		P2: not used

	Type 3 - Keys, health, armor, credits
		P1: Class (Keys: 0x18, Health: 0x14, Armor: 0x15, Credits: 0x16 & 0x17)
		P2: Keys: Green - 0, Yellow - 1, Blue - 2,  Red - 3
		    Health, armor, credits: Amount to add

	Type 4 - Inventory Consumables
		P1: Sm Medkit: 0x19, Lg Medkit: 0xA1, SoulSphear: 0xA2, Berzerker: 0xA3, Dog Collar: 0xA4 
		P2: Only for Medkits, amount of health to add when used

	Type 5 - Weapons
		P1: Cycle order
		P2: Amount of ammo added on pickup	
	
	Type 6, 16 - Ammo Pickups (6 - single, 16 - multiple)
		P1: Ammo Type (Halon: 0, Bullet: 1, Shell: 2, Rocket: 3, Cell:4)
		P2: Amount of ammo added on pickup

	Type 7 - Furniture, portal, computers, unnamed
		P1: unknown
		P2: not used
	
	Type 8, 9, 14, 15 - Unknown (Unused?)
		P1: not used
		P2: not used
	
	Type 10, 11 (10 - Fire, 11 - Lava)
		P1: not used
		P2: not used
	
	Type 12 - Breakable Items
		P1: Class (Barrel: 1, Crate: 2, Door/Wall: 3, Power Coupling: 4)
		P2: unknown
	
	Type 13 - Furniture
		P1: unused
		P2: unused

There are 115 entities included in the file. See the Entities Data Appendix for more details.

Mappings (mappings.bin)

mappings.bin contains four unrelated groups of records. The file starts out with a 16 byte header, composed of 4 uInt32's that indicate the length of each of these groups.

Group 1 maps wall textures to color palettes. As each texture is used with different palettes, we end up with 51 records instead of 26. Each record is 8 bytes in length, being composed of two uInt32's. The first uInt32 indicates the wall texture (from wtexels.bin), the second indicates the palette (from palettes.bin). How, in both cases, is not obvious. To find the texture index, divide by 4096. To find the texture offset, divide by 2 and add 4. To find the palette index, divide by 16. To find the palette offset, add 4.

We can now extract all of the wall textures.

Group 2 maps sprites to color palettes. There are 207 8-byte records, each composed of two uInt32's. The first indicates the sprite (from bitshapes.bin), the second indicates the color palette (from palettes.bin). To find the offset in to bitshapes.bin, add 4. To find the palette index, divide by 16. To find the palette offset, add 4.

Using some additional information about the dimentions of each sprite (from the Sprite Data Appendix), we can finally extract all of the sprites.

Group 3 contains 93 records. Each record consists of a single uInt16. This maps the wall texture id from the line segment portion of .bsp files to the wall textures in Group 1. For example, The wall texture assigned to the Portal (in reactor.bsp) is 34, but the wall texture is at index 24. The value at Group 3 index 34 is 24.

Group 4 contains 252 records. Each record consists of a single uIn16. Values range from 0 to 205. Its purpose is unknown, but appears to be related to sprites.

Levels and Maps (*.bsp)

As luck would have it, Simon Howard (Fraggle) has worked out a good bit of the Doom RPG bsp file format [Mirror]. I'll expand on his work here, filling in quite a few of the missing details. You can also take a look at Richard Walmsley's Map Viewer.

.bsp files start off with a 13-byte header:

	.bsp header:
		uInt24: Floor Color BGR888
		uInt24: Ceiling Color BGR888
		uInt24: unknown (always 0)
		uInt8:  Level id
		uInt24: unknown

The Level id number starts at 1 for intro.bsp and increases by one for each file in the natural level order: junction.bsp, level01.bsp, level02.bsp, level03.bsp, level04.bsp, level05.bsp, level06.bsp, level07.bsp, junction_destroyed.bsp, reactor.bsp. The enemy montage at the end of the game endgame.bsp and the test items.bsp both have an id of 0.

BSP Tree

Following the header is the BSP tree. It starts with a uInt16 representing the number of nodes. Each node record is 48 bytes in length, so you can quickly skip over this section if you don't need it.

The first four bytes of each node record represent the two coordinate pairs of a bounding box (x1, y1, x2, y2 in that order). (These are positioned on the "medium grid" mentioned earlier. You can multiply each value by 8 to convert them to the "fine grid".)

The last six bytes represent different things, depending on the value of the first byte. We'll use Fraggle's naming here. The first byte is the "nodetype", the second is named "splitpos", the remaining four represent two uInt16's, the purpose of which varies depending on nodetype, called "arg1" and "arg2".

If nodetype is zero, the current node is a leaf-node. The splitpos byte is ignored. arg1 tells us the number of line segments in the node, and arg2 gives us the index of the first line segment, in the line segment record set, of the first line segment in the node. (The remaining line segment indices are in sequence from the first segment.)

If nodetype is 1, the current node is split in to two subnodes along the y-axis. splitpos contains the position along the y-axis to split the node. Arg1 contains the index of the first subnode, arg2 the index of the second.

If nodetype is 2, the current node is split in to two subnodes along the x-axis. splitpos contains the position along the y-axis to split the node. Arg1 contains the index of the first subnode, arg2 the index of the second. (This is identical to a nodetype of 1, but split along the x-axis instead of the y-axis.)

Line Segments

The line segment section immediately follows the bsp tree. Line segments are used for walls and doors. The line segment section begins with a uInt16 that tells us the number of line segment records that follow.

Line segment records are 36 bytes in length. The first 4 bytes represent the start and end coordinate pairs for each line segment on the medium grid. This is followed by a uInt16 for the wall texture, then a uInt16 for various flags.

The value for the wall texture is an index to group 3 in mappings.bin which has the actual wall texture index.

For consistancy with Fraggle's work, I'll use LSB 0 numbering. From most significant to least significant:

	15: Flip texture horizontally
	14: East-facing wall
	13: West-facing wall
	12: North-facing wall
	11: South-facing wall
	10: Locked door
	 9: Shift horizontal
	 8: Shift vertical
	 7:  not used
	 6:  not used
	 5: Secret / Hidden
	 4: Shift West or North
	 3: Shift East or South
	 2: Door (with bit 0)
	 1:  not used
	 0: Door (with bit 2)

Doors, short walls, and walls that are not perfectly vertical or horizontal do not have an orientation flag (bits 14-11) set.

Doors all have either bit 8 or 9 set, but none have bit 4 or 3 set.

Things

Immediately following line segments are 'things'. Things is a broad category that covers everything to enemies and pickups to wall decorations and 'fences'. There are 107 things in the game. See the Thing Data Appendix for details.

The things section starts with a uInt16 that tells us the number of thing records that follow.

Thing records are 5 bytes in length. The first two bytes represent the x and y coordinates of the thing on the medium grid. Things are centered on their coordinates. The third byte identifies the thing id (not necessarily the entity id) of the thing being described or the wall texture if flag bit 2 is set. The remaining two bytes (uInt16) are flags which provided additional information about the thing. Flags are mostly unused by enemies and pickups. Wall decorations and 'fences' use most of the flags.

Using LSB 0 numbering, from most to least significant:

	15:  not used
	14:  not used
	13:  not used
	12:  not used
	11: Fence (with bit 1)
	10:  not used 
	 9: North or South-facing wall decoration
	 8: Dead Enemy
	 7: Wall Decoration
	 6: West-facing
	 5: East-facing
	 4: South-facing
	 3: North-facing
	 2: Treat as Wall *
	 1: Fence (with bit 11)
	 0: Hidden

	 * When set, the id is used as the wall texture id.
	   Orientation bits also change:
	   6: East-facing
	   5: West-facing
	   4: North-facing
	   3: South-facing

Events

The events section immediately follows the things section. Fraggle calls these 'interactions'. Events mark every scripted action in the game. They can be triggered with the action button like activating doors, using computers, and talking to people or they can be triggered simply by stepping on or off a coarse grid square. They can even be triggerd by scripts.

The events section starts with a uInt16, which tells us how many event records follow.

Event records are 4 bytes long, with all of the fields packed tightly in to a uInt32. From most to least significant:

	bits 31-25:  unknown (7 bits) [sometimes set to 1, e.g. the portal in reactor.bsp]
	bits 24-19: Number of commands in script (6 bits)
	bits 18-10: Index of first command (9 bits)
	bits 9-5  : Event Y position on coarse grid (5 bits)
	bits 4-0  : Event X position on coarse grid (5 bits)

Commands and Scripts

Following events are commands. The command section starts with a uInt16 which tells us how many commands follow.

Commands are 9 bytes in length. The first byte is the command. The next 8 bytes are two uInt32's, the first of which (arg1) acts as arguments to the command. The second (arg2) deals with the execution of the command. Each event has a value associated with it I'll call the Event Variable. It defaults to zero, and can be modified by other commands. That variable is referenced by the event's position on the coarse grid (typically 16 bits with bits 15-8 representing the y coordinate and bits 7-0 representing the x coordinate).

Arg2:
	Bits 31-16: Only execute command IF this Value matches the Event Variable

	Bits 15-0:
	15:
	14:
	13:
	12:
	11:
	10:
	 9: things/walls are added/removed by this command
	 8: Execute command on 'action button pressed' 
	 7: East  (execute command on 'leave', in directions set by bits 7-4)
	 6: North 
	 5: West  
	 4: South 
	 3: West (execute command on 'enter' in directions set by bits 3-0)
	 2:
	 1: East
	 0:
Commands:

	 1: Change Location
		arg1: Orientation (bits 23-20) (N: - S: - E: - W: 8)
		      Location Y,X on coarse grid (bits 15-0)

	 2: Change Level 
		arg1: Flags, level
		      Completed current level (bit 31)
		      unknown (bits 30-8)
		      Level filename (local string index, bits 7-0)
	
	 3: Run Event Script
		arg1: Event location Y,X (bits 15-0)

	 4: Show Status Bar Message
		arg1: Message (string index, bits 15-8)

	 5: Not Used

	 6: Not Used

	 7: Show Thing 
		arg1: Thing state (bits 15-8) (state 0: normal, state 2: dead)
		      Thing id (bits 7-0)

	 8: Show Message
		arg1: Message (string index, bits 15-8)
	
	 9: Get Map Data

	10: Enter Passcode (Halt on failure)
		arg1: Prompt (string index, bits 15-8)

	11: Set Event Variable
		arg1: Value (bits 31-16)
		      Event Variable to Modify (bits 15-0, coarse grid Location)

	12: Lock Door
		arg1: Door (line segment index)

	13: Unlock Door
		arg1: Door (line segment index)

	14: Not Used

	15: Open Door
		arg1: Door line segment index

	16: Close Door
		arg1: Door line segment index

	17: Not Used

	18: Hide Things at Location
		arg1: coarse grid Location (bits 15-0)

	19: Incriment Event Variable
		arg1: event variable (bits 15-0)
		      (increases by 2x after zero: 0, 1, 2, 4, 8, etc.)

	20: Not Used

	21: Increase Status Item Count
		arg1: Amount to gain (bits 11-8)
		      Status item (bits 7-0) health: 0, armor: 1, credits: 2

	22: Decrease Status Item Count
	    arg1: Amount to lose (bits 11-8)
	          Status item (bits 7-0) health: 0, armor: 1, credits: 2

	23: Show Message and Halt IF Status Item Count is less than Amount
		arg1: Message string index (bits 31-16)
		      Amount (bits 15-8)
		      Status item (bits 7-0) health: 0, armor: 1, credits: 2

	24: Show Status Bar Message
		arg1: Message (string index, bits 15-8)

	25: Explosion
		arg1: type? (bits 31-24), location on coarse grid (bits 23-0)

	26: Show Message
		arg1: Message (string index, bits 15-8)

	27: Change Level Parameters (called before command 2) 
		arg1: unknown (bits 31-24)
		      Start Level At coarse grid Location Y,X (bits 23-8)
		      unknown (bits 7-0)
	
	28: Not Used

	29: Shake Effect
		arg1: Intensity (bits 31-24), duration in ms (bits 23-0)
	
	30: Set Floor Color
		arg2: Color BGR888 (bits 23-0)
	
	31: Set Ceiling Color
		arg1: Color BGR888 (bits 23-0)

	32: Give/Take All Collected Weapons
		arg1: 0 - Take, 1 - Give

	33: Open Store
		arg1: store id (0, 1, 2, or 3)
	
	34: Set State of Thing at coarse grid Location (used only to kill humans)
		arg1: State (Bits 23-16) (state 2: dead)
		      unknown (bits 15-10)
		      Human coarse grid location Y (bits 9-5)
		      Human coarse grid location X (bits 4-0)
	
	35: Particle Effect
		arg1: effect (bits 31-24)
		      color BGR888 (bits 23-0)
		      (Effects: 0x20 blood spurt, 0x23 teleport/transformation)

	36: Draw Frame

	37: Wait
		arg1: time to wait in ms (bits 23-0)

	38: Unknown. Used Only Once (in reactor.bsp in the "gate lift" script) Related to the portal?

	39: Show message IF [some level] not complete
		arg1: Level id (bits 31-24) from bsp header
		      Message (string index, bits 15-8)

	40: Add Notebook Entry
		arg1: Note (string index, bits 15-8)
	
	41: Halt IF missing keycard
		arg1: Keycard id (bits 1-0)
		(Green: 0, Yellow: 1, Blue: 2, Red: 3)

Block Map

The last 256 bytes of the file represent the block map. The blocks are ordered from left to right, top to bottom. The block map is 32x32 blocks in size, meaning that each block is represented by two bits. The MSB is a flag that tells us if a block is part of a secret area. The LSB tells us if the square is impassable. Bit pairs within each byte are not ordered as you'd expect, but 'reversed'. Each byte represents 4 blocks, but the left most block is represented by the least significant pair, the most significant pair representing the rightmost block.

	Bit pairs:
		00 - Floor
		01 - Wall 
		10 - Floor (secret)
		11 - Wall (secret)

This block map of Level 2 shows all four block types:

Sprite Data Appendix

IndexDescriptionOffsetStrip SizeStrip CountLengthstexels.bin OffsetHeader
0Axe4363189400 A0 01 00 C1 00 70 01 01 3F 2C 3F
1Fire Extinguisher20542510029648 A2 01 00 68 00 88 00 18 30 21 3F
2Shotgun3172641284588C A3 01 00 84 00 84 01 00 3F 30 3F
3Super Shotgun45735516570982 A5 01 00 A9 00 52 01 05 3B 2E 3F
4Chain Gun6343551659536A A7 01 00 A9 00 50 01 05 3B 2C 3F
5Rocket Launcher811362186134478 AA 01 00 BE 00 7A 01 01 3E 2C 3F
6Plasma Gun100935416217054A AD 01 00 A6 00 56 01 05 3A 2C 3F
7BFG 900011835643202042EC AF 01 00 44 01 A6 01 00 3F 1B 3F
8Zombie151574128726176A B4 01 00 23 01 D8 00 0E 36 09 3F
9Zombie Attack18147392733163AE B8 01 00 15 01 BE 00 12 38 09 3F
10Zombie Dead20993501503673AA BC 01 00 9A 00 CC 00 08 39 2F 3F
11Hellhound22616331983959E6 BE 01 00 CA 00 A0 00 16 36 14 3F
12Hellhound Attack24718473764327C6 C1 01 00 7C 01 E6 00 0D 3B 03 3F
13Hellhound Dead28593511534851DE C5 01 00 9D 00 FC 00 07 39 29 3F
14Commando30248504005232D8 C8 01 00 94 01 EE 00 0B 3C 05 3F
15Commando Attack34368504006000D8 CE 01 00 94 01 02 01 0A 3B 06 3F
16Commando Dead3848364192679106 D5 01 00 C4 00 16 01 00 3F 2B 3F
17Imp405274632272104C D8 01 00 46 01 08 01 0C 39 08 3F
18Imp Attack4386855440782418 DD 01 00 BC 01 48 01 07 3D 04 3F
19Imp Dead483836118384580C E2 01 00 BB 00 12 01 03 3F 2A 3F
20Lost Soul50337443088835FE E4 01 00 38 01 FE 00 0A 35 08 3F
21Lost Soul Attack5353744308935106 E9 01 00 38 01 08 01 0A 35 0A 3F
22Lost Soul Dead5673256112986204 ED 01 00 74 00 EA 00 06 3D 30 3F
23Pinky579774934310109F2 EE 01 00 5B 01 04 01 0C 3C 08 3F
24Pinky Attack6152753371109214A F5 01 00 77 01 24 01 0A 3E 09 3F
25Pinky Dead653546425611764E0 FB 01 00 04 01 28 01 00 3F 20 3F
26Cacodemon6803864512123304C 00 02 00 04 02 5C 01 00 3F 00 3F
27Cacodemon Attack732786451213930CC 0C 02 00 04 02 30 01 00 3F 00 3F
28Cacodemon Dead785156432015482EC 18 02 00 44 01 14 01 00 3F 1A 3F
29Pain Elemental8183864512162650A 1F 02 00 04 02 78 01 00 3F 07 3F
30Pain Elemental Attack870786451217518D4 28 02 00 04 02 72 01 00 3F 07 3F
31Pain Elemental Dead923156331518789C2 32 02 00 3F 01 1C 01 01 3F 1E 3F
32Revenant95588504001961536 39 02 00 94 01 4A 01 0B 3C 00 3F
33Revenant Attack997074934320209DA 3D 02 00 5B 01 28 01 0D 3D 09 3F
34Mancubus10325864512207460C 42 02 00 04 02 40 01 00 3F 00 3F
35Mancubus Attack108498645122230840 4E 02 00 04 02 64 01 00 3F 00 3F
36Mancubus Dead1137346425623792D8 59 02 00 04 01 24 01 00 3F 21 3F
37Archvile116417453152446418 5F 02 00 3F 01 2C 01 0C 38 0E 3F
38Archvile Attack1196886451224943D6 62 02 00 04 02 C0 01 00 3F 00 3F
39Archvile Dead124923521562551650 67 02 00 A0 00 D6 00 06 39 2E 3F
40Baron1266084838425823B6 69 02 00 84 01 02 01 0B 3A 00 3F
41Baron Attack130568645122667660 70 02 00 04 02 80 01 00 3F 00 3F
42Baron Dead1358045522027624C8 77 02 00 E0 00 E4 00 06 3C 27 3F
43Cyberdemon138128524162807248 7B 02 00 A4 01 58 01 08 3B 00 3F
44Cyberdemon Attack142408574562907620 83 02 00 CC 01 AC 01 03 3B 00 3F
45Kratos147088594723015186 8B 02 00 DC 01 DE 01 01 3B 03 3F
46Kratos Attack1519286451230833DA 90 02 00 04 02 02 02 00 3F 05 3F
47Keycard1571631545316989C 97 02 00 31 00 5C 00 19 27 2B 3F
48Halon Can1577323162318117E 98 02 00 42 00 80 00 13 31 36 3F
49Bullet Clip15847216323194284 99 02 00 24 00 44 00 1B 2A 35 3F
50Shotgun Clip158911181831998F4 99 02 00 16 00 4C 00 18 29 39 3F
51Rocket1592132575320434E 9A 02 00 4F 00 68 00 1A 32 27 3E
52Cell Clip16008222443216746 9B 02 00 30 00 5C 00 17 2C 34 3F
53Health Vial1606431957322751E 9C 02 00 3D 00 50 00 19 2B 2E 3F
54Armor Shard161332224432367D6 9C 02 00 30 00 5C 00 18 2D 31 3F
55Flak Jacket161893319332484C0 9D 02 00 61 00 8E 00 10 2E 2F 3F
56Credit1629424080326814A 9F 02 00 54 00 A4 00 0E 35 2E 3D
57Medkit16386338114329698A A1 02 00 76 00 9C 00 12 37 2D 3F
58Soul Sphear1651243212833262D4 A3 02 00 84 00 86 00 13 32 27 3F
59Dog Collar166524351403354102 A6 02 00 90 00 BE 00 13 35 1F 3D
60Lava Pit1680426312633758B4 A7 02 00 82 00 0E 01 01 3F 31 3F
61Fire16942864512340752E AA 02 00 04 02 A8 01 00 3F 01 3F
62Barrel1746643915635197F2 B2 02 00 A0 00 A0 00 14 3A 20 3F
63Coupler176348403203560522 B6 02 00 44 01 58 01 0C 33 01 3F
64Sink1796663319836332D0 BB 02 00 CA 00 AC 00 17 37 12 3F
65Toilet181766321923665352 BE 02 00 C4 00 9E 00 12 31 16 3F
66Chair18380528140371472E C2 02 00 90 00 B6 00 14 2F 1B 3F
67Lamp18532642252374194E C4 02 00 00 01 B6 00 14 3D 10 3F
68Exit Sign1879622244377700C C7 02 00 30 00 5C 00 15 2A 00 0D
69File Cabinet18852744308379213A C8 02 00 38 01 B4 00 14 3F 0C 3F
70Table191724542163859278 CD 02 00 DC 00 3C 01 07 3C 24 3F
71Bunk19400658348389392E D0 02 00 60 01 B6 01 03 3C 16 3F
72Enter Sign1976023162396116E D5 02 00 42 00 80 00 10 2E 00 0D
73Civilian19834736252398251A D7 02 00 00 01 B8 00 0E 31 08 3F
74Scientist200988342724035238 DB 02 00 14 01 C2 00 13 34 06 3F
75Marine203828362884085526 DF 02 00 24 01 C2 00 11 34 06 3F
76Crate2068244919641347FE E2 02 00 C8 00 C8 00 0D 3D 20 3F
77Blast A Frame 12089054020041966D4 E7 02 00 CC 00 A4 00 0C 33 0C 33
78Blast A Frame 2211026482884253546 EC 02 00 24 01 8C 01 07 36 09 38
79Blast A Frame 3214028624964329638 F2 02 00 F4 01 B2 02 00 3D 02 3D
80Blast B Frame 12191042911643641EA F4 02 00 78 00 B6 00 11 2D 11 2D
81Blast B Frame 22203876444843868B0 F6 02 00 C4 01 32 01 00 3F 07 38
82Blast B Frame 32249846425645039D6 FF 02 00 04 01 0E 01 00 3F 11 2C
83Blast C Frame 122766215304547844 03 03 00 22 00 40 00 18 26 19 26
84Blast C Frame 22280854020045528A8 03 03 00 CC 00 FA 01 0B 32 0D 31
85Blood Splat23020859472457222C 05 03 00 DC 01 E2 01 03 3D 03 3D
86Blood Splat Pentagram235048635044621200 09 03 00 FC 01 96 02 01 3F 03 3F
87Blood Splat Die2402085241646939AE 0E 03 00 A4 01 14 02 07 3A 06 3F
88X Brace244488645124731298 11 03 00 04 02 D0 01 00 3F 00 3F
89Wall Tube24972840320487770A 1D 03 00 44 01 A4 00 0C 33 00 3F
90Wall Damage25304864512500570A 27 03 00 04 02 8E 01 00 3F 00 3F
91Bars2582886451250788C0 2C 03 00 04 02 52 01 00 3F 01 3F
92Wall Side Supports2635286451251810BC 34 03 00 04 02 A4 00 00 3F 00 3F
93Wall Broken Plaster2687686451252203CE 37 03 00 04 02 04 01 00 3F 01 3F
94Axe Hold274008312485364008 43 03 00 FC 00 96 00 21 3F 07 3F
95Axe Use276605351755407976 46 03 00 B3 00 92 00 08 2A 1A 3F
96Fire Extinguisher Hold27847563315542992E 48 03 00 3F 01 2E 01 00 3E 1A 3F
97Fire Extinguisher Use2817485644855022D4 4D 03 00 C4 01 6E 01 06 3D 00 3F
98Gun Hold286344261045588490 54 03 00 6C 00 6E 00 13 2C 27 3F
99Gun Use28750426104560811A 56 03 00 6C 00 82 00 12 2B 20 3F
100Shotgun Hold288664421685634428 58 03 00 AC 00 AC 00 08 31 21 3F
101Shotgun Use290465412055671916 5B 03 00 D1 00 C6 00 0A 32 1A 3F
102Chain Gun Hold29263440160572594E 5F 03 00 A4 00 A4 00 0C 33 26 3F
103Chain Gun User29435542210576667C 62 03 00 D6 00 B0 00 0C 35 1A 3F
104Super Shotgun Hold2965733610858329AA 67 03 00 70 00 94 00 0E 31 28 3F
105Super Shotgun Use297775402005863208 6A 03 00 CC 00 C2 00 0C 33 1D 3F
106Plasma Gun Hold2998944016059106BC 6D 03 00 A4 00 A6 00 0C 33 26 3F
107Plasma Gun Use301614401605953210 71 03 00 A4 00 C0 00 0B 32 26 3F
108Rocket Launcher Hold303334502005994244 74 03 00 CC 00 CC 00 07 38 27 3F
109Rocket Launcher Use3054555025060410EC 77 03 00 FE 00 D0 00 07 38 1E 3F
110BFG 9000 Hold308073551656109342 7D 03 00 A9 00 E0 00 04 3A 28 3F
111BFG 9000 Use309846633786162264 81 03 00 7E 01 48 01 01 3F 12 3F
112Hellhound Hold31374546230626425C 89 03 00 EA 00 C8 00 0A 37 1A 3F
113Hellhound Use31616761427631798E 8D 03 00 AF 01 34 01 02 3E 09 3F

Thing Data Appendix

#ID16Description
101Axe
202Fire Extinguisher
303Shotgun
404Super Shotgun
505Chain Gun
606Rocket Launcher
707Plasma Gun
808BFG9000
911Zombie Pvt
1012Zombie Lt
1113Zombie Cpt
1214Hell Hound
1315Cerberus
1416Demon Wolf
1517Troop
1618Commando
1719Assassin
181AImpling
191BImp
201CImp Lord
211DPhantom
221ELost Soul
231FNightmare
2420Bull Demon
2521Pinky
2622Belphegor
2723Malwrath
2824Cacodemon
2925Wretched
3026Beholder
3127Rahovart
3228Pain Elemental
3329Ghoul
342AFiend
352BRevenant
362CBehemoth
372DMancubus
382EDruj
392FInfernis
4030Archvile
4131Apollyon
4232Ogre
4333Hell Knight
4434Baron
4535Cyberdemon
4636Kronos
473EBurned Steel Wall
483FBroken Tube Wall
4941Red Key
5042Blue Key
5143Green Key
5247Steel Wall
5349Yellow Key
5451Halon Can (1)
5552Halon Can (4)
5653Bullet Clip (1)
5754Bullet Clip (4)
5855Shell Clip (1)
5956Shell Clip (4)
6057Rocket (1)
6158Rocket (4)
6259Cell (1)
635ACell Clip (4)
645BHealth Vial
655CArmor Shard
665DFlak Jacket Green
675ECombat Suit Blue
685FCredit Green
6960Credit Yellow
7063MedKit Small
7164MedKit Large
7265Soul Sphear
7366Berserker
746ECollar
7580Lava
7681Fire
7782Barrel
7883Power Coupling
7984Sink
8085Toilet
8186Chair
8287Lamp Yellow
838AExit Sign
848BFile Cabinet
858CLamp Blue
868DTable
878EBunk
8891Civilian Yellow
8992Scientist White
9093Marine Green
9194Scientist Black
9295Scientist Blue (Guerard)
9396Civilian Purple (Nadira)
9497Civilian Green
9598Marine Blue
96A1Crate Orange
97A2Crate Yellow
98D1Splat
99D2Splat Pentagram
100D3Splat Die
101D4Wall X Brace
102D5Wall X Brace
103D6Wall Tech
104D7Damaged Stucco
105D8Bars
106D9Wall Side Supports
107DCDamaged Steel Wall

Entities Data Appendix

#StringIDTypeP1P2
0:Axe000150000000000
1:Fire Ext00025010000000A
2:Shotgun000350300000008
3:Super Shotgn00045050000000A
4:Chaingun00055040000000C
5:Rocket Lnchr000650700000004
6:Plasma Gun00075060000000C
7:BFG00085080000000F
8:Pistol000950200000000
9:Hellhound000A50900000000
10:Cerberus000B50A00000000
11:Demon Wolf000C50B00000000
12:Zombie Pvt001110000000126
13:Zombie Lt0012100000001D3
14:Zombie Cpt001310000000280
15:Hellhound001410100000126
16:Cerberus0015101000001D3
17:Demon Wolf001610100000280
18:Troop001710200000126
19:Commando0018102000001D3
20:Assassin001910200000280
21:Impling001A10300000126
22:Imp001B103000001D3
23:Imp Lord001C10300000280
24:Phantom001D10400000126
25:Lost Soul001E104000001D3
26:Nightmare001F10400000280
27:Bull Demon002010500000126
28:Pinky0021105000001D3
29:Belphegor002210500000280
30:Malwrath002310600000126
31:Cacodemon0024106000001D3
32:Wretched002510600000280
33:Beholder002610700000126
34:Rahovart0027107000001D3
35:Pain Elemental002810700000280
36:Ghoul002910800000126
37:Fiend002A108000001D3
38:Revenant002B10800000280
39:Behemoth002C10900000126
40:Mancubus002D109000001D3
41:Druj002E10900000280
42:Infernis002F10A00000126
43:Archvile003010A000001D3
44:Apollyon003110A00000280
45:Ogre003210B00000126
46:Hell Knight003310B000001D3
47:Baron003410B00000280
48:Cyberdemon003510C00000126
49:Kronos003610D00000126
50:Red Key004131800000003
51:Blue Key004231800000002
52:Green Key004331800000000
53:Yellow Key004931800000001
54:Halon Can005160000000003
55:Halon Cans005216000000000A
56:Bullet Clip005360100000004
57:Bullet Clips005416010000000A
58:Shell Clip005560200000004
59:Shell Clips005616020000000A
60:Rocket005760300000001
61:Rockets0058160300000004
62:Cell Clip005960400000004
63:Cell Clips005A16040000000A
64:Health Vial005B31400000004
65:Armor Shard005C31500000004
66:Flak Jacket005D31500000019
67:Combat Suit005E31500000032
68:1 credit005F31600000001
69:5 credits006031700000005
70:Sm Medkit006341900000019
71:Lg Medkit006441A0000004B
72:Soul Sphere006541B00000000
73:Berserker006641C00000000
74:Dog Collar006E41D00000000
75:Civilian009120000000000
76:Scientist009220000000000
77:Marine009320000000000
78:Scientist009420000000000
79:Dr. Guerard009520000000000
80:Civilian009620000000000
81:Civilian009720000000000
82:Marine009820000000000
83:Lava Pool0080110000000000
84:Fire0081100000000000
85:Barrel0082120100000FFF
86:Power Coupling0083120400000FFF
87:Sink0084130000000000
88:Toilet0085130000000000
89:Chair0086130000000000
90:Yellow Lamp008770000000000
91:Cabinet008B70000000000
92:Blue Lamp008C70000000000
93:Table008D130000000000
94:Bunk Beds008E70000000000
95:Crate00A1120200000FFF
96:Crate00A2120200000FFF
97:Jammed Door0132120300000001
98:Weak Wall014C120300000001
99:Door013100000000000
100:Red Door013400000000000
101:Blue Door013500000000000
102:Green Door013600000000000
103:Yellow Door013700000000000
104:Exit Door013800000000000
105:Locked Door013A00100000000
106:Unlocked Door013B00200000000
107:015270400000000
108:Portal015370300000000
109:Computer016770500000000
110:Item Vendor016870000000000
111:020190000000000
112:0202140000000000
113:0203150000000000
114:029A80000000000



Home - Last modified: June 2017