plan adjustments
This commit is contained in:
parent
5c1e6dac83
commit
0723057038
@ -1,4 +1,4 @@
|
|||||||
{"type":"meta","next_id":{"DSC":26,"AGD":26,"DEC":14,"PLN":16,"LSN":30,"CLSN":1}}
|
{"type":"meta","next_id":{"DSC":26,"AGD":26,"DEC":14,"PLN":17,"LSN":30,"CLSN":1}}
|
||||||
{"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
{"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||||
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||||
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||||
@ -17,7 +17,7 @@
|
|||||||
{"type":"discussion","id":"DSC-0012","status":"open","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0012","status":"open","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||||
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||||
{"type":"discussion","id":"DSC-0025","status":"open","ticket":"scene-bank-and-viewport-cache-refactor","title":"Agenda - Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-13","tags":["gfx","tilemap","runtime","render"],"agendas":[{"id":"AGD-0025","file":"AGD-0025-scene-bank-and-viewport-cache-refactor.md","status":"accepted","created_at":"2026-04-11","updated_at":"2026-04-13"}],"decisions":[{"id":"DEC-0013","file":"DEC-0013-scene-bank-and-viewport-cache-model.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_agenda":"AGD-0025"}],"plans":[{"id":"PLN-0011","file":"PLN-0011-scene-core-types-and-bank-contract.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0012","file":"PLN-0012-scene-viewport-cache-structure.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0013","file":"PLN-0013-scene-viewport-resolver-and-rematerialization.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0014","file":"PLN-0014-renderer-migration-to-scene-viewport-cache.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0015","file":"PLN-0015-api-bank-integration-and-tests.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0025","status":"open","ticket":"scene-bank-and-viewport-cache-refactor","title":"Agenda - Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-13","tags":["gfx","tilemap","runtime","render"],"agendas":[{"id":"AGD-0025","file":"AGD-0025-scene-bank-and-viewport-cache-refactor.md","status":"accepted","created_at":"2026-04-11","updated_at":"2026-04-13"}],"decisions":[{"id":"DEC-0013","file":"DEC-0013-scene-bank-and-viewport-cache-model.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_agenda":"AGD-0025"}],"plans":[{"id":"PLN-0011","file":"PLN-0011-scene-core-types-and-bank-contract.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0012","file":"PLN-0012-scene-viewport-cache-structure.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0013","file":"PLN-0013-scene-viewport-resolver-and-rematerialization.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0014","file":"PLN-0014-renderer-migration-to-scene-viewport-cache.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0015","file":"PLN-0015-api-bank-integration-and-tests.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]},{"id":"PLN-0016","file":"PLN-0016-scene-binary-payload-format-and-decoder.md","status":"accepted","created_at":"2026-04-13","updated_at":"2026-04-13","ref_decisions":["DEC-0013"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0014","status":"open","ticket":"perf-vm-allocation-and-copy-pressure","title":"Agenda - [PERF] VM Allocation and Copy Pressure","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0013","file":"workflow/agendas/AGD-0013-perf-vm-allocation-and-copy-pressure.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0014","status":"open","ticket":"perf-vm-allocation-and-copy-pressure","title":"Agenda - [PERF] VM Allocation and Copy Pressure","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0013","file":"workflow/agendas/AGD-0013-perf-vm-allocation-and-copy-pressure.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0015","status":"open","ticket":"perf-cartridge-boot-and-program-ownership","title":"Agenda - [PERF] Cartridge Boot and Program Ownership","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0014","file":"workflow/agendas/AGD-0014-perf-cartridge-boot-and-program-ownership.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0015","status":"open","ticket":"perf-cartridge-boot-and-program-ownership","title":"Agenda - [PERF] Cartridge Boot and Program Ownership","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0014","file":"workflow/agendas/AGD-0014-perf-cartridge-boot-and-program-ownership.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0016","status":"done","ticket":"tilemap-empty-cell-vs-tile-id-zero","title":"Tilemap Empty Cell vs Tile ID Zero","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0015","file":"workflow/agendas/AGD-0015-tilemap-empty-cell-vs-tile-id-zero.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0022","file":"lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
{"type":"discussion","id":"DSC-0016","status":"done","ticket":"tilemap-empty-cell-vs-tile-id-zero","title":"Tilemap Empty Cell vs Tile ID Zero","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0015","file":"workflow/agendas/AGD-0015-tilemap-empty-cell-vs-tile-id-zero.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0022","file":"lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||||
|
|||||||
@ -10,11 +10,11 @@ tags: [gfx, tilemap, runtime, render]
|
|||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
Implement the `SceneViewportCache` as the operational render cache for one `Scene`, including one internal ringbuffer per layer and lightweight derived cache entries for raster acceleration.
|
Implement the `SceneViewportCache` as the operational render cache for one `SceneBank`, including one internal ringbuffer per layer and lightweight derived cache entries for raster acceleration.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
`DEC-0013` locks `SceneViewportCache` as the renderer-facing view of scene data and prefers internal ringbuffer storage per layer. This plan isolates the cache data structure and update API before resolver and renderer integration.
|
`DEC-0013` locks `SceneViewportCache` as the renderer-facing view of scene data and prefers internal ringbuffer storage per layer. `PLN-0011` already established the canonical source as `SceneBank` with exactly four `SceneLayer`s in a fixed array and moved per-layer movement metadata to `motion_factor`. This plan isolates the cache data structure and update API before resolver and renderer integration.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
@ -56,10 +56,10 @@ Create the internal data model for one viewport cache layer and for cached tile
|
|||||||
### Step 2 - Define `SceneViewportCache` as a four-layer aggregate
|
### Step 2 - Define `SceneViewportCache` as a four-layer aggregate
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Create the top-level cache aggregate for one `Scene`.
|
Create the top-level cache aggregate for one `SceneBank`.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Represent one cache aggregate containing four internal layer caches.
|
- Represent one cache aggregate containing four internal layer caches aligned to `SceneBank.layers`.
|
||||||
- Thread through cache dimensions and tile-size assumptions for V1.
|
- Thread through cache dimensions and tile-size assumptions for V1.
|
||||||
- Make the cache explicitly scene-derived and non-canonical.
|
- Make the cache explicitly scene-derived and non-canonical.
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ Define the update surface that later plans will use for rematerialization.
|
|||||||
Add helpers that copy canonical scene data into cache entries.
|
Add helpers that copy canonical scene data into cache entries.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Build helpers that read canonical `SceneLayer`/`TileMap` data and populate cache entries.
|
- Build helpers that read canonical `SceneBank` / `SceneLayer` / `TileMap` data and populate cache entries.
|
||||||
- Keep the helpers unaware of camera policy; they should only perform requested materialization work.
|
- Keep the helpers unaware of camera policy; they should only perform requested materialization work.
|
||||||
- Ensure per-layer movement factors remain metadata of the scene layer, not cache-only state.
|
- Ensure per-layer movement factors remain metadata of the scene layer, not cache-only state.
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ Protect the cache shape and update operations before wiring the resolver.
|
|||||||
- Line/column/region refresh APIs only rewrite the requested area.
|
- Line/column/region refresh APIs only rewrite the requested area.
|
||||||
|
|
||||||
### Integration Tests
|
### Integration Tests
|
||||||
- Materialization from `Scene` into `SceneViewportCache` succeeds across all four layers.
|
- Materialization from `SceneBank` into `SceneViewportCache` succeeds across all four layers.
|
||||||
|
|
||||||
### Manual Verification
|
### Manual Verification
|
||||||
- Inspect debug output or temporary probes to confirm cache updates do not expose ringbuffer details outside the cache boundary.
|
- Inspect debug output or temporary probes to confirm cache updates do not expose ringbuffer details outside the cache boundary.
|
||||||
@ -137,7 +137,7 @@ Protect the cache shape and update operations before wiring the resolver.
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- Depends on `PLN-0011` for canonical `Scene` / `SceneLayer` / `TileMap` types.
|
- Depends on `PLN-0011` for canonical `SceneBank` / `SceneLayer` / `TileMap` types and the fixed four-layer shape.
|
||||||
- Source decision: `DEC-0013`
|
- Source decision: `DEC-0013`
|
||||||
|
|
||||||
## Risks
|
## Risks
|
||||||
|
|||||||
@ -10,17 +10,17 @@ tags: [gfx, tilemap, runtime, render]
|
|||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
Implement `SceneViewportResolver` as the owner of master totem, per-layer totems, drift, hysteresis, clamp, cache update decisions, and per-layer copy instrumentation metadata.
|
Implement `SceneViewportResolver` as the owner of master anchor, per-layer anchors, drift, hysteresis, clamp, cache update decisions, and per-layer copy instrumentation metadata.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
`DEC-0013` makes the resolver the owner of movement policy between camera input and viewport cache updates. This plan isolates the decision logic before final renderer migration.
|
`DEC-0013` makes the resolver the owner of movement policy between camera input and viewport cache updates. `PLN-0011` already fixed the canonical source as `SceneBank` and renamed per-layer movement metadata to `motion_factor`. This plan isolates the decision logic before final renderer migration.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
### Included
|
### Included
|
||||||
- Define `SceneViewportResolver`.
|
- Define `SceneViewportResolver`.
|
||||||
- Implement master totem and per-layer derived totems.
|
- Implement master anchor and per-layer derived anchors.
|
||||||
- Implement drift and hysteresis.
|
- Implement drift and hysteresis.
|
||||||
- Implement clamp behavior.
|
- Implement clamp behavior.
|
||||||
- Implement cache-update triggering and copy instrumentation metadata.
|
- Implement cache-update triggering and copy instrumentation metadata.
|
||||||
@ -39,8 +39,8 @@ Create the resolver state model and its public input surface.
|
|||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Define resolver state to own:
|
- Define resolver state to own:
|
||||||
- master totem
|
- master anchor
|
||||||
- per-layer derived totems
|
- per-layer derived anchors
|
||||||
- viewport dimensions
|
- viewport dimensions
|
||||||
- hysteresis thresholds
|
- hysteresis thresholds
|
||||||
- clamp-relevant scene bounds
|
- clamp-relevant scene bounds
|
||||||
@ -52,10 +52,10 @@ Create the resolver state model and its public input surface.
|
|||||||
### Step 2 - Implement master-to-layer totem derivation
|
### Step 2 - Implement master-to-layer totem derivation
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Make layer motion derive from the master totem using each layer’s `totem_factor`.
|
Make layer motion derive from the master anchor using each layer’s `motion_factor`.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Compute per-layer effective motion from the master totem.
|
- Compute per-layer effective motion from the master anchor.
|
||||||
- Preserve support for normal layers (`1.0`) and parallax/background-like layers (`!= 1.0`).
|
- Preserve support for normal layers (`1.0`) and parallax/background-like layers (`!= 1.0`).
|
||||||
- Keep the derivation explicit and testable per axis.
|
- Keep the derivation explicit and testable per axis.
|
||||||
|
|
||||||
@ -66,10 +66,10 @@ Make layer motion derive from the master totem using each layer’s `totem_facto
|
|||||||
### Step 3 - Implement drift, hysteresis, and clamp
|
### Step 3 - Implement drift, hysteresis, and clamp
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Translate camera motion into discrete totem advancement safely.
|
Translate camera motion into discrete anchor advancement safely.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Implement drift calculation in pixel space against totem centers in tile space.
|
- Implement drift calculation in pixel space against anchor centers in tile space.
|
||||||
- Implement hysteresis with:
|
- Implement hysteresis with:
|
||||||
- internal safe band
|
- internal safe band
|
||||||
- external trigger band
|
- external trigger band
|
||||||
@ -117,8 +117,8 @@ Protect resolver correctness before renderer integration.
|
|||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Add tests for:
|
- Add tests for:
|
||||||
- master totem updates
|
- master anchor updates
|
||||||
- per-layer totem factor derivation
|
- per-layer motion-factor derivation
|
||||||
- hysteresis stability
|
- hysteresis stability
|
||||||
- repeated high-speed movement
|
- repeated high-speed movement
|
||||||
- clamp at scene edges
|
- clamp at scene edges
|
||||||
@ -131,8 +131,8 @@ Protect resolver correctness before renderer integration.
|
|||||||
|
|
||||||
### Unit Tests
|
### Unit Tests
|
||||||
- Hysteresis prevents edge flick/thrash.
|
- Hysteresis prevents edge flick/thrash.
|
||||||
- Totem movement occurs discretely in tile steps.
|
- Anchor movement occurs discretely in tile steps.
|
||||||
- Per-layer totems follow the master according to `totem_factor`.
|
- Per-layer anchors follow the master according to `motion_factor`.
|
||||||
- Clamp behavior is correct near scene edges.
|
- Clamp behavior is correct near scene edges.
|
||||||
|
|
||||||
### Integration Tests
|
### Integration Tests
|
||||||
@ -144,7 +144,7 @@ Protect resolver correctness before renderer integration.
|
|||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] `SceneViewportResolver` exists with the full state required by `DEC-0013`.
|
- [ ] `SceneViewportResolver` exists with the full state required by `DEC-0013`.
|
||||||
- [ ] Master and per-layer totems are derived correctly.
|
- [ ] Master and per-layer anchors are derived correctly.
|
||||||
- [ ] Hysteresis and clamp are implemented and tested.
|
- [ ] Hysteresis and clamp are implemented and tested.
|
||||||
- [ ] Cache refresh requests are emitted by line, column, and region as required.
|
- [ ] Cache refresh requests are emitted by line, column, and region as required.
|
||||||
- [ ] Copy instrumentation metadata is available for later renderer use.
|
- [ ] Copy instrumentation metadata is available for later renderer use.
|
||||||
|
|||||||
@ -10,11 +10,11 @@ tags: [gfx, tilemap, runtime, render]
|
|||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
Migrate world rendering from direct canonical map consumption to `SceneViewportCache` consumption while preserving the accepted observable composition order.
|
Migrate world rendering from direct canonical `SceneBank` consumption to `SceneViewportCache` consumption while preserving the accepted observable composition order.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
`DEC-0013` makes `SceneViewportCache` the immediate source of copy data for world blits and preserves the visible order of world layers, interleaved sprites, and HUD. This plan focuses on the renderer migration itself.
|
`DEC-0013` makes `SceneViewportCache` the immediate source of copy data for world blits and preserves the visible order of world layers, interleaved sprites, and HUD. `PLN-0011` already removed the old canonical `TileLayer` / `ScrollableTileLayer` model and cleaned the bridge surface accordingly. This plan focuses on the renderer migration itself.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
@ -35,10 +35,10 @@ Migrate world rendering from direct canonical map consumption to `SceneViewportC
|
|||||||
### Step 1 - Identify and isolate direct canonical map consumption in the renderer
|
### Step 1 - Identify and isolate direct canonical map consumption in the renderer
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Locate current renderer paths that read canonical layer maps directly.
|
Locate current renderer paths that read canonical scene/layer maps directly.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Replace direct `TileMap` reads in [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) with abstraction points prepared to accept cache-sourced copy requests.
|
- Replace any remaining direct `SceneBank` / `SceneLayer` / `TileMap` reads in [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs) with abstraction points prepared to accept cache-sourced copy requests.
|
||||||
- Keep the migration incremental enough to preserve buildability.
|
- Keep the migration incremental enough to preserve buildability.
|
||||||
|
|
||||||
**File(s):**
|
**File(s):**
|
||||||
@ -124,7 +124,7 @@ Protect the migrated composition order and world rendering behavior.
|
|||||||
|
|
||||||
## Acceptance Criteria
|
## Acceptance Criteria
|
||||||
|
|
||||||
- [ ] Renderer world composition no longer reads canonical scene maps directly in the hot path.
|
- [ ] Renderer world composition no longer reads canonical `SceneBank` data directly in the hot path.
|
||||||
- [ ] World layers are copied from `SceneViewportCache`.
|
- [ ] World layers are copied from `SceneViewportCache`.
|
||||||
- [ ] Sprite interleaving and HUD ordering remain correct.
|
- [ ] Sprite interleaving and HUD ordering remain correct.
|
||||||
- [ ] V1 destructive composition still works end-to-end.
|
- [ ] V1 destructive composition still works end-to-end.
|
||||||
|
|||||||
@ -10,17 +10,16 @@ tags: [gfx, tilemap, runtime, render]
|
|||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
Finish the scene/viewport-cache migration by aligning exposed APIs, bank-loading integration, and test coverage across HAL, drivers, and system entry points.
|
Finish the scene/viewport-cache migration by aligning exposed APIs, final integration surfaces, and test coverage across HAL, drivers, and system entry points.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
After core types, cache, resolver, and renderer migration exist, the remaining work is to align the surrounding surfaces so the new architecture is usable as the runtime’s operational model.
|
After core types, cache, resolver, and renderer migration exist, the remaining work is to align the surrounding surfaces so the new architecture is usable as the runtime’s operational model. `PLN-0011` already removed the old canonical tile-layer APIs and introduced `BankType::SCENE` plus scene-aware bank slots. The binary `SCENE` payload contract and decoder are now isolated in `PLN-0016`.
|
||||||
|
|
||||||
## Scope
|
## Scope
|
||||||
|
|
||||||
### Included
|
### Included
|
||||||
- Update bridge APIs and exposed runtime surfaces.
|
- Update bridge APIs and exposed runtime surfaces.
|
||||||
- Align bank-loading/integration paths with scene-backed content.
|
|
||||||
- Remove stale tile-layer-era interfaces.
|
- Remove stale tile-layer-era interfaces.
|
||||||
- Add cross-layer regression coverage.
|
- Add cross-layer regression coverage.
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ After core types, cache, resolver, and renderer migration exist, the remaining w
|
|||||||
Remove or replace public APIs still shaped around the old scrollable tile-layer model.
|
Remove or replace public APIs still shaped around the old scrollable tile-layer model.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Update `GfxBridge` and adjacent bridge traits so they no longer expose obsolete canonical layer ownership assumptions.
|
- Verify `GfxBridge` and adjacent bridge traits stay free of obsolete canonical layer ownership assumptions after cache/resolver integration.
|
||||||
- Introduce scene/cache/resolver-oriented access only where required by runtime consumers.
|
- Introduce scene/cache/resolver-oriented access only where required by runtime consumers.
|
||||||
|
|
||||||
**File(s):**
|
**File(s):**
|
||||||
@ -50,43 +49,29 @@ Ensure hardware and driver initialization paths can construct and own the new sc
|
|||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Update hardware bootstrap and driver ownership paths to instantiate the canonical scene and viewport-cache stack.
|
- Update hardware bootstrap and driver ownership paths to instantiate the canonical scene and viewport-cache stack.
|
||||||
- Remove any remaining ownership assumptions tied to `ScrollableTileLayer`.
|
- Remove any remaining ownership assumptions tied to the pre-`SceneBank` model.
|
||||||
|
|
||||||
**File(s):**
|
**File(s):**
|
||||||
- [crates/console/prometeu-drivers/src/hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs)
|
- [crates/console/prometeu-drivers/src/hardware.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/hardware.rs)
|
||||||
- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs)
|
- [crates/console/prometeu-drivers/src/gfx.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/gfx.rs)
|
||||||
|
|
||||||
### Step 3 - Align asset/bank integration paths
|
### Step 3 - Remove stale type and API remnants
|
||||||
|
|
||||||
**What:**
|
|
||||||
Make sure bank-loading and asset integration paths understand the scene-backed model at the operational layer.
|
|
||||||
|
|
||||||
**How:**
|
|
||||||
- Update asset-side or loader-side integration points so scene-backed content can be staged, installed, and referenced coherently.
|
|
||||||
- Keep the work scoped to the bank-loading path; do not reopen the canonical model here.
|
|
||||||
|
|
||||||
**File(s):**
|
|
||||||
- [crates/console/prometeu-drivers/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs)
|
|
||||||
- [crates/console/prometeu-drivers/src/memory_banks.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/memory_banks.rs)
|
|
||||||
- [crates/console/prometeu-hal/src/cartridge_loader.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/cartridge_loader.rs)
|
|
||||||
- Related asset/bank shared types
|
|
||||||
|
|
||||||
### Step 4 - Remove stale type and API remnants
|
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Clean out old interfaces that would leave the codebase in a dual-model state.
|
Clean out old interfaces that would leave the codebase in a dual-model state.
|
||||||
|
|
||||||
**How:**
|
**How:**
|
||||||
- Remove obsolete references to:
|
- Remove any remaining obsolete references to:
|
||||||
- `TileLayer`
|
- `TileLayer`
|
||||||
- `ScrollableTileLayer`
|
- `ScrollableTileLayer`
|
||||||
- direct old-layer scroll ownership APIs
|
- direct old-layer scroll ownership APIs
|
||||||
|
- transitional commented fallback paths left during migration
|
||||||
- Keep only the canonical scene model and the viewport-cache/render pipeline required by the decision.
|
- Keep only the canonical scene model and the viewport-cache/render pipeline required by the decision.
|
||||||
|
|
||||||
**File(s):**
|
**File(s):**
|
||||||
- HAL and driver modules touched by earlier plans
|
- HAL and driver modules touched by earlier plans
|
||||||
|
|
||||||
### Step 5 - Add full-stack regression coverage
|
### Step 4 - Add full-stack regression coverage
|
||||||
|
|
||||||
**What:**
|
**What:**
|
||||||
Add the minimum test family needed to execute the migration safely one plan at a time.
|
Add the minimum test family needed to execute the migration safely one plan at a time.
|
||||||
@ -125,17 +110,15 @@ Add the minimum test family needed to execute the migration safely one plan at a
|
|||||||
|
|
||||||
- [ ] Bridge and runtime-facing APIs align with the new scene/cache model.
|
- [ ] Bridge and runtime-facing APIs align with the new scene/cache model.
|
||||||
- [ ] Hardware/driver construction paths instantiate the new architecture correctly.
|
- [ ] Hardware/driver construction paths instantiate the new architecture correctly.
|
||||||
- [ ] Asset/bank integration paths accept the scene-backed model.
|
|
||||||
- [ ] Stale old-layer APIs are removed.
|
- [ ] Stale old-layer APIs are removed.
|
||||||
- [ ] Full-stack regression coverage exists for the migration.
|
- [ ] Full-stack regression coverage exists for the migration.
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
- Depends on `PLN-0011`, `PLN-0012`, `PLN-0013`, and `PLN-0014`.
|
- Depends on `PLN-0011`, `PLN-0012`, `PLN-0013`, `PLN-0014`, and `PLN-0016`.
|
||||||
- Source decision: `DEC-0013`
|
- Source decision: `DEC-0013`
|
||||||
|
|
||||||
## Risks
|
## Risks
|
||||||
|
|
||||||
- API cleanup is where hidden dependencies on the old model are most likely to surface.
|
- API cleanup is where hidden dependencies on the old model are most likely to surface.
|
||||||
- Asset/bank integration can expand in scope if loader assumptions are too tightly coupled to current bank enums.
|
|
||||||
- If stale APIs are not removed aggressively, the codebase can get stuck in a fragile dual-model transition.
|
- If stale APIs are not removed aggressively, the codebase can get stuck in a fragile dual-model transition.
|
||||||
|
|||||||
@ -0,0 +1,164 @@
|
|||||||
|
---
|
||||||
|
id: PLN-0016
|
||||||
|
ticket: scene-bank-and-viewport-cache-refactor
|
||||||
|
title: Plan - Scene Binary Payload Format and Decoder
|
||||||
|
status: accepted
|
||||||
|
created: 2026-04-13
|
||||||
|
completed:
|
||||||
|
tags: [asset, runtime, scene, codec, binary-format]
|
||||||
|
---
|
||||||
|
|
||||||
|
## Objective
|
||||||
|
|
||||||
|
Define the canonical binary payload contract for `SCENE` assets and implement the runtime decoder needed to load `SceneBank` content without JSON-based scene payloads.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
`DEC-0013` established `SceneBank` as the canonical loaded scene aggregate. `PLN-0011` introduced `BankType::SCENE` and the scene-aware bank slot model, but intentionally left `SCENE` payload decoding open. A temporary `todo!()` now blocks scene payload materialization in the asset manager until the binary contract is closed. This plan isolates that format and decoder work before the final integration pass.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
### Included
|
||||||
|
- Define the binary on-disk/on-wire payload format for `SCENE`.
|
||||||
|
- Define the minimum metadata contract needed in `AssetEntry` for `SCENE`.
|
||||||
|
- Implement the runtime decoder from payload bytes into `SceneBank`.
|
||||||
|
- Add format and decode tests for valid and invalid scene payloads.
|
||||||
|
- Re-enable scene asset load/preload coverage once the decoder exists.
|
||||||
|
|
||||||
|
### Excluded
|
||||||
|
- `SceneViewportCache`
|
||||||
|
- `SceneViewportResolver`
|
||||||
|
- renderer migration
|
||||||
|
- cartridge authoring tooling beyond what is strictly needed to encode test fixtures
|
||||||
|
- reopening canonical scene/runtime type design
|
||||||
|
|
||||||
|
## Execution Steps
|
||||||
|
|
||||||
|
### Step 1 - Define the binary `SCENE` payload contract
|
||||||
|
|
||||||
|
**What:**
|
||||||
|
Close the binary layout for serialized `SceneBank` assets.
|
||||||
|
|
||||||
|
**How:**
|
||||||
|
- Define a versioned binary format with:
|
||||||
|
- file/payload prelude or version marker
|
||||||
|
- fixed four-layer scene layout
|
||||||
|
- per-layer metadata block
|
||||||
|
- per-layer tilemap dimensions
|
||||||
|
- serialized tile records
|
||||||
|
- Keep the format aligned with the canonical runtime shape from `PLN-0011`:
|
||||||
|
- `SceneBank`
|
||||||
|
- `[SceneLayer; 4]`
|
||||||
|
- `motion_factor`
|
||||||
|
- `TileMap`
|
||||||
|
- `Tile`
|
||||||
|
- Document field sizes, endianness, ordering, and validation rules.
|
||||||
|
|
||||||
|
**File(s):**
|
||||||
|
- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs)
|
||||||
|
- [crates/console/prometeu-hal/src/cartridge_loader.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/cartridge_loader.rs)
|
||||||
|
- Additional shared asset-format module(s) if needed
|
||||||
|
|
||||||
|
### Step 2 - Define `SCENE` metadata requirements in `AssetEntry`
|
||||||
|
|
||||||
|
**What:**
|
||||||
|
Decide what belongs in `AssetEntry.metadata` versus the binary payload itself.
|
||||||
|
|
||||||
|
**How:**
|
||||||
|
- Keep metadata minimal and stable.
|
||||||
|
- Add only fields that materially help validation or loader routing.
|
||||||
|
- Avoid duplicating large structural scene information in both metadata and payload.
|
||||||
|
- Add typed metadata helpers in HAL if required for scene assets.
|
||||||
|
|
||||||
|
**File(s):**
|
||||||
|
- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs)
|
||||||
|
|
||||||
|
### Step 3 - Implement the runtime `SCENE` decoder
|
||||||
|
|
||||||
|
**What:**
|
||||||
|
Replace the current `todo!()` loader path with a real binary decoder.
|
||||||
|
|
||||||
|
**How:**
|
||||||
|
- Implement `perform_load_scene_bank(...)` using the accepted binary contract.
|
||||||
|
- Decode from slice/reader into canonical runtime objects:
|
||||||
|
- `SceneBank`
|
||||||
|
- `SceneLayer`
|
||||||
|
- `TileMap`
|
||||||
|
- `Tile`
|
||||||
|
- Add explicit validation for:
|
||||||
|
- invalid version
|
||||||
|
- short payload
|
||||||
|
- invalid tile-size values
|
||||||
|
- layer count mismatch
|
||||||
|
- tile count mismatch
|
||||||
|
- numeric overflow / malformed dimensions
|
||||||
|
- Keep decode logic self-contained and free of viewport/cache behavior.
|
||||||
|
|
||||||
|
**File(s):**
|
||||||
|
- [crates/console/prometeu-drivers/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs)
|
||||||
|
- Supporting HAL/shared modules if decoder helpers are factored out
|
||||||
|
|
||||||
|
### Step 4 - Re-enable scene asset loading paths and tests
|
||||||
|
|
||||||
|
**What:**
|
||||||
|
Turn scene asset loading back on in the asset manager and restore coverage.
|
||||||
|
|
||||||
|
**How:**
|
||||||
|
- Re-enable the `SCENE` load/preload path currently blocked by the `todo!()`.
|
||||||
|
- Add tests for:
|
||||||
|
- scene payload decode success
|
||||||
|
- scene asset load
|
||||||
|
- scene preload on initialization
|
||||||
|
- malformed scene payload rejection
|
||||||
|
- Ensure glyph/sound behavior remains unchanged.
|
||||||
|
|
||||||
|
**File(s):**
|
||||||
|
- [crates/console/prometeu-drivers/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs)
|
||||||
|
|
||||||
|
### Step 5 - Confirm cartridge-loader and asset-table compatibility
|
||||||
|
|
||||||
|
**What:**
|
||||||
|
Ensure the broader cartridge/asset pipeline accepts the finalized `SCENE` contract cleanly.
|
||||||
|
|
||||||
|
**How:**
|
||||||
|
- Verify `AssetEntry` and cartridge-loading paths accept the new scene metadata contract.
|
||||||
|
- Add targeted tests for asset-table parsing or preload validation if needed.
|
||||||
|
- Keep this step scoped to compatibility with the finalized binary scene payload, not new tooling features.
|
||||||
|
|
||||||
|
**File(s):**
|
||||||
|
- [crates/console/prometeu-hal/src/cartridge_loader.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/cartridge_loader.rs)
|
||||||
|
- [crates/console/prometeu-hal/src/asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-hal/src/asset.rs)
|
||||||
|
|
||||||
|
## Test Requirements
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
- Valid binary scene payloads decode into the expected `SceneBank`.
|
||||||
|
- Invalid payloads fail with explicit decoder errors.
|
||||||
|
- Per-layer metadata and tile contents survive round-trip fixture decode.
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
- `SCENE` assets can be loaded and preloaded through `AssetManager`.
|
||||||
|
- Scene bank slot installation works without breaking glyph/sound behavior.
|
||||||
|
|
||||||
|
### Manual Verification
|
||||||
|
- Inspect one representative binary scene fixture and confirm the decoded `SceneBank` matches the expected four-layer canonical shape.
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
- [ ] The binary `SCENE` payload format is explicitly defined and versioned.
|
||||||
|
- [ ] `AssetEntry` requirements for `SCENE` are documented and implemented.
|
||||||
|
- [ ] `perform_load_scene_bank(...)` is implemented without JSON payload parsing.
|
||||||
|
- [ ] Scene load/preload tests pass against the finalized binary decoder.
|
||||||
|
- [ ] Glyph and sound asset paths remain unaffected.
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
- Depends on `PLN-0011`.
|
||||||
|
- Should complete before the final integration/cleanup pass in `PLN-0015`.
|
||||||
|
- Source decision: `DEC-0013`
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
- Overloading `AssetEntry.metadata` can duplicate scene structure and make the contract brittle.
|
||||||
|
- A weak binary format definition can create hidden compatibility problems for future scene growth.
|
||||||
|
- Decoder validation gaps can surface later as corrupted scene state instead of explicit asset-load failures.
|
||||||
Loading…
x
Reference in New Issue
Block a user