======================================= Notes on the LR2 level data structure ======================================= by Anthony Kozar http://www.anthonykozar.net/ Nov. 22, 1999 June 18, 2003 (Revised) Jan. 24, 2012 (Thoroughly revised) ======================================= In this file, I will present an overview of the LR2 level data format. This format applies equally to single-level .LVL files created by the Editor and to the "LVL" type resources stored in PRX files. The only (major) difference is that the Editor writes .LVL files in the native byte order of your computer which is big-endian for the Mac and little-endian for Windows PCs. LVL resources in the PRX files that come with LR2 are always in little-endian byte order though. As far as I know, both the Windows and the Mac versions of LR2 can read LVL files in either byte order. **** THESE NOTES PRIMARILY USE THE MAC BIG-ENDIAN BYTE ORDER **** CREDITS: I was helped in compiling this information by some emails that I exchanged with Stephen Appleby back in 1999. In particular, it was his insight into the lengths and purpose of the two large blocks of $FFFF values that occur in most levels that really helped me to understand how to construct a level file without the LR2 Editor. This led directly to my LR2 Level Generators software. Stephen was also the one who figured out all of the values for specifying which "world" a level belongs to and he discovered the existence of the planned "Mall" and "Alien" worlds. I describe the basic overall data structure as follows: Header section Monk section Item section Layout section Examples are from the included example files or from the standard game levels. ================ Header section ================ The header section is $22 (34) bytes long and contains the following info. byte range length description ----- ------ ------------ $00-03 4 "magic number" - always $D8 7E 1B 17 (big-endian) $04-11 14 unknown - seems fairly constant but I have a few levels where some bytes are all greater by the same amount $12-13 2 LR World code $14-17 4 Resource ID of the background pattern $18-1B 4 unknown - always zero ? $1C-21 6 controls scroll-locking The "magic number" is a constant signature that identifies this as a Lode Runner 2 level file (or LVL resource). This field can be used to determine the endianness of the entire file. If the order of the bytes is $D8 7E 1B 17 then the file is big-endian, if the order is $17 1B 7E D8, then the file is little-endian. I have been unable to determine what the next 14 bytes do. They appear to be grouped as seven 2-byte integers. The values that I see most often are 0097 0032 0083 0032 0097 0046 00C8 and these have worked for the levels created by my Level Generators software UNLESS the world for the level is Wacky world. In that case, the above values cause the LR2 game to crash. Using the values shown below for empty_wacky.lvl instead have worked for me. But sometimes, levels created by the Editor have different values for these bytes (see third example below). The "LR World" field is 2 bytes long and can take these values (thanks to Stephen Appleby) 0000 Mona world 0001 Wacky world 0002 Industry world 0003 Alien world (not implemented) 0004 Jungle world 0005 Builder world 0006 Gear world 0007 Mall world (not implemented) 0008 World Hub 0009 Credits world Presumably, the world code affects which graphics and sound resources are loaded for displaying the level. But according to Stephen Appleby, the world code may not be restrictive. He told me that he found a way to include blocks from any world in a level "regardless of the world your level is made in". But I don't know how he did it and I have had problems with levels appearing empty when played in the game if the world code does not match the types of blocks used. The next four bytes are the ID of the XPK resource for the background pattern. Values for the patterns selectable in the Editor range from $2AF8 to $2B0F. Five other XPK resources are available in BGrounds.PRX and I found that their IDs can be used too. In fact, I found that you can use ANY XPK resource as the background but some choices cause strange drawing effects and may cause LR2 to crash after awhile. See the file 22_BGrounds_PRX_TOC.txt for more information. Bytes $1C to $21 are all $00 when scrolling is unlocked. When scrolling is locked the first two bytes are $0001 and the other four bytes contain some kind of data -- probably the screen coordinates of what area to show -- but I don't know exactly what the values mean. Examples -------- File: empty.lvl D8 7E 1B 17 ; this is a big-endian LVL file 00 97 00 32 00 83 00 32 00 97 00 46 00 C8 ; these are the "usual" values 00 05 ; Builder world 00 00 2A F8 ; "blue-green haze" background 00 00 00 00 00 00 ; scrolling is unlocked 00 00 00 00 File: empty_wacky.lvl D8 7E 1B 17 ; this is a big-endian LVL file 00 98 00 32 00 84 00 32 00 98 00 46 00 C8 ; these values "needed" for Wacky world ; values 1,3,5 each greater by 1 00 01 ; Wacky world 00 00 2B 08 ; "lighter bubbles" background 00 00 00 00 00 00 ; scrolling is unlocked 00 00 00 00 Level: Tutorial level #1 17 1B 7E D8 ; this is a little-endian LVL file 9A 00 32 00 86 00 32 00 9A 00 46 00 C8 00 ; values 1,3,5 each greater by 3 05 00 ; Builder world FA 2A 00 00 ; "purple haze" background 00 00 00 00 01 00 ; scrolling is locked 96 0F 14 0D ; view window ?? ================ Monk section ================ A section about monks follows immediately after the main header. It begins with its own short header: byte range length description ----- ------ ------------ $00-01 2 number of monks $02-03 2 always $0005 (marker for monk section ?) If there are no monks in a level, then these four bytes are the entire section. Otherwise, there follows a series of individual monk data structures ("chunks"), one for each monk. Monk data structure ------------------- byte range length description ----- ------ ------------ $00-03 4 00CC 0003 marker that says "this is a monk"? $04-09 6* Xcor Ycor Zcor the monk's starting position $0A-0F 6 FFFF FFFF FFFF constant ? $10-13 4 0000 03E9 Resource ID of monk XPK (different if monk is facing different directions?) $14-15 2 ? leash setting 0 =none, 1 = breakable, 2 = unbreakable $16-1B 6* Xval Yval Zval leash lengths (default = 5,5,2) $1C-1D 2 ???? unknown - typically $0000, but have seen $0001 $1E-1F 2 type of monk 0 = blue, 1 = purple, 2 = black $20-25 6* Xval Yval Zval length of sight $26-27 2 (dflt = 5) number of seconds before regeneration $28- varies (FFFF is none) list of linked regeneration points varies (FFFF is none) list of monk paths * each 2-byte coordinate value byte-swaps on its own The last two parts of the monk chunk are lists of variable length for regeneration points and monk paths. I haven't looked into the format of this information much yet, but here is what I guess to be true. If either of these lists is empty, they are replaced by the two byte value $FFFF. If both are empty, then the monk chunk ends with $FFFF FFFF and is exactly $2C (44) bytes long. If either are non-empty, then I believe the first 2 bytes give the number of entries in the list: either the number of regeneration points that this monk is linked to, or the number of locations that have path info for this monk. See the accompanying file 13_More_about_Monks.txt for additional speculations and an example. Additional monk chunks follow immediately, one after another. =============== Item section =============== A section about items follows right after the monk section and includes info on locations of gold, power-ups, LR & monk regeneration points, and bombs. These come in a specific order that I haven't taken the time to write down yet. Like the monk section, the item section begins with its own short header: byte range length description ----- ------ ------------ $00-01 2 number of items $02-03 2 always $0003 (marker for item section ?) (I wonder if there were $00CC items if LR2 would confuse this with another monk?) If there are no items in a level, then these four bytes are the entire section. Otherwise, there follows a series of 12-byte chunks for each item (14 bytes for bombs). All of the values in these chunks are 2 bytes wide. Gold and power-up chunks all have the form: 00AD type FFFF Xcor Ycor Zcor type item type item ---- ----- ---- ----- 0001 gold piece 0008 stasis mine (watch) 0009 morph power-up 000A monk cloak 000B one-up 000C gasoline can 000E landmines 0011 detonator 0012 inviso 0013 beachball 0014 donut Bomb chunks have the form: 00A7 000F type Xcor Ycor Zcor Num type item type item ---- ----- ---- ----- 0001 sphere 0004 "the cross" (x & y axes) 0002 linear x-axis 0005 vertical (linear z-axis) 0003 linear y-axis 0006 "the trinity" (x, y, & z) Num is the number of bombs that get picked up; 1&5 standard but 2-6 also work!! Monk regeneration point: 00A2 0002 FFFF Xcor Ycor Zcor LR regeneration point: 00A2 0003 FFFF Xcor Ycor Zcor Triggers and possibly monk paths also appear to create chunks in the items section with the following form: 00AA 0004 FFFF Xcor Ycor Zcor I don't know anything for sure about these "pseudo items" yet but the coordinates appear to correspond to the locations of bricks that are affected by triggers or to the locations of monk paths. (I am a little skeptical now about the relationship of these pseudo items to monk paths -- I have one test level that I created with a single path and single pseudo item that match coordinates but I can't find these item chunks in other levels with monk paths). ================ Layout section ================ The layout section contains all of the information for the locations, graphics, and other properties of the blocks, ladders, exits, triggers, etc. within the level. It has a hierarchical organization where each Z-plane (all of the locations with the same Z coordinate) has its own chunk. Within each Z-plane chunk are smaller chunks for all of the blocks that share the same Y coordinate and within these Y-chunks are the still smaller chunks that represent individual blocks. So, the general structure of the layout section is: ----------------------------------------- | First Z-plane chunk (z1) | | -------------------------------------| | | First Y-chunk with coord z1 (y1) | | | Block chunk - x1, y1, z1 | | | Block chunk - x2, y1, z1 | | | ... | | | Block chunk - xN, y1, z1 | | |------------------------------------| | | Next Y-chunk with coord z1 (y2) | | | Block chunk - x11, y2, z1 | | | Block chunk - x12, y2, z1 | | | ... | | | Block chunk - x1N, y2, z1 | | -------------------------------------| | ... | | -------------------------------------| | | Last Y-chunk with coord z1 (yN) | | | Block chunk - xN1, yN, z1 | | | Block chunk - xN2, yN, z1 | | | ... | | | Block chunk - xNN, yN, z1 | | -------------------------------------| |---------------------------------------| | Next Z-plane chunk (z2) | | -------------------------------------| | | First Y-chunk with coord z2 (y1) | | |------------------------------------| | | Next Y-chunk with coord z2 (y2) | | -------------------------------------| | ... | | -------------------------------------| | | Last Y-chunk with coord z2 (yN) | | -------------------------------------| ----------------------------------------- . . . ----------------------------------------- | Last Z-plane chunk (zN) | ----------------------------------------- Chunks are organized with Z and Y coordinates in ascending order and with X coordinates in descending order. EVERY Z-plane -- even empty ones -- must have a chunk but only the Y and X values that contain blocks in a Z-plane have Y-chunks and block chunks, respectively. i.e. within any Z-plane chunk, Y-values without blocks do not have a Y-chunk and within any existing Y-chunk, X-values without a block are just skipped. Coordinate values, including Z-values, all range between 10 and 210. If there are no blocks within a Z-plane, then the entire Z-plane chunk consists only of the 2-byte value $FFFF (there is no header). This is why there are generally two large blocks of bytes of $FF, one after the monk and item sections and another at the end of the level data. For example, in a level whose first block has a Z coordinate of 100, there will be 90 empty Z-planes represented by 180 bytes of $FF values preceding the first substantial Z-plane chunk. If the last block has a Z coordinate of 110, then the level data will end with 200 bytes of $FF. These $FFFF values for empty Z-planes also occur in between "normal" Z-plane chunks when there are intermediary Z-values with no blocks. Items and monks are not important here, so only blocks are counted when determining if a Z-plane is empty. WARNING!! Do not insert blocks at Z coordinates less than 10 or greater than 210 or the Editor (and game?) will crash! Each Z-plane chunk that has blocks begins with a 6-byte header followed by the sequence of Y-chunks for that Z-value. Z-plane header (6 bytes) -------------- byte range length description ----- ------ ------------ $00-01 2 number of Y-chunks within this Z-plane $02-03 2 marker - always $0003 $04-05 2 Z coordinate for this plane Each Y-chunk also begins with a 6-byte header followed by the sequence of block chunks with those Z & Y values. Y-chunk header (6 bytes) -------------- byte range length description ----- ------ ------------ $00-01 2 number of blocks for this Y-value within the enclosing Z-plane $02-03 2 marker - always $000A $04-05 2 Y coordinate for this chunk After each Y-chunk header comes its sequence of block data chunks. There are at least two variations of the basic block data structure and there may be more types as I have only really begun to explore the many types of blocks and their combinations. (eg. I have not examined animations or hand-over-hand rails yet) The basic block structure is extended as needed when a block has overlays: ladders, undiggable caps, and triggers. Here is the data structure for the most common type of blocks (usually solid, diggable blocks but I don't think this template is not limited to those). Common block data structure (30 bytes) --------------------------- byte range length description ----- ------ ------------ $00-01 2 $006E a marker for most block types (see below) $02-03 2 0001 (usually) function unknown $04-07 4 (varies) properties: diggable?, passable?, and/or shadowing ?? $08-0D 6* Xcor Ycor Zcor block coordinates $0E 1 00 (constant?) function unknown $0F 1 01 (usually) add $01 for an attached plate trigger overlay ? $10 1 00 (usually) add $01 for an attached left-sided overlay ? $11 1 00 (usually) add $01 for each attached right-sided or cap overlay ? $12-13 2 008C or 008E a marker ? $14-19 6+ (varies) more properties: may also reflect diggability, passability or possibly how the block is drawn ?? $1A-1D 4 XPK rsrc ID ID for this block's graphic * each 2-byte coordinate value byte-swaps on its own + this field may actually be three fields with sizes 1, 4, and 1 bytes Examples -------- File: blueblock.lvl (from the beginning of the layout section - offset $2A) FF FF, etc. ; $B4 (180 bytes of $FF) 00 01 ; 1 Y-chunk in this Z-plane 00 03 ; Z-plane header marker 00 64 ; Z coord: 100 00 01 ; 1 block in this Y-chunk 00 0A ; Y-chunk header marker 00 64 ; Y coord: 100 ; This is a "normal", solid, diggable block 00 6E ; block chunk marker 00 01 ; unknown 00 00 1C 11 ; properties: unpassable?, diggable? 00 64 00 64 00 64 ; coord: 100, 100, 100 00 01 00 00 ; last byte = no ladders? 00 8C ; marker ? 00 ; unknown 00 00 1C 19 ; properties ? 00 ; unknown 00 00 13 89 ; Builder world "solid blue block" FF FF, etc. ; $DC (220 bytes of $FF) File: blue_glass_floor.lvl (from the first block - offset $EA) ; This is a blue glass floor tile from ; Gear world that Jake can walk under 00 6E ; block chunk marker 00 01 ; unknown 00 00 1D 13 ; properties: X & Y passable?, diggable? 00 64 00 64 00 64 ; coord: 100, 100, 100 00 01 00 00 ; last byte = no ladders? 00 8C ; marker ? 00 ; unknown 00 00 1D 59 ; properties ? 00 ; unknown 00 00 04 20 ; Gear world "blue glass tile" File: invisible_block.lvl (from the first block - offset $EA) ; This is an "invisible block" ; (the green V in the Editor) 00 6E ; block chunk marker 00 01 ; unknown 00 00 01 10 ; properties: unpassable?, undiggable? 00 64 00 64 00 64 ; coord: 100, 100, 100 00 01 00 00 00 8C ; marker ? 00 ; unknown 00 00 01 09 ; properties ? 00 ; unknown 00 00 29 E0 ; "invisible volume" Exit block data structure (32 bytes) ------------------------- The block chunk for an exit looks a little different and is two bytes longer: byte range length description ----- ------ ------------ $00-01 2 $0070 a marker for exit or maybe animated blocks ? $02-03 2 0005 function unknown (compare to 0001 for other blocks) $04-07 4 0000 1D14 properties ? - constant for exit blocks $08-0D 6* Xcor Ycor Zcor block coordinates $0E 1 00 (constant?) function unknown $0F 1 01 no overlays for exits $10 1 00 no overlays for exits $11 1 00 no overlays for exits $12-13 2 008F a marker (compare to 008C or 008E for other blocks) $14-19 6+ 00 00005D8D 00 more properties ?? - constant for exit blocks $1A-1D 4 0000 2EE0 general rsrc ID for exit blocks $1E-1F 2 world which world the exit's graphic belongs to * each 2-byte coordinate value byte-swaps on its own + this field may actually be three fields with sizes 1, 4, and 1 bytes The "world" field is 2 bytes long and can take these values 0002 Mona world 0003 Wacky world 0004 Industry world 0006 Jungle world 0007 Builder world 0008 Gear world 000B Credits world These values are two greater than the "LR World code" constants used in the LVL header. It appears that $00002EE0 is the base resource ID for all things related to exits. There are XMV, XPK, AIF, SID, and SID resources with this ID. Of course, each world has its own graphic for the exit. This extra value is clearly used to find the right graphic (see the World Hub level were there are five exit blocks, all identical except for these last two bytes). But why the value is two greater than the "world code", I don't know, because the XPK and XMV resources for the various exit blocks have IDs that are the sum of $00002EE0 and the "LR World code" constants: Filename Index Offset Type ID Length Gog.PRX 216 745904 XMV $00002EE0 536 WackyWG.PRX 291 929361 XMV $00002EE1 536 TubeWG.PRX 112 127426 XMV $00002EE2 536 JungleWG.PRX 242 448719 XMV $00002EE4 536 BuildWG.PRX 59 31748 XMV $00002EE5 536 GearWG.PRX 154 572457 XMV $00002EE6 536 CreditWG.PRX 279 218844 XMV $00002EE9 536 (The Mona world exit resources appear to be in Gog.PRX and the resources for the other four primary worlds' exits are also duplicated in IntroWG.PRX). Overlays -------- The block structures above describe a block without any overlays. Ladders, caps, and triggers make the block chunk longer, adding a small chunk for each overlay. These overlay chunks usually start with a marker value of $008C or 008E and appear to be similar to bytes $12-1D of the common block chunk. Examples of overlay chunks: a left-side red ladder 008C 01 00000009 08 0000283E a right-side red ladder 008C 02 00000009 08 0000296A an undiggable cap 008C 02 00000009 0A 00001771 two red ladders 008C 01 00000009 08 0000283E 008E 02 00000009 08 0000296A I would guess the following general form from these examples: Common overlay data structure (12 bytes) ----------------------------- byte range length description ----- ------ ------------ $00-01 2 008C or 008E a marker ? $02 1 ?? unknown - 01 or 02 in examples $03-06 4 ???? similar to block's properties at $15-18? $02 1 ?? 08 for ladders ?, 0A for caps $08-0B 4 XPK rsrc ID ID for the overlay's graphic Examples -------- Here are side-by-side examples of a solid blue block with various combinations of overlays: Files: bb_undiggable.lvl bb_leftladder.lvl bb_rightladder.lvl bb_twoladders.lvl bb_twoladders_ud.lvl undiggable cap left red ladder right red ladder two red ladders two ladders + cap block marker 00 6E 00 6E 00 6E 00 6E 00 6E 00 01 00 01 00 01 00 01 00 01 prop: undig 00 00 1C 10 00 00 1C 10 00 00 1C 10 00 00 1C 10 00 00 1C 10 coord 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 00 64 has overlays 00 01 00 01 00 01 01 00 00 01 00 01 00 01 01 01 00 01 01 02 marker 00 8C 00 8C 00 8C 00 8E 00 8E 00 00 00 00 00 properties? 00 00 1C 19 00 00 1C 19 00 00 1C 19 00 00 1C 19 00 00 1C 19 00 00 00 00 00 blue block 00 00 13 89 00 00 13 89 00 00 13 89 00 00 13 89 00 00 13 89 marker 00 8C 00 8C 00 8C 00 8C 00 8C unknown 02 01 02 01 01 properties? 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 00 00 00 09 cap/ladder 0A 08 08 08 08 overlay ID 00 00 17 71 00 00 28 3E 00 00 29 6A 00 00 28 3E 00 00 28 3E marker 00 8E 00 8E unknown 02 02 properties? 00 00 00 09 00 00 00 09 cap/ladder 08 08 overlay ID 00 00 29 6A 00 00 29 6A marker 00 8C unknown 02 properties? 00 00 00 09 cap/ladder 0A overlay ID 00 00 17 71 It appears that the addition of a left-side ladder adds 1 to byte 3 of the line labeled "has overlays" above, while the addition of either an undiggable cap or a right-side ladder adds 1 to byte 4. I don't really understand yet why the field that I am calling a "marker" is sometimes $8C and other times $8E. For examples showing how I arrived at some of my guesses for the byte-sizes of the values within block structures, see the document 12_Comparing_byte_order_in_levels.txt Triggers -------- Triggers can be either overlays (switches, levers, and plates) or specialized blocks (trip wires and invisible triggers). The two categories are thus treated a little differently from each other but in all cases, the block data (and overlay data if applicable) is followed by a "trigger info chunk" that has a uniform structure. I can't yet explain many of the unique values within the block and overlay data for triggers so I will just present them as is. Here are the specific block data for invisible triggers and trip wires: invisible trig. trip wire 00 6E 00 6E 00 01 00 01 00 00 40 12 00 00 40 10 ; these are unique Xcor Ycor Zcor Xcor Ycor Zcor 00 01 00 00 00 01 00 00 00 8D 00 8D ; $8D marker seems common to triggers 00 00 00 00 00 69 00 00 03 2D ; these are unique 0C 0C ; this value is common to triggers too 00 00 2A 8A 00 00 2A 6C * ; resource ID for graphic [Trigger info] [Trigger info follows] * $00002A6C is the resource ID for an "x-axis-oriented" trip wire graphic. Use $00002A76 for a "y-axis-oriented" trip wire. The trigger overlays all show some similarities: left-side switch 008D 01 00000029 0C 00002A46 left-side switch 2 008D 01 00000029 0C 00002A44 left-side lever 008D 01 00000029 0C 00002A32 left-side lever 2 008D 01 00000029 0C 00002A30 plate trigger 008D 00 00000029 0C 00002A80 I haven't looked into the right-side trigger overlays yet. The data for the block to which a trigger overlay is attached is fairly normal, except for the four bytes before the coordinates which seem to always be $5C10 and for the four bytes after the coordinates which change according to what type of trigger is attached. Here is an example of a brick with a plate trigger: File: trigger_plate_no_block.lvl (offset $EA) ; fairly "normal" brick 00 6E 00 01 00 00 5C 10 ; this value is changed 00 64 00 64 00 64 00 02 00 00 ; bytes 2-4 change depending on overlay 00 8E 00 00 00 1C 19 00 00 00 13 89 ; trigger overlay 00 8D ; "trigger marker" 00 ; $00 or $01 depending on overlay 00 00 00 29 ; always $29 0C ; always $0C 00 00 2A 80 ; plate trigger graphic FF FF 0D 00 01 FF 00 00 ; an "empty" trigger info chunk The trigger info chunk is the most interesting part of the trigger and has the following structure: Trigger info data structure --------------------------- byte range length description ----- ------ ------------ $00-01 2 NUM number of blocks/bombs controlled by trigger; $FFFF if none $02-03 2 $0004 constant, but this field only exists if NUM is positive! $03- 6*NUM array of coord. list of coordinates of affected blocks; 6 bytes each 1 trigger type $0B = switch or lever, $0D = plate, $0E = trip wire or invisible 2 operation $0001 = 'phase-out', $0002 = 'phase-in' 1 num of uses $01 = 'once', $FF = 'many' (see note below) 2 timer length timer/delay value in seconds; $0000 for no timer/delay This chunk is a little unusual because it has variable-length data in the middle. If there are no blocks controlled by this trigger (NUM = $FFFF), then the constant $0004 and the array of coordinates are omitted. In this case, the other fields starting with trigger type follow immediately after the $FFFF and the total length of the trigger info chunk is 8 bytes. When there are blocks controlled by the trigger, then the NUM of blocks is followed by $0004 and a list of coordinates in the usual Xcor Ycor Zcor format with 2 bytes per coordinate value. The total length of the trigger info chunk in this case will be 10 + (6 * NUM). The trigger type field is pretty self-explanatory but does not distinguish between switches and levers or between the two types of block triggers (trip wire and invisible). One surprise is that triggers can have other values for the "number of uses" field than just "single-use" ($01) or "multiple-use" ($FF). This field is the actual number of times the trigger will work and can presumably be 2, 3, or any 1-byte value up to 254 ($FE). I have only tested small numbers and I have not test whether the standard "multiple-use" value of $FF really allows unlimited use or whether it only allows 255 uses. For numerous annotated examples of triggers that display some of the subtleties not shown above, see the file 14_More_about_Triggers.txt ================================================================================ This is all that I have so far! I had starting making lists of valid graphic codes (the resource IDs) for the bricks in the past, but that was a slow and tedious process. My new PRX Utilities software should make is easier to create complete lists of working codes even if it doesn't tell you which graphic corresponds to each code. To make a list of codes, just run the prxlist program on the world graphics files (such as GearWG.PRX) and filter the results for "XPK". What seems more important to me now than figuring out the graphic codes is to figure out what other values belong in the block data structure for each class of brick. The most perplexing features of the LVL format to me right now are those fields in the block structure that I've labeled "properties". I started to speculate and test how "passability" is encoded many years ago (i.e how some blocks you can walk through from certain directions but not other directions, but most blocks you just cannot walk through at all) but I met with some seemingly inconsistent data from the Editor. See these documents for some lists of IDs and comparisons of block data: 11_Graphics_Resource_IDs.txt 15_Comparison_of_block_ data.txt I hope that you have found this document informative!!!! -- Anthony Kozar