This shows you the differences between two versions of the page.
file_formats:stb_lev [2006/08/04 07:20] |
file_formats:stb_lev [2006/08/04 07:20] (current) |
||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Stb .Lev ====== | ||
+ | For Easier Editing Open **STATIC_MAP_COMMON_HEADER** Last Entry in .Stb Archive \\ | ||
+ | \\ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Static Map Common Header ===== | ||
+ | [4] Bytes - Number of Entries \\ | ||
+ | \\ | ||
+ | Then You Need to Search for Filename (Data\Levels\FinalAlbion\xxxxx.Lev) \\ | ||
+ | Once Desired Name is found there is an offset jump following name. \\ | ||
+ | \\ | ||
+ | [4] Bytes - Offset Jump to File Data \\ | ||
+ | |||
+ | [4] Bytes - Start Data (01 00 00 00) \\ | ||
+ | [4] Bytes - Level ID \\ | ||
+ | [4] Bytes - Unknown (Relative to Dimension of Map) \\ | ||
+ | [4] Bytes - Map Dimension (X) \\ | ||
+ | [4] Bytes - Map Dimesnion (Y) \\ | ||
+ | [4] Bytes - Map World Offset (X) \\ | ||
+ | [4] Bytes - Map World Offset (Y) \\ | ||
+ | [4] Bytes - Null \\ | ||
+ | [4] Bytes - Current File Offset Push \\ | ||
+ | [4] Bytes - Current File Offset Push \\ | ||
+ | \\ | ||
+ | [4] Bytes - New Section Start (0A 00 00 00) \\ | ||
+ | [4] Bytes - Always (04 00 00 00) \\ | ||
+ | [4] Bytes - Repeat of Unknown Data Above (Relative to Dimension of Map) \\ | ||
+ | [4] Bytes - Checksum (Same as one used in .Wad Lev file) \\ | ||
+ | [4] Bytes - Unknown (Always B3 16 34 7C?) \\ | ||
+ | [4] Bytes - Unknown (Always 00 00 32 00) \\ | ||
+ | [4] Bytes - Map World Offset Starting Position (X) {Float} \\ | ||
+ | [4] Bytes - Map World Offset Starting Position (Y) {Float} \\ | ||
+ | [4] Bytes - Map World Offset Starting Position (Z) {Float} \\ | ||
+ | [4] Bytes - Map World Offset Ending Position (X) {Float} \\ | ||
+ | [4] Bytes - Map World Offset Ending Position (Y) {Float} \\ | ||
+ | [4] Bytes - Map World Offset Ending Position (Z) {Float} \\ | ||
+ | [4] Bytes - Current File Offset Push \\ | ||
+ | [4] Bytes - Current File Offset Push \\ | ||
+ | \\ | ||
+ | [4] Bytes - New Section Start (01 00 00 00) (//**.Lev File Offsets**//) \\ | ||
+ | [4] Bytes - Offset to First Table In Desired .Lev \\ | ||
+ | [4] Bytes - Offset to Second Table In Desired .Lev \\ | ||
+ | [4] Bytes - Second Table Size \\ | ||
+ | [1] Byte - Indicator For Offset Push \\ | ||
+ | [4] Bytes - Current File Offset Push \\ | ||
+ | |||
+ | \\ | ||
+ | [4] Bytes - Section Length In Bytes *(Does not Start until after Next 4 Bytes) \\ | ||
+ | [4] Bytes - New Section Start (01 E3 E3 12) (//**Flora Placement?**//) \\ | ||
+ | [4] Bytes - World Placement (X) {Float} \\ | ||
+ | [4] Bytes - World Placement (Y) {Float} \\ | ||
+ | [4] Bytes - Height Placement (Z) {Float} \\ | ||
+ | [4] Bytes - Unknown Placement (Rotation?) {Float} \\ | ||
+ | [4] Bytes - Unknown Placement {Float} \\ | ||
+ | [4] Bytes - Sections for Flora Data (In Static Map Header) (If Present) \\ | ||
+ | [4] Bytes - Offset to Third Section (If Present) in Current .Lev \\ | ||
+ | [4] Bytes - Size of Third Section (If Present) in Current .Lev \\ | ||
+ | [4] Bytes - Offset in Third Section table (Third Section Offset + these bytes) \\ | ||
+ | [4] Bytes - Null \\ | ||
+ | [2] Bytes - Map Dimension (X) \\ | ||
+ | [2] Bytes - Map Dimension (Y) \\ | ||
+ | \\ | ||
+ | [1] Byte - Indicator for Internal Loop Within Last Segment \\ | ||
+ | [4] Bytes - Number of Sections to loop * \\ \\ | ||
+ | *If Zero Data Ends Here for Current Map. If there is Value follow the next segment \\ | ||
+ | === Flora Loop === | ||
+ | [4] Bytes - BIG ID #1 \\ | ||
+ | [4] Bytes - BIG ID #2 \\ | ||
+ | [4] Bytes - BIG ID #3 \\ | ||
+ | [4] Bytes - Placement (X)? {Float} \\ | ||
+ | [4] Bytes - Placement (Y)? {Float} \\ | ||
+ | [4] Bytes - Unknown (Area?) (Int)\\ | ||
+ | [4] Bytes - Null (Int) \\ | ||
+ | [4] Bytes - Unknown (Rotation/Angle?) {Float} \\ | ||
+ | [4] Bytes - Unknown (Rotation/Angle?) {Float} \\ | ||
+ | [4] Bytes - Unknown (Rotation/Angle?) {Float} \\ | ||
+ | [4] Bytes - Placement on Map (X) (Secondary?) {Float} \\ | ||
+ | [4] Bytes - Placement on Map (Y) (Secondary?) {Float} \\ | ||
+ | [4] Bytes - Number of Sections (Int) \\ | ||
+ | [4] Bytes - Unknown (type?) (Int) \\ | ||
+ | [1] Byte - Boolean? Unknown \\ | ||
+ | [1] Byte - Boolean? Unknown \\ | ||
+ | [1] Byte - Boolean? Unknown \\ | ||
+ | [1] Byte - Boolean? Unknown \\ | ||
+ | [4] Bytes - Unknown (Int) \\ | ||
+ | |||
+ | ====== .Lev File Spec ====== | ||
+ | |||
+ | |||
+ | |||
+ | ===== First Table (Height) ===== | ||
+ | //Each Row is 36 Bytes long. Number of Rows is relative to ((X*Y) / 256) (dimensions of map divided by area of section always 16x16) // \\ | ||
+ | \\ | ||
+ | [4] Bytes - Offset \\ | ||
+ | [4] Bytes - Compressed Size \\ | ||
+ | [4] Bytes - World Map Starting Position (X) {Float} \\ | ||
+ | [4] Bytes - World Map Starting Position (Y) {Float} \\ | ||
+ | [4] Bytes - World Map Starting Position (Z) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (X) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (Y) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (Z) {Float} \\ | ||
+ | [4] Bytes - Unknown \\ | ||
+ | \\ | ||
+ | *Each Compressed Package is LZO Compressed following this format: \\ | ||
+ | [4] Bytes - Decompressed Size \\ | ||
+ | [4] Bytes - Compressed Size \\ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Decompressed Data ==== | ||
+ | [2] Bytes - Number of Sections \\ \\ | ||
+ | //**Looped**// \\ | ||
+ | [2] Bytes - Number of Verts \\ | ||
+ | [2] Bytes - Number of Faces \\ | ||
+ | [1] Byte - Null \\ | ||
+ | [4] Bytes - Textures.Big ID of Image used. (This may be only for Proc Textures) These are the actual Mesh \\ | ||
+ | [4] Bytes - Textures.Big ID of Image used. (This may be repeated from above) \\ | ||
+ | [4] Bytes - Textures.Big ID of Bump used. \\ | ||
+ | [4] Bytes - Possibly another texture link \\ | ||
+ | [4] Bytes - Possibly another texture link \\ | ||
+ | [4] Bytes - Possibly another texture link \\ | ||
+ | [1] Byte - Null \\ | ||
+ | |||
+ | === Vert Listing === | ||
+ | //15 Byte rows// \\ \\ | ||
+ | |||
+ | [2] Bytes - Global X Position \\ | ||
+ | [2] Bytes - Global Y Position \\ | ||
+ | [4] Bytes - Height {Float} \\ | ||
+ | [4] Bytes - Packed Normal {PackedXYZ} \\ | ||
+ | [1] Byte - 00 or FF (indicates next X or Y value?) \\ | ||
+ | [1] Bytes - TU offset, Actual TU = (TU + (this-127)/127) \\ | ||
+ | [1] Bytes - TU offset, Actual TU = (TU + (this-127)/127) \\ | ||
+ | |||
+ | === Faces === | ||
+ | // 2 Bytes // \\ | ||
+ | [2] Bytes - Number of Faces \\ | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== Second Table (Unused Graphics?) ===== | ||
+ | //Originally believed to be the mesh, could be used for internal editor only.// \\ | ||
+ | [2] Bytes - Placement (X) \\ | ||
+ | [2] Bytes - Placement (Y) \\ | ||
+ | [2] Bytes - Tile Value (X) (Based on Dimension)* \\ | ||
+ | [2] Bytes - Tile Value (Y) (Based on Dimension)* \\ \\ | ||
+ | *If Value is size of Map then this is the lowest LOD \\ | ||
+ | \\ | ||
+ | [1] Byte - Indicator (01 - Indicates that it contains Offsets. Else it is only 47 Bytes in Length) \\ | ||
+ | [1] Byte - Indicator (Section Start) \\ | ||
+ | [1] Byte - Indicator (Section End) \\ | ||
+ | [4] Bytes - Offset to Compressed Chunk \\ | ||
+ | [4] Bytes - Size of Entire Table (If Value is present this indicates a start of a new LOD) \\ | ||
+ | [4] Bytes - Offset Push Within Table (Next Section to Read, Table treated as internal file!) \\ | ||
+ | [4] Bytes - World Map Start Position (X) {Float} \\ | ||
+ | [4] Bytes - World Map Start Position (Y) {Float} \\ | ||
+ | [4] Bytes - World Map Start Position (Z) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (X) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (Y) {Float} \\ | ||
+ | [4] Bytes - World Map Ending Position (Z) {Float} \\ | ||
+ | |||
+ | |||
+ | |||
+ | ==== Offset Rows ==== | ||
+ | //If Indicator = 01 above then loop until starting indicator equals (stop indicator above)// \\ | ||
+ | //13 Byte Rows// \\ | ||
+ | |||
+ | [1] Byte - Indicator (Row start based on LOD) \\ | ||
+ | [4] Bytes - Offset to compressed chunk \\ | ||
+ | [4] Bytes - Compressed Chunk Size \\ | ||
+ | [4] Bytes - Offset to specific compressed Data (Offset to compressed chunk + Value of These Bytes) \\ | ||
+ | |||
+ | *Additional Notes Number of LODs seems dependent on First Table Rows. Example Creature Hub 4 Rows in first Table. Graphics It Contains (4 High Quality, 6 Medium, 1 Low) \\ \\ | ||
+ | *Each Compressed Package is LZO Compressed following this format: \\ | ||
+ | [4] Bytes - Decompressed Size \\ | ||
+ | [4] Bytes - Compressed Size \\ | ||
+ | |||
+ | |||
+ | === Decompressed Data === | ||
+ | [2] Bytes - Image Dimension (X) it takes up on Map *\\ | ||
+ | [2] Bytes - Image Dimension (Y it takes up on Map *\\ \\ | ||
+ | *If Dimension equals map dimensions then it is the lowest LOD \\ | ||
+ | \\ | ||
+ | [2] Bytes - Tile Placement of Image (Based on Map Dimensions) (X) \\ | ||
+ | [2] Bytes - Tile Placement of Image (Based on Map Dimensions) (Y) \\ | ||
+ | [1] Byte - Null \\ | ||
+ | [1] Byte - Indicator for LOD (not an actual value!) \\ | ||
+ | [3] Bytes - Unkown Based on LOD \\ | ||
+ | [1] Byte - Indicator new section start \\ | ||
+ | [1] Byte - Image Dimensions (X) (Actual Image Size, for editing) \\ | ||
+ | [1] Byte - Image Dimensions (Y) (Actual Image Size, for editing) \\ | ||
+ | [1] Byte - Indicator new section start \\ | ||
+ | [2] Bytes - Image Dimensions Repeat (X) as 2 bytes \\ | ||
+ | [2] Bytes - Image Dimensions Repeat (Y) as 2 bytes \\ | ||
+ | [1] Byte - Indicator new section start \\ | ||
+ | [4] Bytes - Unknown \\ | ||
+ | [6] Bytes - Null? \\ | ||
+ | [4] Bytes - Always (01 00 00 00) Indicates Image Start \\ | ||
+ | ~ DXT1 Image (To get Image size take __actual dimension__ ( X * Y / 2) \\ | ||
+ | |||
+ | *The Rest of file is currently Unknown | ||
+ | |||
+ | |||
+ | |||
+ | ===== Third Section (Flora/Model) ===== | ||
+ | // The only offset to this section exists in Static Map Header **see: [4] Bytes - Offset in Third Section table (Third Section Offset + these bytes)** // \\ | ||
+ | \\ | ||
+ | *The following entries are very sloppy and jump around quite a bit. \\ \\ | ||
+ | [4] Bytes - always zero? \\ | ||
+ | [4] Bytes - if zero again it will need to read until it is at least reaches 1. \\ | ||
+ | [4] Bytes - Global X coords [Float] \\ | ||
+ | [4] Bytes - Global Y coords [Float] \\ | ||
+ | [4] Bytes - Global Z coords [Float] \\ | ||
+ | [4] Bytes - Unknown (Rotation?) [Float] \\ | ||
+ | [4] Bytes - Unknown (Always 23?) [Float] \\ | ||
+ | [4] Bytes - Unknown [Integer] \\ | ||
+ | [4] Bytes - Offset to Chunk [Integer] \\ | ||
+ | [4] Bytes - Chunk Size [Integer] \\ | ||
+ | [4] Bytes - Offset in Chunk (take above Offset + This) [Integer] \\ | ||
+ | [2] Bytes - Placement X? [Short] \\ | ||
+ | [2] Bytes - Placement Y? [Short] \\ | ||
+ | [2] Bytes - Size X? [Short] \\ | ||
+ | [2] Bytes - Size Y? [Short] \\ | ||
+ | [1] Byte - Indicates more entries. If zero reading is finished. \\ \\ | ||
+ | |||
+ | //Here is the Tricky Part. If Offset above leads **directly** to anything other than zero you read below, else the entry is dead and the loop above is redone. // \\ | ||
+ | \\ | ||
+ | [4] Bytes - Number of Sections (Array) [Integer] \\ | ||
+ | [4] Bytes - Chunk Offset [Integer] \\ | ||
+ | [4] Bytes - Chunk Size [Integer] \\ | ||
+ | [4] Bytes - Package Offset (Chunk Offset + Package Offset) (This will lead to compressed data) [Integer] \\ | ||
+ | [4] Bytes - Global X coords [Float] \\ | ||
+ | [4] Bytes - Global Y coords [Float] \\ | ||
+ | [4] Bytes - Global Z coords [Float] \\ | ||
+ | [4] Bytes - Unknown (Rotation?) [Float] \\ | ||
+ | [4] Bytes - Unknown [Float] \\ | ||
+ | [4] Bytes - Unknown [Integer] \\ | ||
+ | [4] Bytes - Unknown [Integer] \\ | ||
+ | |||
+ | ==== Compressed Package ==== | ||
+ | [4] Bytes - Decompressed Size \\ | ||
+ | [4] Bytes - Compressed Size \\ | ||
+ | *Data is LZO compressed \\ | ||
+ | === Decompressed Data === | ||
+ | |||
+ | |||
+ | |||
+ | |||