139 lines
4.7 KiB
Markdown
139 lines
4.7 KiB
Markdown
# Historical Snapshot - Game Memcard Slots Surface and Semantics
|
|
|
|
Status: historical snapshot in `learn`, not normative.
|
|
Current normative anchors:
|
|
|
|
- [`../specs/08-save-memory-and-memcard.md`](../specs/08-save-memory-and-memcard.md)
|
|
- [`../specs/16-host-abi-and-syscalls.md`](../specs/16-host-abi-and-syscalls.md)
|
|
- [`../specs/16a-syscall-policies.md`](../specs/16a-syscall-policies.md)
|
|
- [`mental-model-save-memory-and-memcard.md`](mental-model-save-memory-and-memcard.md)
|
|
- [`mental-model-status-first-and-fault-thinking.md`](mental-model-status-first-and-fault-thinking.md)
|
|
|
|
## Status
|
|
|
|
Accepted
|
|
|
|
## Contexto
|
|
|
|
Jogos precisam de persistencia previsivel e portavel para save/config/blob, sem acesso amplo ao filesystem.
|
|
|
|
A agenda `013-game-memcard-slots-surface-and-semantics.md` consolidou os inputs de produto:
|
|
|
|
- `game` usa `32` slots por jogo;
|
|
- payload maximo por slot de `32KB`;
|
|
- jogo acessa somente slots do proprio `app_id`;
|
|
- persistencia explicita com `commit` atomico por slot;
|
|
- copia/export/import de saves ocorre fora do jogo (Hub/OS).
|
|
|
|
Esta decisao fecha o contrato v1 do perfil `game` usando a decisao `003` como data plane de bytes.
|
|
|
|
## Decisao
|
|
|
|
### 1. Contrato base de capacidade e ownership
|
|
|
|
- cada jogo possui exatamente `32` slots logicos (`0..31`);
|
|
- cada slot oferece payload util de ate `32 * 1024` bytes;
|
|
- acesso em userland e restrito ao `app_id` dono do cart carregado;
|
|
- nao existe acesso por path para jogos no v1.
|
|
|
|
### 2. Surface minima de memcard (status-first)
|
|
|
|
- `slot_count() -> (status:int, count:int)`
|
|
- `slot_stat(slot:int) -> (status:int, state:int, used_bytes:int, generation:int, checksum:int)`
|
|
- `slot_read(slot:int, buf:HeapRef<Bytes>, offset:int, max_bytes:int) -> (status:int, bytes_read:int)`
|
|
- `slot_write(slot:int, buf:HeapRef<Bytes>, offset:int, len:int) -> (status:int, bytes_written:int)`
|
|
- `slot_commit(slot:int) -> status:int`
|
|
- `slot_clear(slot:int) -> status:int`
|
|
|
|
Regras:
|
|
|
|
- `status` e sempre o primeiro retorno;
|
|
- operacoes de bytes usam `HeapRef<Bytes>` + janela explicita (`offset`, `max_bytes`/`len`);
|
|
- shape segue politica de `16a`.
|
|
|
|
### 3. Envelope digital runtime-owned por slot
|
|
|
|
Cada slot mantem metadados canonicos runtime-owned:
|
|
|
|
- `app_id` dono;
|
|
- `slot_index`;
|
|
- `save_uuid`;
|
|
- `generation`;
|
|
- `payload_size`;
|
|
- `checksum`;
|
|
- `state` (`EMPTY`, `STAGED`, `COMMITTED`, `CORRUPT`).
|
|
|
|
`generation` e `checksum` nao sao controlados manualmente pela userland:
|
|
|
|
- `generation` incrementa a cada `slot_commit` bem-sucedido;
|
|
- `checksum` e recalculado pelo runtime no payload persistido.
|
|
|
|
### 4. Envelope visual para Hub/OS
|
|
|
|
O slot expoe metadados visuais para UX fora do jogo:
|
|
|
|
- `label`;
|
|
- `subtitle`;
|
|
- `updated_at` (ou contador logico equivalente);
|
|
- `icon_ref` (v1 estatico, formato extensivel para animacao futura).
|
|
|
|
### 5. Politica de escrita e atomicidade
|
|
|
|
- `slot_write` altera staging (nao persiste no destino final);
|
|
- `slot_commit` aplica persistencia atomica por slot;
|
|
- sucesso parcial silencioso e proibido;
|
|
- em falha de commit, retorna `status` de erro e preserva invariante de atomicidade.
|
|
|
|
### 6. Fronteira de fault class
|
|
|
|
`memcard(game)` segue `16a`:
|
|
|
|
- `Trap`: erro estrutural (slot fora da faixa, `HeapRef` invalido/dead, janela invalida, shape ABI invalido);
|
|
- `status`: erro operacional de dominio;
|
|
- `Panic`: apenas quebra de invariante interna.
|
|
|
|
Catalogo minimo de status do dominio:
|
|
|
|
- `OK`;
|
|
- `EMPTY`;
|
|
- `NOT_FOUND`;
|
|
- `NO_SPACE`;
|
|
- `ACCESS_DENIED`;
|
|
- `CORRUPT`;
|
|
- `CONFLICT`;
|
|
- `UNAVAILABLE`;
|
|
- `INVALID_STATE`.
|
|
|
|
### 7. Politica de copia/export/import (fora do jogo)
|
|
|
|
- copia/export/import e responsabilidade do Hub/OS;
|
|
- jogo nao recebe API para copiar slots entre apps;
|
|
- v1 valida ownership por `app_id` no import;
|
|
- conflito e corrupcao devem ser refletidos por status do dominio e UX do Hub.
|
|
|
|
### 8. Integracao com storage host
|
|
|
|
- namespace fisico isolado por `app_id`;
|
|
- representacao fisica por slot e interna ao runtime/host;
|
|
- persistencia deve usar estrategia atomica (arquivo temporario + flush + rename equivalente da plataforma).
|
|
|
|
## Consequencias
|
|
|
|
### Positivas
|
|
|
|
- fecha o contrato de save de `game` sem abrir FS amplo;
|
|
- torna copy/export/import um fluxo de sistema (Hub/OS), nao de userland;
|
|
- padroniza integridade/versionamento de slot com `generation` + `checksum`.
|
|
|
|
### Custos
|
|
|
|
- exige implementacao de staging/commit atomico por slot;
|
|
- exige especificacao explicita do formato de export/import no Hub/OS;
|
|
- exige alinhamento com specs de memcard e ABI.
|
|
|
|
## Follow-up Obrigatorio
|
|
|
|
- a agenda `013-game-memcard-slots-surface-and-semantics.md` deve ser considerada fechada e removida;
|
|
- `specs/08-save-memory-and-memcard.md` deve absorver este contrato (`32 x 32KB`, slots por `app_id`, commit atomico);
|
|
- `specs/16-host-abi-and-syscalls.md` e `specs/16a-syscall-policies.md` devem absorver a surface e matriz de fault/status.
|