2026-07-03 17:23:49 +01:00

212 lines
6.4 KiB
Markdown

# 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:
```json
{
"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.
Directory cartridges are also the only form discovered by the v1 local Home
games library. When a host provides `--games-root <dir>`, discovery scans only
immediate child directories under that root. Each child directory is a candidate
cartridge.
For the v1 Home games library:
- a candidate must have a valid `manifest.json`;
- the manifest must declare `app_mode: "Game"`;
- the library retains the loaded manifest data, `title`, `app_id`,
`app_version`, the internal cartridge path, and discovery metadata;
- invalid candidates are logged or reported as diagnostics and omitted from the
Home list;
- valid non-Game cartridges are omitted from the Game library.
Discovery reads metadata for cataloging. It does not replace the normal
cartridge loader used when firmware starts the selected cartridge.
### Packaged `.pmc` form
This form is recognized conceptually by the loader boundary, but its actual load path is not implemented yet.
Packaged `.pmc` cartridges are not discovered by the v1 Home games library.
The cartridge spec therefore distinguishes:
- supported current load form;
- reserved future distribution form.
## 8 Relationship to Other Specs
- [`12-firmware-pos-and-prometeuhub.md`](12-firmware-pos-and-prometeuhub.md) defines how firmware consumes cartridge metadata.
- [`14-boot-profiles.md`](14-boot-profiles.md) defines cartridge selection at boot.
- [`15-asset-management.md`](15-asset-management.md) defines the `assets.pa` envelope, asset table semantics, preload lifecycle, and residency semantics.