Skip to content

Commit f672712

Browse files
aronwk-aaronclaude
andcommitted
fix: update raw.ksy with verified field names, v<32 support, missing color_a
Changes verified against Ghidra RE of ReadNewTerrainFormat (0x0103b920), RAWReadHeightmap, RAWReadColorandLightMaps, RAWReadFlairData, RAWReadSceneMap, RAWReadMeshData, FUN_0103aaf0 (blend map reader), and the four legacy terrain functions (FUN_01013db0, FUN_01013880, FUN_01013640, FUN_01013550) in legouniverse.exe 1.10.64. Validated against all 309 .raw files across multiple client versions (v31 and v32) — 309/309 pass. Chunked format (v30+): - Rename density → scale (matches client field name) - Rename diffuse_res → color_map_resolution, diffuse_res_pixels → color_map_pixels - Rename bits → blend_channel_mask - Add color_a (u1) to flair_attributes (35→36 byte fix) - Remove size: 36 override on flairs - Add version/vert_size guards on mesh data - Replace unknown1/unknown2 with proper v<32 definitions Legacy flat-grid format (v<30): - Document the legacy format in a legacy_grid reference type - No file header; zone LUZ version determines layout - Four sub-readers: heightmap, color map, texture, scene map - Version-dependent field sizes across v0-v29 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent eb15852 commit f672712

1 file changed

Lines changed: 98 additions & 17 deletions

File tree

files/raw.ksy

Lines changed: 98 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,32 @@ meta:
44
endian: le
55
imports:
66
- ../common/common
7+
doc: >
8+
LEGO Universe .raw terrain file format.
9+
10+
There are two distinct formats sharing the .raw extension:
11+
12+
1. **Chunked format** (zone LUZ version >= 30): Self-describing with a
13+
u16 version + u1 dev header, followed by chunked terrain data.
14+
This is the format described by the top-level seq below.
15+
File versions 31 and 32 are known to exist.
16+
17+
2. **Legacy flat-grid format** (zone LUZ version < 30): No file header.
18+
The zone's LUZ file version determines the field layout. This format
19+
uses a single flat grid instead of chunks. Since the file is not
20+
self-describing, the legacy format cannot be expressed in this ksy
21+
and is documented in the `legacy_grid` type below for reference.
22+
No known .raw files use this format in any shipped client.
23+
24+
The client's `OpenTerrain` function (0x01048080) selects the reader:
25+
mapVersion < 30 → legacy flat-grid reader
26+
mapVersion >= 30 → `ReadNewTerrainFormat` (chunked reader)
727
seq:
828
- id: version
929
type: u2
1030
- id: dev
1131
type: u1
32+
doc: Must be 0 for valid terrain data; non-zero aborts loading
1233
- id: num_chunks
1334
type: u4
1435
if: dev == 0
@@ -43,73 +64,92 @@ types:
4364
type: u4
4465
repeat: expr
4566
repeat-expr: 4
46-
- id: density
67+
- id: scale
4768
type: f4
69+
doc: Heightmap scale factor, used to transform grid coords to world coords
4870
- id: height_map
4971
type: f4
5072
repeat: expr
5173
repeat-expr: width * height
52-
- id: diffuse_res
74+
- id: color_map_resolution
5375
type: u4
5476
if: _root.version >= 32
55-
- id: diffuse_res_pixels
56-
size: diffuse_res * diffuse_res * 4
77+
doc: Resolution of the color/diffuse map
78+
- id: color_map_pixels
79+
size: color_map_resolution * color_map_resolution * 4
5780
if: _root.version >= 32
58-
doc: RGBA
59-
- id: unknown1
60-
type: u1
61-
repeat: eos
81+
doc: RGBA color map pixels (raw block)
82+
- id: color_map_pixels_legacy
83+
size: width * width * 4
6284
if: _root.version < 32
63-
doc: todo
85+
doc: >
86+
v<32 color map. Client reads width*width pixels (4 bytes each)
87+
with per-pixel BGRA byte swizzle. colorMapResolution = width - 1;
88+
only the inner (width-1)^2 pixels are used.
6489
- id: diffuse_map_dds_size
6590
type: u4
6691
if: _root.version >= 32
6792
- id: diffuse_map_dds
6893
size: diffuse_map_dds_size
6994
if: _root.version >= 32
95+
doc: DDS texture data for diffuse/light map
7096
- id: blend_res
7197
type: u4
7298
- id: blend_pixels
7399
size: blend_res * blend_res * 4
74-
- id: bits
100+
doc: >
101+
Blend/texture map pixels. v>=32 reads as raw RGBA block;
102+
v<32 reads per-pixel as B,G,R,A (byte-swizzled).
103+
- id: blend_channel_mask
75104
type: u1
76105
if: _root.version >= 32
106+
doc: Bitmask of active detail textures (bits 0-3)
77107
- id: blend_map_dds_size
78108
type: u4
79109
if: _root.version >= 32
80110
- id: blend_map_dds
81111
size: blend_map_dds_size
82112
if: _root.version >= 32
113+
doc: DDS texture data for blend map (DXT5)
83114
- id: num_flairs
84115
type: u4
85116
- id: flairs
86117
type: flair_attributes
87-
size: 36
88118
repeat: expr
89119
repeat-expr: num_flairs
90120
- id: scene_map
91-
size: diffuse_res * diffuse_res
121+
size: color_map_resolution * color_map_resolution
92122
if: _root.version >= 32
93-
- id: unknown2
94-
type: u1
95-
repeat: eos
96-
if: _root.version < 32
97-
doc: todo
123+
doc: Per-pixel scene ID assignment, indexes into LUZ scene list
124+
- id: scene_map_v31
125+
size: width * width
126+
if: _root.version == 31
127+
doc: >
128+
v31 scene map. Allocates (colorMapRes+1)^2 where colorMapRes=width-1.
129+
Client reads (colorMapRes+1)^2 cells; inner colorMapRes^2 cells
130+
contain scene IDs, border cells are skipped/discarded.
131+
- id: scene_map_skip
132+
size: 1
133+
if: _root.version < 31
134+
doc: v<31 skips 1 byte; scene map is zero-filled by client
98135
- id: vert_size
99136
type: u4
100137
if: _root.version >= 32
101138
- id: mesh_vert_usage
102139
type: u2
103140
repeat: expr
104141
repeat-expr: vert_size
142+
if: _root.version >= 32 and vert_size != 0
105143
- id: mesh_vert_size
106144
type: u2
107145
repeat: expr
108146
repeat-expr: 16
147+
if: _root.version >= 32 and vert_size != 0
109148
- id: mesh_tri
110149
type: mesh_tri
111150
repeat: expr
112151
repeat-expr: 16
152+
if: _root.version >= 32 and vert_size != 0
113153

