Commit Graph

151 Commits

Author SHA1 Message Date
gamer147
d9611a03b1 feat: model ADV coroutines and retained effect teardown 2026-07-10 09:45:43 -04:00
gamer147
54bd9a7006 docs: scene-entry state snapshot (capture_global_writes + --state)
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>
2026-07-09 13:32:52 -04:00
gamer147
d2e9cc5a99 re: record differential oracle outcome + first divergence
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>
2026-07-09 12:00:12 -04:00
gamer147
43249f430b plan: differential VM-vs-engine oracle (lever #3, spec + plan)
Control-flow offset-path diff: Frida engine op-tracer (recon-gated
tick/0x41b940 hook) + VM ITraceSink offsets + diff_optrace.py first-
divergence report. Deterministic opening (SC0000 --boot). Ready to
execute in a fresh context; prereq = game running at the opening.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 11:06:31 -04:00
gamer147
5cd5abb00a re: hot-helper naming (lever #2, pivoted from STL/CRT auto-naming)
Function ID recon = WEAK (0 matches; bundled FidDbs don't cover the VC9
static runtime) and our library workers are already named. Pivoted to
naming the hottest documented-but-unnamed helpers by call-count: named 5
(~2400 call sites) in Ghidra — vm_operand_fetch@0x41b940 (1021 refs),
vm_operand_write@0x425fb0, vm_operand_lvalue@0x415f30,
__security_check_cookie@0x54f981 (692), operator_new@0x5502be (533).
Validated: gfx_op_0x215 reads near source-level. Spec/plan + engine-re.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 10:38:29 -04:00
gamer147
1b151f6e17 re: apply EngineCtx struct to /v2 handlers; doc + canonical-map wiring
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>
2026-07-09 10:08:06 -04:00
gamer147
4a5d64a679 re: EngineCtx field registry (engine-ctx.toml) + builder
Canonical source vm-map/engine-ctx.toml (35 documented ctx fields) +
engine_ctx_build.py (--build/--lint, unit-tested) -> build/engine-ctx.json
+ docs/engine-ctx-reference.md. Applied to Ghidra in the next task.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 10:01:54 -04:00
gamer147
e166cab2d5 re(frida): import-map applied to /v2 — 248 Win32 APIs named; validated
Labeled the module-resident IAT at RVA 0x16f000 (imp_<dll>_<func> x248,
0 clobbers). Validated in decomp: FUN_0044f390 -> imp_kernel32_CreateFileA
/ SetFilePointer; sleep_timer_arm -> imp_winmm_timeGetTime (pins
DAT_0056f3d4). d3d9/heap-resolved DLLs unlabeled by design.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 09:26:19 -04:00
gamer147
7f8da4be71 plan: frida import-map slice (spec + implementation plan)
Replaces the abandoned pe-sieve Task B: attach + scan the live process to
map resolved import pointers (RVA->dll!Func) and label /v2. Recon-first
hard gate; clean labels; read-only Frida.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 09:19:36 -04:00
gamer147
23f518f39b re: document pe-sieve IAT failure on packed AGE.EXE; queue Frida import-map
pe-sieve /imp on the running game gave ~17 genuine imports (packer
bootstrap + one-per-DLL seed) and 300+ spurious stray-DWORD guesses:
the exe ships a zeroed IAT resolved via GetProcAddress, so there is no
conventional IAT to rebuild. Do not graft the output. Task B re-scoped
to a Frida live import-map (runtime_addr->dll!Func, RVA->name, label the
/v2 image); design captured in engine-re.md runbook.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 08:54:08 -04:00
gamer147
ace8ddf8eb re: auto-label all opcode dispatch handlers from FUN_00413860
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>
2026-07-09 08:32:01 -04:00
gamer147
51f6a421dc docs(re): scene-coroutine framework RE head-start (0x7b/0x7c/0x140 + gate) + magic-circle-stuck note
Head-start for the next slice: the fix for the slot-0 collapse is running label_125bd
via the scene-coroutine framework. 0x7b=yield-save, 0x7c=resume, 0x140=LABEL (target
TBD), G[0xaba5c] gate. Plus the revealed magic-circle-persists-across-transition issue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 00:04:40 -04:00
gamer147
ac481b4002 diag+docs: confirm grey-BG root cause = unfilled slot-table (label_125bd via stubbed coroutine op 0x140)
Traced end-to-end (AGE_DIAG_SETTEX): set-texture slot=G[0x62452] <- query-gfx-object?
(-1 for unregistered CG handles) -> fallback lookup-array-2d(rec[s3]=G[0x3239])=0
because the slot table is never filled: label_125bd (SC0000 0x50f, slots 4..13) is
gated behind the scene-coroutine framework (0x140 coroutine-yield, stubbed). Adds
env-gated VM set-texture/query slot diagnostics + GfxState.IsRegistered.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 23:55:50 -04:00
gamer147
9dd96bbc84 docs: grey-BG root cause (color-op alpha=tint-strength; slot-0 collision) + --gfx-log tool
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 23:42:20 -04:00
gamer147
620ffb4fb7 docs: record SC0000 anim cluster coverage (opcodes + slice plan)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:13:56 -04:00
gamer147
130eadee3d docs(re): SC0000 anim cluster op->field map (in-scope setters/queries + deferred)
Reversed via dispatch table: 0x22f/0x229 position, 0x239/0x231 spritesheet,
0x232 animated-color glow, 0x228/0x23f queries. Deferred 0x21f/0x223 matrix/scale
+ 0x236 movie. Ghidra renamed+annotated+saved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:58:55 -04:00
gamer147
a6377c6a60 docs(plan): SC0000 anim/transform/spritesheet cluster implementation plan
TDD plan: RE workers (known dispatch addresses) -> channel model -> ported
ping-pong interpolator on FrameClock -> wire setter ops -> host apply. Fixes
motion + spritesheet-cell + 'mach 5' pacing. Rotation/scale gated on Task 1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:25:07 -04:00
gamer147
4589b98be5 docs(spec): SC0000 anim/transform/spritesheet cluster design
One-unit scope for the gfx animation cluster (0x1fd, 0x21c-0x243): channel
model + faithful gfx_object_anim_interpolate port on FrameClock (fixes 'mach 5')
+ spritesheet cell selection. Grounded in the recovered dispatch table
(handler(op)=ctx[0x26c93+op]; Kelebek labels are drift) + the reversed
interpolator. Bounded RE Task-0 with known handler addresses.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:06:05 -04:00
gamer147
689d3ef433 docs: record blend/transparency slice A (colorkey + alpha/tint + fade fill)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:10:31 -04:00
gamer147
34cdfeda0e docs(re): interpolation RE pass stalled — anim-interp is ping-pong on frame clock; 0x202 consumer unlocated
Confirms both slice-A deferrals (smooth color-anim interp + additive). Ghidra
gfx_object_anim_interpolate annotated+saved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 18:48:50 -04:00
gamer147
fe61f7287c docs(plan): blend & transparency slice A implementation plan + colorkey RE
TDD plan (BlendMath -> RenderObject resolution -> host colorkey/alpha/tint blit
-> surfaceless fade fill -> docs). Records the reversed colorkey format and the
0x202/0x203 color workers in engine-re.md (Ghidra annotated+saved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 18:10:32 -04:00
gamer147
d5ea8aa84e docs(spec): blend & transparency slice A design (colorkey + alpha/tint + blend mode)
Hybrid architecture (engine resolves RenderObject blend plan, host blits).
Grounded in fresh Ghidra RE of gfx_object_composite/blit + the 0x202/0x203
color workers (renamed+plate-commented, saved). Includes a bounded RE Task-0
(colorkey format, blend-mode source, color/alpha anim coupling).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 18:02:35 -04:00
gamer147
0f81ab248f docs(slice): record frame-stepped VM as done+merged; note residual graphics gap
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 17:39:17 -04:00
gamer147
cdc50b571f docs: frame-stepped-vm spec+plan + frame-cadence Frida probes
Design artifacts for the merged frame-stepped VM work (throttle the Godot VM
to a per-frame op budget). Probes measured the native ~1788 ops/sec cadence
and uncapped D3D9 Present that motivated the wall-clock-op-rate approach.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 17:34:52 -04:00
gamer147
1f9bde3739 docs+godot: finish frame-cadence RE notes + headless shot null-guard
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>
2026-07-08 17:26:27 -04:00
gamer147
37fbbd278d docs: correct the overstated 'opening animates' claim across all docs
The frame-paced-sleep slice did NOT make the opening burst animate (only the
one-shot dramatic pauses). Correct the canonical result (phase-a-slice-plan),
the RE doc (engine-re), the opcode source+generated ref (opcodes.toml 0xc8),
and add correction banners to the point-in-time spec/plan. Also folds in the
diagnostics + headless halt-at-wait results into phase-a-slice-plan.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 10:53:08 -04:00
gamer147
791ea2ca0f fix(vm): faithful headless — halt at wait-for-input instead of plowing
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>
2026-07-08 10:45:32 -04:00
gamer147
9ccfc43959 feat(diag): aggregating + filtered trace sinks (histogram, op-filter, per-script)
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>
2026-07-08 09:50:07 -04:00
gamer147
52fccd25b9 docs(gfx): record the frame-paced sleep slice + SC0000 GAP shrink
sleep 0xc8 -> impl, 0x20c present -> safe-noop; handled 65->67/129 (51.9%).
Opening now animates through distinct sleep-paced frames (shot-sequence verified).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 09:08:31 -04:00
gamer147
2ed5eed261 feat(godot): --shot-sequence per-frame capture for verifying paced animation
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>
2026-07-08 09:07:22 -04:00
gamer147
6044a0d412 re(gfx): decode sleep 0xc8 timing (non-blocking ms timer) + 0x20c present
- sleep_op_0xc8 @0x420ec0: arms a non-blocking main-loop-polled timer
  (sleep_timer_arm @0x44cff0); operand = milliseconds. Also carries
  anti-tamper + gfx cmd-type 3 (not needed host-side).
- 0x20c = gfx_op_0x20c_present_frame (host presents continuously -> noop_headless).
- Ghidra annotated + saved; opcodes.toml rebuilt (lint clean); engine-re.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:57:22 -04:00
gamer147
22a972cc85 docs(gfx): implementation plan — frame-paced sleep
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:49:29 -04:00
gamer147
3d263a289a docs(gfx): spec — frame-paced sleep so the SC0000 opening animates
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:44:27 -04:00
gamer147
e52186a268 docs(gfx): correct 'immediate-mode slot-0' -> engine is RETAINED (native-verified)
The animation-slice note mis-called the SC0000 opening 'immediate-mode slot-0
blits', inferred from our own gfx oracle (which mis-reported slot 0). Verified from
native code + raw bytecode: draw-texture (0x1fb) -> gfx_object_bind_draw@0x47e870
binds a RETAINED object by handle (stores the slot INDEX, a live per-frame ref, not
a snapshot). The opening is a sleep-paced sequence of retained objects with distinct
handles + per-object working slots (CG loader: handle=CG_array[G[0x62450]] INIT2
array, slot=G[0x62452]). Our VM collapses the paced sequence -> only the final state
shows -> needs frame-pacing (scene-coroutine/sleep), not this alpha channel.

engine-re.md: new 'opening render path is RETAINED' subsection. Ghidra: annotated
gfx_op_0x1fb_draw_bind (gfx_object_bind_draw already documented retained).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 08:24:30 -04:00
gamer147
89e4b26215 docs(gfx): record the animation opening slice results + honest AE* finding
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:56:11 -04:00
gamer147
328c25bc56 feat(gfx): label + dispatch set-anim-transform 0x21e/0x220 into GfxState
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:37:28 -04:00
gamer147
53b84b8daf docs(gfx): decode anim_start/set_anim_clock + confirm SC0000 opening anim subset
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:19:15 -04:00
gamer147
bc9b817301 docs(gfx): implementation plan for the sprite animation subsystem (opening slice)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:05:43 -04:00
gamer147
f69b295c0e docs(gfx): RE the 0x21c-0x243 sprite animation cluster + subsystem spec
Native RE of the largest remaining SC0000 rendering GAP band: resolved every
handler in 0x21c-0x243 (+0x2bd/0x2bf) via the dispatch table (ctx[0x26c93+op]
from FUN_00413860). The cluster is ONE subsystem = sprite transform + animation/
tween; two members already named (0x234 anim_start, 0x238 set_anim_clock).
Decoded representative ops 0x220/0x21e (argc6, cmd-type 0xd, transform worker
(handle,op2,op3,f4,f5,f6); 0x21e normalizes floats /_DAT_00571c28 -> scale%);
worker gfx_anim_set_channel@0x47eaa0 arms an anim channel on the same object
model GfxState tracks. anim_start+set_anim_clock => a per-frame clock that makes
AE* fades animate rather than snap.

engine-re.md: full op->handler map + contract. Ghidra annotated (renamed
gfx_op_0x220_set_transform3_abs / gfx_op_0x21e_set_transform3_norm /
gfx_anim_set_channel + plate comments, saved).

Add the approved brainstorming spec for the opening-slice implementation
(wall-clock tween, opening-driven subset, passive GfxState + compositor tween +
alpha-aware blit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 22:57:42 -04:00
gamer147
a8f742cf57 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>
2026-07-07 22:57:25 -04:00
gamer147
962e55b43d fix(gfx): op 0x215 query registry is separate from the geometry store
The retained-mode "2nd CG renders off-screen" bug: GfxState conflated two
distinct native structures. It assigned a fabricated AcquireSlot() slot on
every GetOrCreate (called by all geometry/draw ops) and returned it from
QuerySlot (op 0x215). But Ghidra (gfx_op_0x215_register_query @0x42a0b0 /
gfx_op_0x1a2_registry_insert @0x42d360) shows 0x215 does map.find(handle) over
a registry populated ONLY by op 0x1a2 -- it never allocates a slot.

So a CG handle (never 0x1a2-registered) read back as "existing", took the
existing branch of label_12649, ran get-texture-size on the wrong slot (0),
got size 0, and computed dst = pos(0,0) - (w/2,h) = (-400,-600) -> off-screen.
The real engine returns -1 -> the fresh branch -> anchor from the INIT2 arrays
-> dst=(0,0).

Fix: GfxState keeps a separate _registry (HashSet) populated only by
Register() (op 0x1a2); QuerySlot returns the handle if registered else -1, and
no longer consults the geometry store or invents slots. Drop AcquireSlot /
GfxObject.Slot / the free-list.

Verified: Age.Cli gfx --boot SC0000.BIN -> all event CGs dst=(0,0), zero
(-400,-600) draws; Godot --boot pages 1/2/4 render opening CGs full-screen;
engine 44/44; sweep parity 284 exit / 13 STEP-LIMIT unchanged.

Docs: engine-re.md (query-registry-vs-geometry-store section), opcodes.toml
0x1a2/0x215 rebuilt; Ghidra helpers gfx_registry_map_find/hash_insert
annotated + saved. Tests rewritten to the native contract.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 22:09:11 -04:00
gamer147
48d1284a75 docs(gfx): RE the full render model (surfaces+objects+handle-order composite); redo spec+Phase1
Reversed create/set/draw-texture handlers + gfx_render_frame: surfaces at ctx+0x52bd4[slot]
(set-texture loads a file with a colorkey); objects in the ctx+0x408 registry reference a
surface by slot (live) + rect + position (V24) + visible bit; render iterates the registry
in ASCENDING HANDLE ORDER (= z-order) and composites visible objects. Answers both unknowns
(z-order = handle; slot 0 not special). Design spec + Phase 1 plan rebuilt on this model,
replacing the flawed flat-layer version. Ghidra annotated (gfx_op_0x1f8/9/b, gfx_object_bind_draw,
gfx_render_frame, gfx_object_composite, gfx_op_0x20c_present_frame).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 20:22:40 -04:00
gamer147
339d1bab4c docs(gfx): animated-compositor design spec + Phase 1 plan + animation RE
engine-re.md: the gfx animation/effects subsystem (gfx_anim_start/0x234, 0x1fd,
0x238 non-blocking anim clock, render model — the fades are host-loop-drivable, no
VM/host lockstep). Design spec: retained per-frame animated compositor, 4-phase.
Phase 1 plan (TDD): retained DrawLayer model + per-frame clear/recomposite. Ghidra
handlers/workers annotated (0x234/0x1fd/0x238/gfx_anim_start).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:41:13 -04:00
gamer147
9859fd88b9 docs(gfx): render drift RESOLVED (native ops + system boot); align living docs
engine-re.md: 0x1f7 erase correction + 'The render drift's SECOND half' (missing
INIT2 boot state via SYSTEM4) + gfx-command-buffer backlog marked DONE + worker
annotations noted. phase-a-slice-plan A2b: drift RESOLVED (both halves; CGs render
screenshot-confirmed; residual = AE* alpha/blend + cold anchors). tools-reference:
gfx --boot + godot --boot. (Status memory + MEMORY.md + CLAUDE.md updated on disk.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:09:34 -04:00
gamer147
62fa3231bc fix(gfx): 0x1f7 is a registry ERASE, not a create
RE correction: op 0x1f7's worker gfx_registry_erase_range (@0x47d8b0) loops
gfx_registry_erase over [handle, handle+count) — a teardown, not a create.
Objects are created lazily by the geometry SET ops (gfx_object_get_or_create).
GfxState.EraseRange + VM case + tests; opcodes.toml renamed gfx-elem-create ->
gfx-elem-erase; Ghidra handler + workers annotated. Booted SC0000 CG geometry
unchanged for the working CGs (no regression). Engine 40 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:05:31 -04:00
gamer147
7c03371519 chore(gfx): set dispatch labels for the gfx command-buffer ops
VM dispatches on the opcodes.toml label field (OpcodeTableJson), so the 14 gfx
ops' labels are set to their dispatch strings. Ops still stubbed until the VM
cases land (Task 3.3+); full suite green (34), lint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:44:32 -04:00
gamer147
dac684a5e6 docs(gfx): Phase 3 TDD plan + resolve vector-pairing risk in the spec
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:24:44 -04:00
gamer147
a4e173fc0f docs(gfx): Phase 2 design spec — host-side gfx command-buffer model
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:14:29 -04:00
gamer147
e0ac60e668 docs(gfx): reverse the full gfx command-buffer op contract (Phase 1)
Ghidra-read all 13 still-stubbed gfx-family handlers via the dispatch table
(0x1a2/0x1f7/0x1fa/0x1ff/0x202/0x203/0x212/0x213/0x216/0x217/0x218/0x219/0x21a);
recovered 0x219 (was unanalyzed). Every op writes a cmd-type into the current
object record then SETs fields (native worker) or QUERYs fields (returns to
operands). Recorded the op-contract table in engine-re.md, set opcodes.toml
semantics (source=investigation, confidence=high), renamed handlers in Ghidra.

Key finding: the drift has TWO stubbed drivers, not one — 0x215 (slot-select)
AND 0x218/0x21a (per-object geometry vectors feeding the anchor-preserve math).
The subsystem is a per-object record model (slot + position/anchor 3-vectors +
color) queried by the ops; native DirectDraw workers need not be modelled. This
is the spec for Phase 2 (host-side model design).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:01:14 -04:00
gamer147
e6f6803a15 docs(gfx): implementation plan for the gfx command-buffer subsystem
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 16:50:29 -04:00