engine-re.md: the write-log method, plaintext-value insight (store is obfuscated),
vm_operand_write ABI, the packer poll-until-unpacked fix, and the validation
(34k-global capture seeds the VM to match the engine's whole opening). Plus the
resync-tolerant align() / operand-hook blind-spot notes. tools-reference: the new
tool + trace --state.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
engine-re.md: the offset-path diff method, the working capture (operand hook
0x41b940; tick 0x410fb0 sees ecx!=ctx), the two capture caveats (hook-before-load
gating + operand-mode argc>=1 filter), SC0000 codebase id, and the first
divergence found (op 0xa0 jcc @ 0x8d on uninitialized G[0x6c1], the ADV-chrome
enable — a two-boot-gap state hole, not the predicted coroutine yield).
tools-reference.md: trace_engine_ops.py, diff_optrace.py, --trace-json.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Created the EngineCtx Ghidra struct (35 fields, 0xa1000) and retyped all
419 dispatch handlers' this -> EngineCtx* (CUSTOM_STORAGE, ctx in ECX).
Handlers now decompile ctx->cur_ctx_index / ctx->run_state_flags etc.
Validated: sleep_op_0xc8, gfx_op_0x215. tools-reference + engine-re.md
wired; CLAUDE.md canonical-map updated (root, outside repo).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extract op->real-handler map (handler(op)=ctx[0x26c93+op]) from the
registration routine's override stores; ghidra_handler_map.py +
build/op-handler-map.json (420 overrides). Cross-check vs opcodes.toml
found 0 real drift. One-shot Ghidra pass then labeled the /v2 image:
281 raw FUN_/LAB_ handlers -> op_0xNN_handler, 107 bare VAs -> functions,
31 hand-named preserved, opcode plate comment on every handler.
Includes the Task A spec + plan and the two-program (/v2 vs SMM) gotcha.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Prior-session WIP: RE findings on the engine frame cadence (engine-re.md,
phase-a-slice-plan.md, tools-reference.md) and a null-guard so headless
--shot-sequence advances without a rendered viewport texture.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The headless divergence that sent us chasing a phantom 'sleep' spin: op 0x72
wait-for-input was a no-op headless, so a run plowed past all 166 of a scene's
prompts into code no real playthrough reaches (SC0000 -> the name-entry poll
loop, spinning sleep 1 493k x to STEP-LIMIT). That path is a fiction.
Fix: VmOptions.HaltAtWaitForInput -> the VM halts (reason 'wait-for-input') at
0x72. run/play default to faithful (SC0000 now halts at ~402 steps, 0 sleeps,
matching the real run's path to the first prompt); --plow opts into the old
walk-every-page coverage. sweep stays plow by default (dialogue oracle, 284/13
unchanged); --halt-at-wait makes all 297 scenes halt cleanly at their first
prompt (0 STEP-LIMIT). Godot unaffected (really blocks on input; flag false).
Engine 58/58 (2 new); sweep default 284/13 unchanged; Godot selftest OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The existing trace framework only had a flat text formatter, so every question
became 'dump millions of lines, then grep'. This session that cost a long wrong
detour. Add, all observe-only (parity preserved):
- HistogramTraceSink: execution counts per opcode AND per call-site (script:pc)
with a sample operand. Dumped sorted after the run. This is what instantly
showed the 493k headless 'sleep's are INPUTNAME.BIN:0x1c3 (a name-entry poll
loop), not the opening.
- TraceSinkBase: tracks the frame stack -> attributes each step to its REAL
script (nested call-script frames included) = the 'which script is this pc in?'
answer a bare step trace can't give.
- TextTraceSink: op-filter (--trace-ops sleep,draw-texture,...) + script:pc tags.
- CompositeTraceSink: fan-out (text + histogram + Godot's call-script queue).
- OpcodeTable.ByLabel: mnemonic -> opcode for --trace-ops.
- CLI: --trace-histogram, --trace-ops, robust --trace-file (mkdir -p).
- Godot: --trace-histogram <file> profiles the REAL run (headless flow diverges:
real run to page 1 is 562 steps / 0 sleeps vs headless 2M steps / 493k sleeps).
- Also: --sleep-scale <f> debug knob to slow the paced opening for inspection.
Engine 56/56 (4 new); sweep parity 284/13; Godot builds + dogfooded end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Dumps one PNG per _Process frame (auto-advancing past input waits), so a
time-based sleep-paced effect can be verified as distinct frames. Confirmed
the SC0000 opening now steps through paced AE*/character/CG frames instead of
jumping straight to the final state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>