Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions files/luz.ksy
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,16 @@ types:
- id: unknown1
type: common::vector3
if: _root.file_version == 33
doc: >
v33-only reserved field. Skipped by client (ptr += 12) in every
known build from 0.179.12 through 1.10.64. Never read into any
struct or used at runtime.
- id: unknown2
type: f4
if: _root.file_version == 33
doc: >
v33-only reserved field. Skipped by client (ptr += 4) in every
known build. See unknown1.
- id: scene_color_r
type: u1
if: _root.file_version >= 33
Expand Down
71 changes: 54 additions & 17 deletions files/raw.ksy
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@ meta:
endian: le
imports:
- ../common/common
doc: >
LEGO Universe .raw terrain file format (chunked, version >= 30).

There are two distinct formats sharing the .raw extension:

1. **Chunked format** (zone LUZ version >= 30): Self-describing with a
u16 version + u1 dev header, followed by chunked terrain data.
This is the format described here. File versions 31 and 32 exist.

2. **Legacy flat-grid format** (zone LUZ version < 30): No file header.
See `raw_legacy.ksy` for that format.

The client's `OpenTerrain` function (0x01048080) selects the reader:
mapVersion < 30 → legacy flat-grid reader
mapVersion >= 30 → `ReadNewTerrainFormat` (chunked reader)
seq:
- id: version
type: u2
- id: dev
type: u1
doc: Must be 0 for valid terrain data; non-zero aborts loading
- id: num_chunks
type: u4
if: dev == 0
Expand Down Expand Up @@ -43,73 +59,92 @@ types:
type: u4
repeat: expr
repeat-expr: 4
- id: density
- id: scale
type: f4
doc: Heightmap scale factor, used to transform grid coords to world coords
- id: height_map
type: f4
repeat: expr
repeat-expr: width * height
- id: diffuse_res
- id: color_map_resolution
type: u4
if: _root.version >= 32
- id: diffuse_res_pixels
size: diffuse_res * diffuse_res * 4
doc: Resolution of the color/diffuse map
- id: color_map_pixels
size: color_map_resolution * color_map_resolution * 4
if: _root.version >= 32
doc: RGBA
- id: unknown1
type: u1
repeat: eos
doc: RGBA color map pixels (raw block)
- id: color_map_pixels_legacy
size: width * width * 4
if: _root.version < 32
doc: todo
doc: >
v<32 color map. Client reads width*width pixels (4 bytes each)
with per-pixel BGRA byte swizzle. colorMapResolution = width - 1;
only the inner (width-1)^2 pixels are used.
- id: diffuse_map_dds_size
type: u4
if: _root.version >= 32
- id: diffuse_map_dds
size: diffuse_map_dds_size
if: _root.version >= 32
doc: DDS texture data for diffuse/light map
- id: blend_res
type: u4
- id: blend_pixels
size: blend_res * blend_res * 4
- id: bits
doc: >
Blend/texture map pixels. v>=32 reads as raw RGBA block;
v<32 reads per-pixel as B,G,R,A (byte-swizzled).
- id: blend_channel_mask
type: u1
if: _root.version >= 32
doc: Bitmask of active detail textures (bits 0-3)
- id: blend_map_dds_size
type: u4
if: _root.version >= 32
- id: blend_map_dds
size: blend_map_dds_size
if: _root.version >= 32
doc: DDS texture data for blend map (DXT5)
- id: num_flairs
type: u4
- id: flairs
type: flair_attributes
size: 36
repeat: expr
repeat-expr: num_flairs
- id: scene_map
size: diffuse_res * diffuse_res
size: color_map_resolution * color_map_resolution
if: _root.version >= 32
- id: unknown2
type: u1
repeat: eos
if: _root.version < 32
doc: todo
doc: Per-pixel scene ID assignment, indexes into LUZ scene list
- id: scene_map_v31
size: width * width
if: _root.version == 31
doc: >
v31 scene map. Allocates (colorMapRes+1)^2 where colorMapRes=width-1.
Client reads (colorMapRes+1)^2 cells; inner colorMapRes^2 cells
contain scene IDs, border cells are skipped/discarded.
- id: scene_map_skip
size: 1
if: _root.version < 31
doc: v<31 skips 1 byte; scene map is zero-filled by client
- id: vert_size
type: u4
if: _root.version >= 32
- id: mesh_vert_usage
type: u2
repeat: expr
repeat-expr: vert_size
if: _root.version >= 32 and vert_size != 0
- id: mesh_vert_size
type: u2
repeat: expr
repeat-expr: 16
if: _root.version >= 32 and vert_size != 0
- id: mesh_tri
type: mesh_tri
repeat: expr
repeat-expr: 16
if: _root.version >= 32 and vert_size != 0

