Cart binary format

.sprite carts are TLV-structured binary blobs targeting one of two machines — SC8 or GameTank — selected by the header's machine_id byte. Total in-cap cart size depends on the header's target_medium byte: 32 KB by default (the SC8 norm), or up to 2 MB for GameTank carts targeting flash-2m. Source code, when present, ships in a separate SRC section that sits outside the cap, on both machines.

Header (80 bytes)

offset  size  field
------  ----  ----------
   0     4    magic = "SPRT"
   4     2    version       (u16 LE; v1 today)
   6     1    machine_id    (u8;  0x01=SC8, 0x02=GameTank)
   7     1    palette_id    (u8;  SC8: 0=PICO-8, 1=DB16, 2=Sweetie 16; ignored by GameTank)
   8     2    flags         (u16 LE; reserved, 0 in v1)
  10     1    target_medium (u8;  0=flat32k, 1=micro-8k, 2=flash-2m)
  11     1    reserved_1[1] (all zero)
  12    32    title         (NUL-padded UTF-8)
  44    32    author        (NUL-padded UTF-8)
  76     4    reserved_2    (all zero)
  • magic — fixed bytes "SPRT".
  • version — cart format version (u16 LE; currently 1).
  • machine_id — target machine: 0x01 = SC8 (internal code name M8), 0x02 = GameTank.
  • palette_id — SC8 only: 0 = PICO-8, 1 = DB16, 2 = Sweetie 16 (see Palettes). GameTank carts ignore this byte — their color model is a fixed 256-entry LUT, not a per-cart choice. Was reserved_0 pre-P3.6.
  • flags — u16 LE; reserved, all zero in v1.
  • title, author — 32 bytes each, NUL-padded UTF-8.
  • target_medium — u8; selects the cart's storage medium / size cap: 0 = flat 32 KB (SC8 default), 1 = micro-8k (8 KB EEPROM), 2 = flash-2m (2 MB banked flash, GameTank default). Was the first byte of reserved_1 pre-Task 2.1.
  • reserved_1[1], reserved_2 — all zero; reserved for future header growth without bumping the format version.

TLV sections

Each section: 4-byte tag + 4-byte LE length + payload.

TagCapContents
CODE16 KBCompiled bytecode (Op stream + word table).
SPRT8 KB (SC8) / up to 512 KB (GameTank)SC8: up to 256 tiles × 8×8 × 4-bit indices. GameTank: up to 8 sprite sheets × 256×256 8-bit indices, blitted with blit (see HCALLs for the wire format or Sprite sheets & blit for a worked example).
SOND8 KBTracker data — instruments + 32×5 patterns + tempo. GameTank instruments may reference SMPL slots instead of a synth voice.
SYMS256 BSymbol table — exported lifecycle word names + bytecode addresses. Runner reads init (run-once at load) and update (per-frame). See below.
METAJSON metadata — formerly carried update word address; SYMS owns that now. Retained for back-compat and future cart-level metadata.
RAMI8 KBRAM-init bytes for s"" string literals (P2.4).
SMPL1 MBPCM sample data — GameTank only; SC8 carts never emit this section. Authored in the Samples tab; see the Samples tutorial and Sounds editor.
SRC unboundedOriginal Forth source — outside the size cap on both machines. Used by /studio's Load .sprite.

SYMS — lifecycle vocabulary

The SYMS section maps reserved Forth word names to bytecode addresses. Each entry is {name_len:u8, name:[u8;name_len], addr:u16 LE}. The runner consults SYMS at cart load to wire two lifecycle hooks:

  • init — called once at cart load, before the first frame. Optional; useful for one-time RAM setup or state seeding.
  • update — called every frame at 60 Hz. Required for most carts (a cart without update still presents frames but runs no per-frame code).

Other names in the vocabulary are reserved for future hooks (on-input, on-pause, on-save, etc.). Compilers ignore non-vocabulary names; the section is capped at 256 B (~7 entries with 32-byte names; many more with short names).

Carts that pre-date SYMS carry update's address in META JSON as {"update": <addr>}. The runner falls back to that path when SYMS is absent so older carts keep working.

Total size budget

The in-cap total (header + all capped TLV sections — CODE, SPRT, SOND, SYMS, META, RAMI, SMPL) is bounded by target_medium: 32 KB by default (SC8 carts always use this — it's their only option), 8 KB for micro-8k, or 2 MB for flash-2m (GameTank's default, needed to fit multiple 256×256 sprite sheets and sample data). SRC sits outside the in-cap total on both machines and may grow arbitrarily.