# 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<N>.png`.
2. The Makefile bakes per-target via `tools/assetbake/assetbake.py
   --type tile --target <port> tbank<N>.png tbank<N>.tbk`. Output
   lands in `examples/spacetaxi/generated/<port>/tiles/` and is
   staged into the runtime tree at `build/<port>/.../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.