flair_attributes:
seq:
Expand All @@ -127,6 +162,8 @@ types:
type: u1
- id: color_b
type: u1
- id: color_a
type: u1
mesh_tri:
seq:
- id: mesh_tri_list_size
Expand Down
109 changes: 109 additions & 0 deletions files/raw_legacy.ksy
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
meta:
id: raw_legacy
file-extension: raw
endian: le
doc: >
LEGO Universe legacy .raw terrain file format (zone LUZ version < 30).

This format has no file header — the zone's LUZ file version determines
the field layout. It uses a single flat grid instead of chunks.
No known .raw files use this format in any shipped client.

The `map_version` parameter must be provided externally (from the
zone's LUZ file version). The client's `OpenTerrain` (0x01048080)
calls four functions in sequence, each gated on map_version.

See `raw.ksy` for the chunked format used by LUZ version >= 30.
params:
- id: map_version
type: u4
seq:
# --- Heightmap (FUN_01013db0) ---
- id: width
type: u4
if: map_version >= 11
- id: height
type: u4
if: map_version >= 11
- id: scale
type: f4
if: map_version >= 12
doc: Heightmap scale factor; v<12 uses hardcoded 3.0
- id: height_map_u16
type: u2
repeat: expr
repeat-expr: total_cells
if: map_version < 4
doc: v<4 u16 heights, scaled to float by multiplying with scale
- id: height_map_f32
type: f4
repeat: expr
repeat-expr: total_cells
if: map_version >= 4
doc: >
v4+ f32 heights. v4-10 are pre-scaled (multiply by scale factor
at load time); v11+ are already in world units.

# --- Color map (FUN_01013880) ---
- id: color_map_argb
type: u4
repeat: expr
repeat-expr: total_cells
if: map_version == 3
doc: v3 packed ARGB color per cell
- id: color_map_float_rgba
type: f4
repeat: expr
repeat-expr: total_cells * 4
if: map_version >= 4 and map_version < 11
doc: >
v4-10 float RGBA per cell (4 floats each).
v4-7 values are scaled by a constant at load time;
v8-10 are used directly.
- id: color_map_bytes
size: total_cells * 4
if: map_version >= 11
doc: v11+ RGBA bytes per cell (4 bytes each)
- id: uv_coords
type: f4
repeat: expr
repeat-expr: total_cells * 2
if: map_version >= 4
doc: v4+ UV coordinates per cell (2 floats each)

# --- Texture/material (FUN_01013640) ---
- id: material_ids
type: u4
repeat: expr
repeat-expr: total_cells
if: map_version >= 6 and map_version < 10
doc: v6-9 material ID per cell
- id: material_structs
size: 20
repeat: expr
repeat-expr: total_cells
if: map_version >= 10
doc: >
v10+ material struct per cell (20 bytes):
u1 materialId, f32 blendWeight, 3x f32 blend weights

# --- Scene map (FUN_01013550) ---
- id: scene_palette
size: 1024
if: map_version >= 20
doc: v20+ scene palette/header (1024 bytes, usage unknown)
- id: scene_map
size: total_cells
if: map_version >= 20
doc: v20+ u1 scene ID per cell
instances:
default_width:
value: 1280
default_height:
value: 1280
actual_width:
value: 'map_version >= 11 ? width : default_width'
actual_height:
value: 'map_version >= 11 ? height : default_height'
total_cells:
value: actual_width * actual_height