As a hobbyist, I’m trying to reverse engineer the level format of the racing game Turbo Sliders Unlimited. The current version of the game is v1.01.3. This article is a very incomplete description of what can be done, but maybe it helps someone to read, modify or create levels.
On Linux, your levels can be found at ~/.config/unity3d/Turbo Sliders/Unlimited/76000000000000000/Levels/
where the number is the user ID of your Steam account. You can look up your steamID64 (Dec) on Steam ID Finder or just match any folder. The levels are stored as ZIP 2.0 archives with the file ending .lvl
. Their compression method is Deflate.
The Levels folder may also contain a few .lvl.bak
files. These backup files get created whenever you overwrite a level using the in-game editor.
To unzip my existing my-level.lvl
into a temporary folder, I use the following Linux terminal command:
unzip my-level.lvl -d tmp
To compress our changes back into an archive, I use:
zip -j my-level.lvl tmp/*
We find the following files inside a level archive:
- checkpoints.bin
- colors.bin
- editor.bin
- location.bin
- materials.bin
- nature.bin
- objects.bin
- properties.bin
- roads.bin
- thumb1.jpg
- thumb2.jpg
The thumbnail files thumb1.jpg and thumb2.jpg are optional files. All other files seem to be required.
The binary files use Little-endian encoding for integers and floats. The most common data size seems to be 32 bit (4 bytes).
Properties
The description may contain Line Feed (LF, 0x0a) as a new line character.
Meaning:
- 0x7b 0x00 0x06 0x00 0x65 0x00 (unknown bytes)
- first half of the “guid”, 64-bit unsigned integer
- a new one is generated on each save
- bits in order
- 2 bits, just 0b00
- 44 bits, timestamp since 2020-01-01 midnight UTC in milliseconds
- 12 bits, random
- 6 bits, object type (level / vehicle / …) and “guid” type (null / built-in / unpublished / published)
- set this to 0b000010
- 0x94 0x00 0x39 0x02 0x9e 0x03 0x01 0x00 0x10 0x01 (second half of the “guid”, 64-bit unsigned integer)
- This is some static value based on the object type and “guid” type.
- 0x76 0xe9 0xbf 0xfc 0xd3 0x33 0xdd 0x08 (unknown bytes)
- indicator optional values
- bit 0 (dec 1): level name
- bit 1 (dec 2): true (unknown)
- bit 2 (dec 4): level type
- bit 3 (dec 8): description
- bit 4 (dec 16): true (unknown)
- bit 5 (dec 32): author name
- optional values
- level name
- byte length of the level name, unsigned 32-bit integer
- level name, utf-8 string
- 0x39 0x02 0x9e 0x03 0x01 0x00 0x10 0x01 (unknown bytes)
- level type, unsigned 32-bit integer
- 0 = Circuit
- 1 = Special Stage
- level description
- byte length of the level description, unsigned 32-bit integer
- level description, utf-8 string
- 0x05 0x00 0x00 0x00 (unknown bytes)
- author name
- byte length of the author name, unsigned 32-bit integer
- author name, utf-8 string
- level name
- 0x00 0x00 (2 unknown bytes)
- indicator optional tag values
- bit 0 (dec 1): style
- bit 1 (dec 2): size
- bit 2 (dec 4): curviness
- bit 3 (dec 8): difficulty
- bit 4 (dec 16): bumpiness
- bit 5 (dec 32): confirm tags ok (boolean, no additional value follows)
- optional values
- style, 8-bit integer
- size, 8-bit integer
- curviness, 8-bit integer
- difficulty, 8-bit integer
- bumpiness, 8-bit integer
Location
This is the empty default square island in a hex inspector:
90 03 02 00 80 00 0e 40 01 00 00 00 00 00 00
Meaning:
- 0x90 0x03 0x02 0x00 (4 unknown bytes, format version header?)
- indicator about optional sun values
- bit 2 (dec 4) active = no clouds
- 0x80 = 0 bytes follow
- 0x91 = 8 bytes follow: time, sun direction
- optional values
- time, 32-bit float (min: 5, max: 19)
- sun direction, 32-bit float (min: 0, max: 360)
- 0x00 0x0e 0x40 0x01 (4 unknown bytes)
- 0x00 0x00 0x00 0x00 0x00 (5 unknown bytes)
- indicator for optional wind values
- bit 3 (dec 8) active = wind multiplier follows
- 0x00 = 0 bytes follow
- 0x07 = 12 bytes follow: speed, frequency, turbulence
- 0x0F = 16 bytes follow: speed, frequency, turbulence, multipler
- optional values
- wind speed, 32-bit float (min: 0, max: 5)
- wind frequency, 32-bit float (min: 0, max: 5)
- wind turbulence, 32-bit float (min: 0, max: 5)
- wind multiplier, 32-bit float (min: 1, max: 5)
Nature
This file sets the water level, trees and texture of the edge of the level.
The edge of the map is a giant square with slanted corners. If you enable the water, the texture will be visible undernear the transparent water.
This is the empty default nature in a hex inspector:
71 00 04 00 00 00 00 00 00 00 00 56 34 01 00 00 00 00 00 00 00 00
Meaning:
- 0x71 0x00 (unknown format version 113)
- 0x04 0x00 (unknown format version 4)
- indicator about water and trees - 0x21 = no water; 0x00, 0x01, 0x0B = water
- 0x00 = 6 bytes follow
- 0x21 = 10 bytes follow: tree density
- optional values
- tree density, 32-bit integer, (min: 0, max: 1000)
- tree level, 32-bit float, (min: -75, max: 75)
- tree types filter, 32-bit integer (min: 0, max: 65535)
- water level, 32-bit float, (min: -75, max: 75)
- deep water, 32-bit float, (min: 0, max: 10)
- 0x56 0x34 0x01 0x00 0x00 0x00 0x00 (7 unknown bytes, header for custom trees?)
- number of custom trees, 32-bit integer
- per custom tree
- data type (0x1E = default tree)
- If data type == 0x1F, tree type (min: 1, max: 15), decreased by 1 compared to the in-game editor
- types 1 to 4: only leaves at the treetop
- types 5 and 6: needle trees
- types 7 and 8: yellow leaf trees
- types 9 and 10: bended needle trees
- type 11: giant yellow leaf tree
- types 12 to 15: dead trees
- x position, 32-bit float
- y position, 32-bit float
- z position, 32-bit float
- rotation, 32-bit float
- height scale, 32-bit float
- width scale, 32-bit float
- 0x00 (unknown byte)
Nature complexity
The tree density affects how many trees will be placed procedurally. You can also place up to 500 custom trees. Every tree has a complexity of 1 and the water has a complexity of 300. The total nature of a level must not exceed a complexity of 900.
If the combined number of procedural trees and custom trees exceeds 500, the game counts further procedural trees towards the complexity limit of objects.
Roads
The file roads.bin
contains a list of both roads and sequences. Both have properties and a list of markers.
This is the empty default list of roads in a hex inspector:
97 03 01 00 00 01 00 00 00 06 00 00 80 00 01 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00
Meaning:
- 0x97 0x03 0x01 0x00 (4 unknown bytes, format version header?)
- indicator about roads, byte
- bit 0 (dec 1): raise offset
- bit 1 (dec 2): built roads (boolean, no value follows)
- optional values
- raise offset, 32-bit float (default: 0.1)
- number of roads, 32-bit integer
- per road
- 0x06 0x00 0x00 (3 unknown bytes)
- indicator about road, byte
- bit 0 (dec 1) active = Closed Loop
- bit 1 (dec 2) active = Width follows
- bit 2 (dec 4) active = Resolution follows
- bit 7 (dec 128) (unknown, always on?, live updates?)
- optional values
- width, 32-bit float (min: 1, max: 100)
- resolution, 32-bit float (min: unknown, max: unknown)
- indicator about road, byte
- bit 0 (dec 1) active = Closed Loop
- bit 1 (dec 2) active = Width follows
- bit 2 (dec 4) active = Resolution follows
- bit 7 (dec 128) (unknown, always on?, live updates?)
- optional values
- width, 32-bit float (min: 1, max: 100)
- resolution, 32-bit float (min: unknown, max: unknown)
- 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 (unknown bytes)
- number of markers, 32-bit integer
- per marker
- indicator about road, byte
- bit 0 (dec 1) active = Position follows
- bit 1 (dec 2) active = Type is Straight XZ, Straight XYZ or Cirular
- bit 2 (dec 4) active = Spline Strength follows
- optional values
- position
- x position, 32-bit float
- y position, 32-bit float
- z position, 32-bit float
- type
- 1 = Straight XZ
- 2 = Straight XYZ
- 3 = Circular
- spline strength, 32-bit float
- position
- likely missing values
- indicator about shape, byte
- bit 0 (dec 1) active = unknown
- bit 1 (dec 2) active = unknown
- bit 2 (dec 4) active = unknown
- bit 3 (dec 8) active = unknown
- optional values
- width, 32-bit float (min: 0.25, max: 4, default: 1)
- side offset, 32-bit float (min: -20, max: 20, default: 0)
- tilting, 32-bit float (min: -80, max: 80, default: 0)
- tilting center, 32-bit float (min: 0, max: 1, default: 0)
- 0x00 (unknown byte)
- indicator about bridge, byte
- bit 0 (dec 1) active = unknown
- bit 1 (dec 2) active = unknown
- bit 2 (dec 4) active = unknown
- bit 3 (dec 8) active = unknown
- bit 4 (dec 16) active = unknown
- optional values
- type, byte
- 1 = simple
- start offset, 32-bit float (min: 0.25, max: 4, default: 0)
- end offset, 32-bit float (min: -20, max: 20, default: 0)
- start level distance, 32-bit float (min: -80, max: 80, default: 10)
- end level distance, 32-bit float (min: 0, max: 1, default: 10)
- type, byte
- curb
- optional values
- type, enum (“Default”)
- left
- right
- start left, 32-bit float (min: -100, max: 100, default: 0)
- start right, 32-bit float (min: -100, max: 100, default: 0)
- end left, 32-bit float (min: -100, max: 100, default: 0)
- end right, 32-bit float (min: -100, max: 100, default: 0)
- move left, 32-bit float (min: -5, max: 20, default: 0)
- move right, 32-bit float (min: -5, max: 20, default: 0)
- optional values
- barrier
- optional values
- type, enum (“Concrete Low”, “Concrete”, “Guard Rail”)
- left
- right
- start left, 32-bit float (min: -100, max: 100, default: 0)
- start right, 32-bit float (min: -100, max: 100, default: 0)
- end left, 32-bit float (min: -100, max: 100, default: 0)
- end right, 32-bit float (min: -100, max: 100, default: 0)
- move left, 32-bit float (min: -5, max: 20, defaul: 0)
- move right, 32-bit float (min: -5, max: 20, defaul: 0)
- optional values
- side area
- optional values
- left indent, 32-bit float (min: 0.75, max: 20, default: 2.5)
- right indent, 32-bit float (min: 0.75, max: 20, default: 2.5)
- left smoothing, 32-bit float (min: 0, max: 50, default: 5)
- right smoothing, 32-bit float (min: 0, max: 50, default: 5)
- optional values
- indicator about road, byte
Checkpoints
Checkpoints have two positions and a middle. The right end comes first and is referred to as position 1. The middle is inbetween both positions where 0 means that it’s on the right end and 1 means that it’s on the left end.
Meaning:
- 0xeb 0x02 0x02 0x00 (4 unknown bytes, format version header?)
- number of checkpoints, 32-bit integer
- per checkpoint
- 1st indicator about the checkpoint, byte
- bit 0 (dec 1) active = Position 1 follows
- bit 1 (dec 2) active = Position 2 follows
- bit 2 (dec 4) active = Middle follows
- bit 3 (dec 8) active = Skip follows
- bit 4 (dec 16) active = Alt Skip follows
- bit 5 (dec 32) active = Curve Shape follows
- bit 6 (dec 64) active = Type follows
- bit 7 (dec 128): true
- optional values
- position 1
- x position, 32-bit float
- y position, 32-bit float
- z position, 32-bit float
- position 2
- x position, 32-bit float
- y position, 32-bit float
- z position, 32-bit float
- middle, 32-bit float (min: 0, max: 1, default: 0.5)
- skip, 32-bit integer (default: 0)
- alt skip, 32-bit integer (default: -1)
- curve shape, 32-bit float (default: 1)
- type, 32-bit integer
- 0 = Sector
- 2 = Minor
- position 1
- 2nd indicator about the checkpoint, byte
- bit 0 (dec 1) active = Height follows
- optional values
- height, 32-bit float (default: 0)
- 1st indicator about spawning, byte
- bit 0 (dec 1) active = Enabled (boolean, no value follows)
- bit 1 (dec 2) active = Row Size follows
- bit 2 (dec 4) active = Back Offset First follows
- bit 3 (dec 8) active = Back Offset follows
- bit 4 (dec 16) active = Back Offset Row follows
- bit 5 (dec 32) active = Side Offset follows
- bit 6 (dec 64) active = Height follows
- optional values
- row size, 32-bit integer (default: 2)
- back offset first, 32-bit float (default: 4)
- back offset, 32-bit float (default: 5)
- back offset row, 32-bit float (default: 0)
- side offset, 32-bit float (default: 5)
- height, 32-bit float (default: 4)
- 2nd indicator about spawning, byte
- bit 0 (dec 1) active = Ignore Route (boolean, no value follows)
- 1st indicator about the checkpoint, byte
Thumbnails
A level may contain two thumbnail files which commonly only differ in their resolution. The game offers to take a preview screenshot of the level which will become the thumbnail.
- thumb1.jpg: 1280x720
- thumb2.jpg: 320x180
The application file
says: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, baseline, precision 8, components 3. The common file sizes are around 200 KiB for thumb1.jpg and 12 KiB for thumb2.jpg.