209 lines
7.1 KiB
Markdown
209 lines
7.1 KiB
Markdown
---
|
|
id: DEC-0038
|
|
ticket: variable-tile-bank-palette-serialization
|
|
title: Variable Glyph Bank Palette Serialization for Studio and Packer
|
|
status: accepted
|
|
created: 2026-07-14
|
|
accepted: 2026-07-14
|
|
ref_agenda: AGD-0005
|
|
plans:
|
|
- PLN-0087
|
|
- PLN-0088
|
|
- PLN-0089
|
|
- PLN-0090
|
|
- PLN-0091
|
|
tags:
|
|
- packer
|
|
- studio
|
|
- glyph-bank
|
|
- palette-serialization
|
|
- rgba8888
|
|
- runtime-alignment
|
|
---
|
|
|
|
## Status
|
|
|
|
Accepted. Drafted from accepted agenda `AGD-0005` and accepted on
|
|
2026-07-14.
|
|
|
|
## Context
|
|
|
|
This decision belongs to the `packer` domain, with Studio-facing projection and
|
|
fixture impact. Runtime protocol ownership remains in `../runtime`.
|
|
|
|
Studio/packer already aligned glyph-bank colors with RGBA8888 through
|
|
`DSC-0038`. That work kept the `GLYPH/indexed_v1` format name and changed the
|
|
palette color encoding from RGB565-era data to RGBA8888 in runtime channel
|
|
order. It deliberately preserved the fixed 64-palette payload model for that
|
|
wave.
|
|
|
|
Runtime `DEC-0041` now changes the authoritative `GLYPH/indexed_v1` contract:
|
|
|
|
- `palette_count` is the number of serialized and resident palettes;
|
|
- `palette_count` MUST be in `1..=64`;
|
|
- payloads contain exactly `palette_count * 16 * 4` RGBA8888 palette bytes;
|
|
- `size = ceil(width * height / 2) + palette_count * 16 * 4`;
|
|
- `decoded_size = width * height + palette_count * 16 * 4`;
|
|
- resident runtime memory materializes exactly `palette_count` palettes;
|
|
- `palette_id` is direct identity within the loaded glyph bank and is valid
|
|
only when `palette_id < palette_count`;
|
|
- v1 has no sparse-to-dense palette remapping metadata;
|
|
- this remains `GLYPH/indexed_v1`, not a new v2 payload.
|
|
|
|
Studio/packer must now follow that runtime-owned contract as downstream
|
|
producers of runtime-conforming `assets.pa` payloads.
|
|
|
|
## Decision
|
|
|
|
Studio and packer SHALL adopt variable glyph-bank palette serialization for
|
|
`GLYPH/indexed_v1`, following runtime `DEC-0041` as the protocol authority.
|
|
|
|
Packer MUST stop emitting a fixed 64-palette block for glyph banks unless the
|
|
effective `palette_count` is actually `64`.
|
|
|
|
Packer MUST emit exactly `palette_count * 16 * 4` palette bytes for each
|
|
`GLYPH/indexed_v1` glyph-bank payload.
|
|
|
|
Packer MUST compute glyph-bank `size` as:
|
|
|
|
```text
|
|
size = ceil(width * height / 2) + palette_count * 16 * 4
|
|
```
|
|
|
|
Packer MUST compute glyph-bank `decoded_size` as:
|
|
|
|
```text
|
|
decoded_size = width * height + palette_count * 16 * 4
|
|
```
|
|
|
|
Packer MUST publish root effective metadata fields required by runtime:
|
|
|
|
- `tile_size`
|
|
- `width`
|
|
- `height`
|
|
- `palette_count`
|
|
|
|
For `GLYPH/indexed_v1`, `palette_count` MUST describe the number of serialized
|
|
RGBA8888 palettes and the number of resident palettes expected by runtime.
|
|
`palette_count` MUST be in the inclusive range `1..=64`.
|
|
|
|
Packer and Studio MUST NOT introduce `GLYPH/indexed_v2` for this change.
|
|
|
|
Packer and Studio MUST NOT preserve compatibility with the old fixed-padding
|
|
payload shape as a special mode.
|
|
|
|
Packer and Studio MUST NOT introduce sparse-to-dense palette remapping metadata
|
|
for v1.
|
|
|
|
`palette_authored`, when present in tooling or pipeline metadata, is
|
|
informative only. It MUST NOT be treated as effective runtime metadata unless a
|
|
later runtime decision promotes it.
|
|
|
|
Palette bytes SHALL remain RGBA8888 in runtime `R`, `G`, `B`, `A` byte order.
|
|
Palette index `0` and color index `0` remain ordinary indices. Transparency
|
|
remains represented by the alpha channel of the resolved RGBA8888 color.
|
|
|
|
## Rationale
|
|
|
|
Runtime owns the `GLYPH/indexed_v1` wire contract. Once runtime `DEC-0041`
|
|
accepted variable palette serialization, keeping packer output fixed at 64
|
|
palettes would make Studio/packer produce stale runtime payloads.
|
|
|
|
Making `palette_count` the effective serialized and resident count removes the
|
|
old mismatch between authored palette count and payload shape. The packer no
|
|
longer needs to pad every glyph bank to 4096 palette bytes unless the bank
|
|
really uses all 64 palettes.
|
|
|
|
Keeping the existing format name is correct because the project is still in v1
|
|
and runtime explicitly accepted this as an incompatible v1 correction. A v2
|
|
name would add migration surface without protecting any required compatibility
|
|
contract.
|
|
|
|
Rejecting sparse-to-dense remapping keeps `palette_id` direct. Scene, sprite,
|
|
packer output, and runtime lookup all refer to the same palette identity inside
|
|
the loaded glyph bank.
|
|
|
|
## Implications
|
|
|
|
### Specs
|
|
|
|
Packer specs MUST be updated so `GLYPH/indexed_v1` no longer describes a fixed
|
|
`64 * 16 * 4 = 4096` palette block as the normal payload shape.
|
|
|
|
Packer specs MUST define `palette_count` as the effective serialized palette
|
|
count for glyph banks, constrained to `1..=64`.
|
|
|
|
Studio specs MUST be updated only where Studio-facing projections, asset
|
|
details, pack wizard behavior, or fixtures expose the old fixed-padding model.
|
|
|
|
### Code
|
|
|
|
Packer payload emission MUST write only `palette_count` palettes.
|
|
|
|
Packer payload validation/materialization helpers MUST compute size and decoded
|
|
size from variable `palette_count`.
|
|
|
|
Packer metadata projection and Studio-facing read/detail APIs MUST expose the
|
|
runtime-effective `palette_count` correctly.
|
|
|
|
Studio code MUST NOT treat `palette_authored` as the runtime-effective count.
|
|
|
|
### Tests and Fixtures
|
|
|
|
Tests MUST cover:
|
|
|
|
- `palette_count = 1`;
|
|
- an intermediate `palette_count`;
|
|
- `palette_count = 64`;
|
|
- size and decoded-size formulas for variable counts;
|
|
- emitted RGBA8888 palette byte count;
|
|
- metadata/payload mismatch rejection or producer validation.
|
|
|
|
Fixtures that encode the old fixed-padding assumption MUST be regenerated or
|
|
updated unless they intentionally use `palette_count = 64` and satisfy the new
|
|
runtime contract directly.
|
|
|
|
### Non-goals
|
|
|
|
This decision does not change RGBA8888 channel order.
|
|
|
|
This decision does not change the packed `u4` indexed pixel plane.
|
|
|
|
This decision does not change scene `palette_id` payload shape.
|
|
|
|
This decision does not introduce v2, compatibility branches, or palette
|
|
identity remapping.
|
|
|
|
## Propagation Targets
|
|
|
|
- Specs:
|
|
- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md`
|
|
- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md`
|
|
- `docs/specs/studio/4. Assets Workspace Specification.md`, if Studio-facing
|
|
palette count projection is documented there.
|
|
- Code:
|
|
- packer glyph-bank payload emission;
|
|
- packer asset walking/materialization;
|
|
- packer read/detail projections;
|
|
- Studio asset details or pack wizard surfaces if they expose palette counts.
|
|
- Tests:
|
|
- packer parser, walker, materializer, workspace service, and fixture tests;
|
|
- Studio tests if Studio projections or UI logic expose palette counts.
|
|
- Docs:
|
|
- downstream implementation plans derived from this decision.
|
|
|
|
## References
|
|
|
|
- Agenda: `AGD-0005`
|
|
- Runtime decision:
|
|
`../runtime/discussion/workflow/decisions/DEC-0041-variable-glyph-bank-palette-protocol.md`
|
|
- Runtime handoff:
|
|
`../runtime/discussion/workflow/plans/PLN-0172-runtime-spec-handoff-to-packer-and-studio.md`
|
|
- Prior Studio/packer RGBA8888 lesson:
|
|
`discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md`
|
|
|
|
## Revision Log
|
|
|
|
- 2026-07-14: Initial accepted decision from `AGD-0005`, aligned with runtime
|
|
`DEC-0041`.
|