114154
flair_attributes:
115155
seq:
@@ -127,6 +167,8 @@ types:
127167
type: u1
128168
- id: color_b
129169
type: u1
170+
- id: color_a
171+
type: u1
130172
mesh_tri:
131173
seq:
132174
- id: mesh_tri_list_size
@@ -135,3 +177,42 @@ types:
135177
type: u2
136178
repeat: expr
137179
repeat-expr: mesh_tri_list_size
180+
181+
legacy_grid:
182+
doc: >
183+
Legacy flat-grid terrain format (zone LUZ version < 30).
184+
NOT parseable from this ksy — requires the zone's LUZ version
185+
as external context since the file has no header. Documented
186+
here for reference only.
187+
188+
This format uses a single flat grid of `width * height` cells
189+
instead of the chunked layout. No known .raw files use this
190+
format in any shipped client.
191+
192+
The client's OpenTerrain (0x01048080) calls four functions in
193+
sequence, each gated on the zone's map version:
194+
195+
FUN_01013db0 — Heightmap:
196+
v < 4: width = height = 1280; u16 heights (scaled to float)
197+
v 4-10: width = height = 1280; f32 heights (v<11 scaled)
198+
v 11+: u32 width, u32 height from file
199+
v 12+: f32 scale from file (v<12 uses hardcoded 3.0)
200+
All: totalCells = width * height; float heightmap[totalCells]
201+
202+
FUN_01013880 — Color map:
203+
v < 3: no data (defaults)
204+
v 3: u32 packed ARGB per cell
205+
v 4-7: 4x f32 RGBA per cell (scaled by constant)
206+
v 8-10: 4x f32 RGBA per cell (unscaled)
207+
v 11+: 4x u1 RGBA per cell
208+
v 4+: also 2x f32 UV per cell
209+
210+
FUN_01013640 — Texture/material:
211+
v < 6: no data
212+
v 6-9: u32 material ID per cell
213+
v 10+: 20-byte struct per cell (materialId + blend weights)
214+
215+
FUN_01013550 — Scene map:
216+
v < 20: no data (zero-filled)
217+
v 20+: 1024-byte palette, then u1 scene ID per cell
218+
seq: []

0 commit comments

Comments
 (0)