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/SByte share token 0x0B and Fract16/Short share 0x0D. Context determines interpretation.

Byte Order

All multi-byte values are little-endian.

File Structure Pattern

Every format class follows the same pattern:

  1. Read a block ID byte (format-specific, typically starting at 0x27)
  2. Switch on the block ID to read the appropriate data structure
  3. 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.