5.5 KiB

Cartridges

Domain: cartridge package Function: normative

This chapter defines the cartridge contract consumed by the current runtime.

1 Scope

A cartridge is the distributable unit loaded by firmware/runtime.

In the current implementation, the supported dev/runtime form is a directory containing:

  • manifest.json
  • program.pbx
  • optional assets.pa

The loader also recognizes .pmc as a future packaged form, but packaged cartridge loading is not implemented yet.

2 Cartridge Metadata

The runtime currently expects the following manifest fields:

{
  "magic": "PMTU",
  "cartridge_version": 1,
  "app_id": 1234,
  "title": "My Game",
  "app_version": "1.0.0",
  "app_mode": "Game"
}

Additional manifest-supported fields include:

  • capabilities

3 Required Fields

Current required manifest fields:

  • magic
  • cartridge_version
  • app_id
  • title
  • app_version
  • app_mode

Current required file payloads:

  • program.pbx

Optional file payloads:

  • assets.pa

4 Runtime Validation Rules

The current loader validates:

  • magic == "PMTU"
  • cartridge_version == 1
  • manifest parse validity
  • capability normalization
  • presence of program.pbx
  • when Asset capability is declared, presence of valid assets.pa before asset bootstrap

If validation fails, cartridge loading is rejected before execution.

5 App Mode and Boot Protocol

app_mode controls firmware launch behavior:

  • Game
  • System

app_mode is the runtime profile discriminator. No separate manifest target field participates in profile selection.

Cartridge boot is protocol-driven, not manifest-driven.

The executable entrypoint of a valid cartridge is always func_id = 0.

This means:

  • manifest.json does not select the callable to execute;
  • firmware/runtime loads the cartridge and starts execution from func_id = 0;
  • nominal exports may exist for linking or introspection, but they do not hold boot authority.

5.1 Runtime Profiles

Game and System are distinct runtime profiles.

Game cartridges use the game pipeline. The game profile owns the public game surfaces for frame composition, GFX, game input, banks, sprites, and memory-card-style persistence.

System cartridges use a Runtime/Hub pipeline dedicated to system UI and app hosting. The system profile must not inherit the game stdlib or game ABI as its public authoring surface. In particular, System must not expose FrameComposer, Gfx, game Input, banks, sprites, or game memory cards as public profile APIs.

Future System APIs may be transported through syscalls, but syscall transport does not define the conceptual ABI boundary. The author-facing contract for system apps is a dedicated System profile ABI and stdlib/framework.

The following contracts are intentionally deferred from this cartridge chapter:

  • complete WindowManager design;
  • component tree and lifecycle semantics;
  • rich invalidation and transitions;
  • public PBS System ABI;
  • multitasking and scheduler semantics;
  • detailed System filesystem semantics.

The positive filesystem contract for System remains owned by the dedicated filesystem discussion/spec work. The only profile rule fixed here is negative: System does not use game memory cards as its public storage model.

6 Assets and Preload

assets.pa is the runtime-facing asset artifact consumed by the current runtime.

assets.pa v1 is an autocontained binary with:

  • fixed binary prelude;
  • JSON header;
  • binary payload region.

The fixed prelude includes, at minimum:

  • magic
  • schema_version
  • header_len
  • payload_offset

It may additionally include:

  • flags
  • reserved
  • header_checksum

The JSON header carries:

  • asset_table
  • preload

asset_table and preload are therefore no longer the primary runtime contract of manifest.json.

preload is structurally validated as part of assets.pa bootstrap:

  • each preload entry is { asset_id, slot };
  • asset_id uses 32-bit signed integer semantics;
  • each preload.asset_id must resolve to an entry in the same asset_table;
  • no two preload entries may claim the same (bank_type, slot) pair once bank_type is resolved from asset_table.

Runtime lifecycle:

  • asset_table is loaded from assets.pa and remains live while the cartridge is running;
  • preload is loaded from assets.pa, consumed during cartridge initialization, and may be discarded after boot;
  • payload bytes are resolved from the payload region using offsets relative to payload_offset.

Runtime loading policy:

  • cartridges without assets.pa remain valid when Asset capability is not declared;
  • cartridges that declare Asset capability must provide valid assets.pa;
  • assets.pa with invalid preload references or preload slot clashes is structurally invalid;
  • failure must occur as early as cartridge bootstrap, before preload execution.

7 Runtime Forms

Directory form

This is the working runtime/dev form used by the current loader.

Packaged .pmc form

This form is recognized conceptually by the loader boundary, but its actual load path is not implemented yet.

The cartridge spec therefore distinguishes:

  • supported current load form;
  • reserved future distribution form.

8 Relationship to Other Specs