Commit Graph

45 Commits

Author SHA1 Message Date
gamer147
f840e356cf Implement script-configured input bindings 2026-07-21 10:32:37 -04:00
gamer147
d0b2d31d2e Implement ADV layout cursor and bounds 2026-07-21 09:48:25 -04:00
gamer147
f6479209ea Implement ROOM fades and character voices 2026-07-21 00:47:29 -04:00
gamer147
f21a4c06bf Implement root reload and title debug launcher 2026-07-20 22:32:49 -04:00
gamer147
097473fe16 Land SYSTEM4-rooted Godot boot 2026-07-20 18:13:32 -04:00
gamer147
6aede1e525 Implement detached object animation control 2026-07-20 14:53:34 -04:00
gamer147
d740c27b4a Implement retained graphics lifecycle ops 2026-07-20 14:29:41 -04:00
gamer147
458b65aee6 Reverse shared SAVE.DAT integer opcodes 2026-07-20 13:33:27 -04:00
gamer147
e0aae05f32 Implement AGE text line spacing 2026-07-19 23:32:38 -04:00
gamer147
32a67b88de Implement visible ADV History presentation 2026-07-18 23:59:26 -04:00
gamer147
ac5437c5cf Implement ADV History data navigation 2026-07-18 23:41:23 -04:00
gamer147
b7ea16b54c Implement retained ADV History writers 2026-07-18 23:28:26 -04:00
gamer147
96e5306148 Fix retained background lifecycle 2026-07-12 00:00:45 -04:00
gamer147
b41ae36168 Fix AE001H cyclic color blending 2026-07-11 22:21:10 -04:00
gamer147
f195934324 Fix AE001H translation target query 2026-07-11 21:40:16 -04:00
gamer147
0bf6b43a32 Fix AE001H spritesheet animation 2026-07-11 20:37:26 -04:00
gamer147
593a24b510 fix(gfx): restore third CG glow 2026-07-11 20:05:51 -04:00
gamer147
1f18a378d3 Optimize identity raster paths 2026-07-11 15:31:56 -04:00
gamer147
3b5dbc6c2c Optimize static wait presentation 2026-07-11 13:56:30 -04:00
gamer147
54d11f513d Fix ADV chrome one-shot blending 2026-07-11 13:28:31 -04:00
gamer147
024accd8d1 Implement SC0000 movie playback lifecycle 2026-07-11 12:27:51 -04:00
gamer147
82afcf5506 Fix native retained presentation batching 2026-07-10 21:37:42 -04:00
gamer147
992215cc48 Implement native 0x202 color interpolation 2026-07-10 20:49:28 -04:00
gamer147
7f900c8fc6 Implement ADV foreground transition lifecycle 2026-07-10 18:49:53 -04:00
gamer147
bb16a5496a feat: add affine rotation rendering and timeline diagnostics 2026-07-10 17:54:33 -04:00
gamer147
014d128ccd fix: align animation pacing and transforms with native 2026-07-10 15:41:17 -04:00
gamer147
c14c7fdced feat: split native scale and translation channels 2026-07-10 10:28:11 -04:00
gamer147
d9611a03b1 feat: model ADV coroutines and retained effect teardown 2026-07-10 09:45:43 -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
c0b6199dbc fix: color-op alpha (0x202/0x203/0x232) is TINT STRENGTH, not object opacity
Root cause (evidence: gfx-log) of the opening-CG grey background: a CG drawn with
(alpha=0, color=white) means 'no tint' = fully opaque, but slice-A conflated the
color alpha with object opacity -> the CG rendered transparent. RenderObject now
carries TintStrength separately from Alpha (opacity); resolution keeps textured
objects opaque. Tests updated to the evidence-based semantics.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 23:41:03 -04:00
gamer147
b9ca284f90 feat: port anim interpolator (ping-pong spritesheet cell + color glow) on nowMs
BlendMath.PingPong + SnapshotVisibleObjects(nowMs); no-arg overload keeps
headless callers deterministic (parity held, 76/76 + sweep 284/13).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:05:00 -04:00
gamer147
7ca51bfdf3 feat: add src-rect (spritesheet) + animated-color channel fields/mutators
Adapted to Task-1 RE: position is a direct V24 set (not ping-pong); the
oscillating channels are src-rect scroll (0x231/0x239) and color glow (0x232).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:02:46 -04:00
gamer147
143fe8258c feat: resolve per-object alpha/tint/blend into RenderObject (colorkey retained)
0x202/0x203 now route through GfxState.SetObjectColor (sets HasColor);
SnapshotVisibleObjects resolves Alpha/Tint/BlendKind. Drops the stale
'alpha deferred' trace stub — alpha/tint is now consumed by the compositor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:06:34 -04:00
gamer147
4ee7a26e3f feat: add BlendMath (colorkey match + ARGB unpack)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 19:04:12 -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
8ac9e6675b fix(gfx): serialize GetOrCreate/Register/Release on _lock (compositor race)
Once sleep paces the VM thread, the main-thread compositor's SnapshotVisibleObjects
truly overlaps VM-thread _objects/_registry writes. GetOrCreate/Register/Release were
unlocked -> 'Destination array is not long enough' under concurrent enumeration.
_lock is re-entrant so BindDraw/EraseRange (already locked) stay correct. 52 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 09:01:13 -04:00
gamer147
bcb95f3bb5 feat(gfx): surface anim channel to the compositor via RenderObject.AnimState
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:39:18 -04:00
gamer147
6339b93c72 feat(gfx): GfxState animation-channel model (per-object transform + global clock)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 23:34:52 -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
6775be2ac5 feat(gfx): surface+object render model (replaces flat layers)
GfxState: SurfaceStore (slot->{resId,colorkey} from create/set-texture) + object
SourceSlot/SrcRect/Visible (from draw-texture bind); SnapshotVisibleObjects returns
visible objects in ascending-handle order (=z-order) with their live surface resolved.
VM set/create/draw-texture wired to it. Oracle dumps visible objects. Erase removes the
object from the registry (faithful). Engine 44 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 20:28:47 -04:00
gamer147
fc9e46ee85 feat(gfx): retained DrawLayer list in GfxState (thread-safe)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 19:45:28 -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
f66b5e7f16 feat(gfx): GfxState host-agnostic command-buffer model
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:33:51 -04:00
gamer147
3f9117363c Refactor VM to ExecFrame + tag emitted lines with source script (no behavior change)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 13:11:50 -04:00
gamer147
a704765ea0 feat(a1): .NET 8 solution scaffold + Model + OpcodeTable loader
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 13:49:02 -04:00