# Space Taxi level .dat format (STL2) A small custom binary format that `stLevelLoad()` reads at scene boot. Output files land in `examples/spacetaxi/generated/levels/` (from `romToLevel.py` for the 24 canonical C64 levels, or from `mkstlevel` for hand-authored levels in `assets/levels/*.txt`). The build copies them under `DATA/levels/levelNN.dat` in the runtime asset bundle. All multi-byte fields are little-endian. No compression; ~2 KB per level. | Offset | Type | Field | |-------:|:----------|:-----------------------------------------------| | 0 | 4 bytes | magic `S T L 2` | | 4 | u8 | nameLen (0..23) | | 5 | char[N] | name (no NUL; max 23 chars) | | 5+N | u8 | tileBankId | | ... | u8 | musicId (UNUSED -- C64 gameplay is silent; see VERIFIED.md) | | ... | u8 | bgColor (palette slot) | | ... | u8 | borderColor (palette slot, also HUD-band fill) | | ... | u8 | taxiSpawnTileX | | ... | u8 | taxiSpawnTileY | | ... | u8 | xAccel (horizontal thrust magnitude / frame) | | ... | u8 | yAccel (vertical thrust magnitude / frame) | | ... | i8 | xGrav (constant horizontal accel; side-wind on levels P, U) | | ... | i8 | yGrav (constant vertical accel; anti-gravity on level K = -7) | | ... | u8 | bgColor1 ($D022, VIC multicolor -- UNUSED) | | ... | u8 | bgColor2 ($D023, VIC multicolor -- UNUSED) | | ... | u8 | bgColor3 ($D024, VIC multicolor -- UNUSED) | | ... | u8 | spriteMc0 ($D025, sprite multicolor -- UNUSED) | | ... | u8 | spriteMc1 ($D026, sprite multicolor -- UNUSED) | | ... | u8 | sprite0Color ($D027, cab fallback color) | | ... | u8 | sprite1Color ($D028, flame fallback color) | | ... | u8 | padCount (0..10) | | ... | pad[] | padCount * 4 bytes: letter, tileX, tileY, tileW | | ... | u8 | fareCount (0..16) | | ... | fare[] | fareCount * 2 bytes: spawnPad, destPad | | ... | u8[40*25] | tilemap (row-major, full 25 rows) | | ... | u8[40*25] | colormap (row-major, palette slot per cell) | Notes: - `xAccel/yAccel/xGrav/yGrav` mirror the C64 per-level templates at `$7D8F-$7D96`. Side-wind levels P (`xGrav = +4`) and U (`+2`); the anti-gravity level K (`yGrav = -7`) makes the cab drift upward without input. See `VERIFIED.md` for the emulator-traced extracts. - `musicId` is preserved for format symmetry only; the C64 original has no gameplay music (only title/score-screen jingles). - The five VIC multicolor fields are preserved so the .dat is a faithful byte-for-byte capture of the C64 `$7D00-$7D08` block. The port renders in single-color mode and ignores them at runtime. - Pads are 4 bytes (letter + 3 tile coords); there is no patience byte on fares -- Space Taxi proper has no patience timeout, and the emulator trace at `$71CE/$7213` confirmed the only gating is the player-selectable fare target at the title screen. ## Tile-index conventions (in the tilemap byte) Indexes 0..255 reference the level's active tile bank. Reserved ranges: | Range | Meaning | |----------|---------------------------------------------------------| | 0 | empty (sky / interior space; non-solid) | | 1..63 | solid (walls, ceilings, support structures) | | 64..127 | landing-pad surfaces (also solid; pad collisions live here) | | 128..255 | decorative non-solid (lights, signs, animation frames) | The engine's `isSolidAt()` uses this convention. If you redesign a tile bank, keep the indexing consistent so the physics keeps working without changes. ## Authoring pipeline 1. Author a 256-tile (or smaller) tile sheet as an indexed PNG. Each tile is 8x8 px. Arrange in a grid; the bank loader assumes row- major, tile-index = `ty * tilesPerRow + tx`. Drop the PNG at `examples/spacetaxi/assets/tiles/tbank.png`. 2. The Makefile bakes per-target via `tools/assetbake/assetbake.py --type tile --target tbank.png tbank.tbk`. Output lands in `examples/spacetaxi/generated//tiles/` and is staged into the runtime tree at `build//.../DATA/tiles/`. 3. Author each level layout in a text editor or grid tool, save as a .dat per this spec. The helper `examples/spacetaxi/mkstlevel` converts from a human-readable text grid to .dat. The 24 canonical C64 levels are emitted by `stuff/spacetaxi/romToLevel.py` directly from a raw VICE dump of the original .prg. ## Naming Use the original game's level names as the `name` field (uppercase ASCII, max 23 chars). The HUD displays this at the bottom-right of the screen.