Binary Encoding - DustStormPettigrew/LibLR1 GitHub Wiki
Binary Encoding
All token-based formats in LEGO Racers share a common serialization layer implemented in LRBinaryReader/LRBinaryWriter and BinaryFileHelper.
Token Enum
Every typed value in the binary stream is prefixed by a single-byte token:
| Token | Hex | Size | Description |
|---|---|---|---|
String |
0x02 |
Variable | Null-terminated ASCII string |
Float |
0x03 |
4 bytes | IEEE 754 single-precision float |
Int32 |
0x04 |
4 bytes | 32-bit signed integer |
LeftCurly |
0x05 |
0 | Block open { |
RightCurly |
0x06 |
0 | Block close } |
LeftBracket |
0x07 |
0 | Array header open [ |
RightBracket |
0x08 |
0 | Array header close ] |
Fract8 / SByte |
0x0B |
1 byte | 8-bit fixed-point (รท16) or signed byte |
Byte |
0x0C |
1 byte | Unsigned byte |
Fract16 / Short |
0x0D |
2 bytes | 16-bit fixed-point (รท256) or signed short |
UShort |
0x0E |
2 bytes | Unsigned 16-bit integer |
Array |
0x14 |
Variable | Compression pass only โ not in decompressed stream |
Struct |
0x16 |
Variable | Compression pass only โ struct definition |
Note:
Fract8/SByteshare token0x0BandFract16/Shortshare0x0D. Context determines interpretation.
Byte Order
All multi-byte values are little-endian.
File Structure Pattern
Every format class follows the same pattern:
- Read a block ID byte (format-specific, typically starting at
0x27) - Switch on the block ID to read the appropriate data structure
- Repeat until end of stream
Within blocks, property ID bytes identify individual fields. Properties are read until a RightCurly token is encountered.
Compression / Decompression
Binary files on disk may be compressed using a struct-based compression scheme. BinaryFileHelper.Decompress() handles this transparently:
0x16(Struct) โ Defines a reusable struct template:[struct_id] [field_count] [field_token_types...]0x14(Array) โ Inline array:[array_length as int16] [element_token_type] [elements...]- Struct IDs encountered later in the stream are expanded using the stored template
After decompression, the stream contains only the basic tokens (0x02โ0x0E) and format-specific block/property IDs (0x27+).
Common Data Structures
Arrays
[array_length_token] // 0x07 (LeftBracket)
[Int32] count // 0x04 + 4-byte length
[end_length] // 0x08 (RightBracket)
[begin_data] // 0x05 (LeftCurly)
element[0]
element[1]
...
[end_data] // 0x06 (RightCurly)
Struct Arrays
Same as arrays, but each element is wrapped: [type_byte] { element_data }.
Dictionaries
Like struct arrays, but each element has an optional string key:
[type_byte]
"key_name" // optional โ if next token isn't String, uses index as key
{ element_data }
Integral Type Selection
ReadIntegralWithHeader() accepts any of: SByte, Byte, Int32, UShort, Short. The file format picks the smallest type that fits the value. This is why the same field may use different token types in different files.
See Primitive Types for the composite types built on these tokens.