feat(tools): per-scene opcode completeness tracker + 0x259 marker fix
Add tools/scene_opcode_coverage.py: histograms a scene's static opcodes and
classifies each vs the C# VM as impl / safe-noop / GAP (effectful op the VM
silently stubs). Implemented set is parsed live from VirtualMachine.cs case arms
(no drift); metadata from build/opcodes.json. Makes a half-rendered scene legible
("N ops still stubbed") instead of implying everything runs.
SC0000 baseline: 129 distinct ops, ~94.8% instruction-weighted handled, 68 GAP.
The tracker cross-checks opcodes.toml vs VM behavior and surfaced 0x259
(script-entry marker) missing its noop_headless flag -> reconciled in opcodes.toml
and rebuilt (regen: age_opcodes_himegari.py, opcode-reference.md).
Docs: tools-reference.md (tool row), phase-a-slice-plan.md (completeness gauge).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -213,6 +213,11 @@ op 0x90 (u0041BEB0, argc 7): `0x90 x y w h tgt_a tgt_b tgt_c`. Kelebek left it "
|
||||
- **summary:** 2 imm; runs in a chain right after script-entry 0x259, enumerating ids — prologue declaration/registration?
|
||||
- **grounding:** source=harness, confidence=low, noop_headless=True
|
||||
|
||||
### 0x259 `script-entry` (u00416410, argc 0)
|
||||
- **summary:** zero-arg; the first instruction of a script (offset 0), opens the decl chain that 0x258 continues — script/prologue entry marker, structural
|
||||
- **grounding:** source=harness, confidence=low, noop_headless=True
|
||||
- **evidence:** SC0000 offset 0x0 = op 0x259 (argc 0); 0x258's summary names it 'script-entry 0x259'; VM treats it as no-op (default stub) across all 279 CLEAN A0 scenes
|
||||
|
||||
## structural
|
||||
|
||||
### 0x71 `label-def` (u0041A7B0, argc 1)
|
||||
@@ -1045,10 +1050,6 @@ op 0x90 (u0041BEB0, argc 7): `0x90 x y w h tgt_a tgt_b tgt_c`. Kelebek left it "
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x259 `u00416410` (u00416410, argc 0)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
### 0x2bd `u00423100` (u00423100, argc 1)
|
||||
- **summary:** —
|
||||
- **grounding:** source=kelebek, confidence=low
|
||||
|
||||
@@ -308,6 +308,36 @@ Next visual chunk = **alpha/blend + effect fading** (`0x202/0x203` already store
|
||||
compositing. NOTE the two-boot gap: our Phase-B `--boot` runs *data* `*INIT` scripts; this added the *system*
|
||||
boot — a "full boot" should run both.
|
||||
|
||||
### A2b — Scene completeness gauge (opcode coverage tracker, 2026-07-07)
|
||||
|
||||
To stop guessing how "done" a rendered scene is, `tools/scene_opcode_coverage.py` histograms a scene's
|
||||
static opcodes and classifies each against the C# VM: **impl** (VM has a handler arm — real or a deliberate
|
||||
no-op like `set-font`), **safe-noop** (no arm, but `opcodes.toml` marks it `noop_headless` — a statement /
|
||||
block marker, correct to skip), or **GAP** (no arm and effectful → the VM silently `pc+1`s past it). The
|
||||
implemented set is parsed from `VirtualMachine.cs`'s `case` arms (single source of truth, no drift); output is
|
||||
`build/scene-opcode-coverage/<SCENE>.md`. This makes a half-rendered scene legible: *"N ops still stubbed"*,
|
||||
not *"something's wrong and we thought everything ran."*
|
||||
|
||||
**SC0000 baseline:** 129 distinct opcodes / 16257 instrs. Instruction-weighted the VM already covers **~94.8%**
|
||||
(impl 12368 + safe-noop 3053); the holes are **68 GAP opcodes / 836 instrs (5.1%)**. The GAP list clusters into
|
||||
concrete backlog buckets (drives the rendering roadmap below):
|
||||
- **ADV on-screen text** — `draw-string`(0x204)×205 + `0x7a` text-param×205 (1:1 paired). Dialogue text is
|
||||
currently surfaced via `IHost.ShowText` → Godot `Label`; the engine's *native* glyph/window draw path is
|
||||
unmodeled (cosmetic for now, but it owns text layout/speed).
|
||||
- **Unmodeled gfx-range cluster** — `0x21c–0x243` + `0x2bd/0x2bf` (e.g. 0x220×66, 0x22f×34, 0x228×33, 0x21e×25):
|
||||
siblings of the `0x212–0x21a` command-buffer family we implemented, **not yet reversed** → the biggest single
|
||||
rendering unknown (likely sprite/effect/blend geometry). RE these next before more compositor work.
|
||||
- **Timing** — `sleep`(0xc8)×20: animation pacing; fades/effects can't *animate* (only snap) until this exists.
|
||||
- **Audio/SFX** — `play-sound-effect`(0xb4)×24 + `0xb5/0xb6/0xc2/0xd9` (channel/volume/stop control) — stubbed.
|
||||
- **Scene coroutine** — `0x7b`×6 / `0x7c`×2 / `0x140`×1: the scene-coroutine framework backlog (multi-object
|
||||
scene setup routes through it; see the "SECOND latent gap" note in the status memory).
|
||||
- **Misc VM-support ops** — a long tail (`0x75-0x77`, `0x85/0x88/0x8b`, `0x93/0x94`, `0x197-0x1a4`, `0x1c7-0x1cf`,
|
||||
`0x1fd`, `0x20a/0x20c/0x20e`, …), 1–2 sites each; mixed markers vs effectful — triage per-op as the VM reaches them.
|
||||
|
||||
Re-run per scene (`scene_opcode_coverage.py SC0240 …`) to gauge any target. The tracker also cross-checks
|
||||
`opcodes.toml` metadata against VM behavior — it already surfaced `0x259` (script-entry marker) missing its
|
||||
`noop_headless` flag (now reconciled).
|
||||
|
||||
---
|
||||
|
||||
## Risks / open questions for A0
|
||||
|
||||
@@ -62,6 +62,7 @@ All opcode knowledge (ABI, semantics, provenance, `depends_on`) is hand-edited *
|
||||
| Tool | Purpose | Run | Reads → Writes |
|
||||
|---|---|---|---|
|
||||
| `vm0.py` | Headless Python bytecode VM (Phase A0 execution-model prototype; reuses `sys4load`). | `--test` (RECOVER unit test) · `--sweep [N]` (oracle coverage) · `--scene NAME` · `--settex NAME` (set-texture resId trace + exec trace) · `<file.BIN>` | corpus → stdout; `build/vm0-trace.json`; `build/settex-<NAME>.json` |
|
||||
| `scene_opcode_coverage.py` | Per-scene opcode completeness gauge: histograms a scene's static opcodes and classifies each **impl** / **safe-noop** / **GAP** (effectful op the VM silently stubs). Implemented set parsed from `VirtualMachine.cs` `case` arms; metadata from `opcodes.json`. Surfaces the concrete rendering/feature holes so a half-drawn scene reads as "N ops still stubbed", not "mystery". | `scene_opcode_coverage.py [SCENE …]` (default SC0000) | corpus, `build/opcodes.json`, `engine/…/VirtualMachine.cs`, `build/callscript-names.json` → ⚙ `build/scene-opcode-coverage/<SCENE>.md` + stdout |
|
||||
| `correlate_scope.py` | Align the VM's `set-texture(resId)` trace with the game's Frida load order → tag each load's DATA2 package, flag package transitions, dump the significant ops in each transition span (the **scope selector** hunt). | `correlate_scope.py <SCENE>` | `build/settex-<SCENE>.json` + `build/frida-load-order-result.json` + index → stdout |
|
||||
|
||||
## Engine (C#) — VM core, CLI, Godot frontend
|
||||
|
||||
Reference in New Issue
Block a user