Extract VM presentation opcode handler

This commit is contained in:
gamer147
2026-08-02 23:59:21 -04:00
parent 803df2826f
commit 07010298bd
4 changed files with 58 additions and 20 deletions

View File

@@ -185,6 +185,8 @@ default-slot and geometry mutation, direct and range transforms, clone, and eras
ADV-binding, and presentation labels remain in their respective dispatcher groups. ADV-binding, and presentation labels remain in their respective dispatcher groups.
`engine/Age.Engine/Vm/VirtualMachine.Animation.cs` owns retained spritesheet and color channels, timed and cyclic `engine/Age.Engine/Vm/VirtualMachine.Animation.cs` owns retained spritesheet and color channels, timed and cyclic
transforms, per-object animation control, frame-time sampling, and the shared animation-clock opcode handler. transforms, per-object animation control, frame-time sampling, and the shared animation-clock opcode handler.
`engine/Age.Engine/Vm/VirtualMachine.Presentation.cs` owns queued surface-alpha transitions, frame and object-range
publication, skip-aware blocking fades/crossfades, foreground-transition waits, and graphics command-queue clear.
The disposable `build/page-map-<SCENE>.jsonl` files are produced by editor/development Godot runs and map The disposable `build/page-map-<SCENE>.jsonl` files are produced by editor/development Godot runs and map
runtime ADV page ordinals to their authoritative script offsets for `tools/locate_page.py`. Packaged exports runtime ADV page ordinals to their authoritative script offsets for `tools/locate_page.py`. Packaged exports

View File

@@ -655,6 +655,12 @@ do not mix mechanical moves with semantic changes.
existing positions and routes the separated groups through `StepAnimation`; presentation transitions and movie existing positions and routes the separated groups through `StepAnimation`; presentation transitions and movie
masking remain outside the guarded handler. Runtime validation remains green. masking remain outside the guarded handler. Runtime validation remains green.
The sixth bounded `VirtualMachine.Step` extraction moved queued surface-alpha transitions, frame and object-
range publication, skip-aware blocking fades/crossfades, foreground-transition waits, and graphics command-
queue clear into `engine/Age.Engine/Vm/VirtualMachine.Presentation.cs`. The top-level dispatcher retains all
labels and aliases at their existing positions and routes them through guarded `StepPresentation`; movie-mask
transition dispatch remains with the movie handler. Runtime validation remains green.
**Gate:** no externally visible behavior or command changes; generated artifacts are byte-identical where **Gate:** no externally visible behavior or command changes; generated artifacts are byte-identical where
deterministic, and the corresponding engine, Python, Godot, and corpus validations remain green after deterministic, and the corresponding engine, Python, Godot, and corpus validations remain green after
each domain move. each domain move.
@@ -1027,7 +1033,8 @@ layer's rendering diverges from ADV; save layout.
Continue step 2 of the **codebase consolidation** maintenance slice: behavior-neutral physical splits backed Continue step 2 of the **codebase consolidation** maintenance slice: behavior-neutral physical splits backed
by the tracked launcher and layered validation driver. With the planned `Main`, `GodotAdvHost`, and `GfxState` by the tracked launcher and layered validation driver. With the planned `Main`, `GodotAdvHost`, and `GfxState`
domains isolated and the audio, movie, surface/texture, retained-object, and animation `VirtualMachine.Step` domains isolated and the audio, movie, surface/texture, retained-object, and animation `VirtualMachine.Step`
families routed through domain handlers, extract retained presentation/transition dispatch next without replacing families routed through domain handlers, with retained presentation/transition dispatch now isolated as well,
the proven dispatcher or changing public types, commands, and generated output. extract the ADV text-layout/rendering opcode family next without replacing the proven dispatcher or changing
public types, commands, and generated output.
Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does Concrete playthrough blockers may still preempt this bounded maintenance work; the consolidation effort does
not replace Phase B gameplay validation or the open cross-platform gates. not replace Phase B gameplay validation or the open cross-platform gates.

View File

@@ -0,0 +1,46 @@
using Age.Engine.Hosting;
using Age.Engine.Model;
namespace Age.Engine.Vm;
public sealed partial class VirtualMachine
{
private int StepPresentation(string label, IReadOnlyList<Operand> a, int pc)
{
switch (label)
{
case "queue-surface-alpha-transition": // 0x223: target surface crossfade over two object ranges
Gfx.QueueSurfaceAlphaTransition(Read(a[0]), (int)Read(a[1]), Read(a[2]), (int)Read(a[3]),
Read(a[4]), (int)Read(a[5]), Read(a[6]), Read(a[7])); return pc + 1;
case "present-frame": // 0x20c: read/message-skip path snaps a queued transition to its endpoint
_host.PresentFrame(Gfx); return pc + 1;
case "fade-surface-in-from-black": // 0x21: blocking black -> captured full-frame surface
case "u00418860":
_host.FadeSurfaceWithBlack(
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.FromBlack,
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "fade-surface-out-to-black": // 0x22: blocking captured full-frame surface -> black
case "u00418920":
_host.FadeSurfaceWithBlack(
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.ToBlack,
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "crossfade-surfaces": // 0x25: legacy full-frame surface alpha transition
case "u00418B40":
_host.CrossfadeSurfaces(
Gfx, (int)Read(a[0]), (int)Read(a[1]), Read(a[2]),
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "mark-frame-yield": // 0x21c: normal foreground-transition scheduler/resume boundary
_host.WaitForForegroundTransition(Gfx); return pc + 1;
case "clear-gfx-command-queue": // 0x224: retained compositor does not use this native queue
return pc + 1;
case "present-gfx-object-range": // 0x222: publish pending retained changes in the selected range
case "u004216C0":
_host.PresentObjectRange(Gfx, Read(a[0]), Read(a[1])); return pc + 1;
default:
throw new InvalidOperationException($"Non-presentation opcode routed to presentation handler: {label}");
}
}
}

View File

@@ -2606,35 +2606,18 @@ public sealed partial class VirtualMachine
case "play-movie-mask-transition": case "play-movie-mask-transition":
return StepMovie(label, ins, pc); return StepMovie(label, ins, pc);
case "queue-surface-alpha-transition": // 0x223: target surface crossfade over two object ranges case "queue-surface-alpha-transition": // 0x223: target surface crossfade over two object ranges
Gfx.QueueSurfaceAlphaTransition(Read(a[0]), (int)Read(a[1]), Read(a[2]), (int)Read(a[3]),
Read(a[4]), (int)Read(a[5]), Read(a[6]), Read(a[7])); return pc + 1;
case "present-frame": // 0x20c: read/message-skip path snaps a queued transition to its endpoint case "present-frame": // 0x20c: read/message-skip path snaps a queued transition to its endpoint
_host.PresentFrame(Gfx); return pc + 1;
case "fade-surface-in-from-black": // 0x21: blocking black -> captured full-frame surface case "fade-surface-in-from-black": // 0x21: blocking black -> captured full-frame surface
case "u00418860": case "u00418860":
_host.FadeSurfaceWithBlack(
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.FromBlack,
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "fade-surface-out-to-black": // 0x22: blocking captured full-frame surface -> black case "fade-surface-out-to-black": // 0x22: blocking captured full-frame surface -> black
case "u00418920": case "u00418920":
_host.FadeSurfaceWithBlack(
Gfx, (int)Read(a[0]), Read(a[1]), SurfaceBlackFadeDirection.ToBlack,
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "crossfade-surfaces": // 0x25: legacy full-frame surface alpha transition case "crossfade-surfaces": // 0x25: legacy full-frame surface alpha transition
case "u00418B40": case "u00418B40":
_host.CrossfadeSurfaces(
Gfx, (int)Read(a[0]), (int)Read(a[1]), Read(a[2]),
_messageSkipServiceActive || _host.IsMessageSkipActive);
return pc + 1;
case "mark-frame-yield": // 0x21c: normal foreground-transition scheduler/resume boundary case "mark-frame-yield": // 0x21c: normal foreground-transition scheduler/resume boundary
_host.WaitForForegroundTransition(Gfx); return pc + 1;
case "clear-gfx-command-queue": // 0x224: retained compositor does not use this native queue case "clear-gfx-command-queue": // 0x224: retained compositor does not use this native queue
return pc + 1;
case "present-gfx-object-range": // 0x222: publish pending retained changes in the selected range case "present-gfx-object-range": // 0x222: publish pending retained changes in the selected range
case "u004216C0": case "u004216C0":
_host.PresentObjectRange(Gfx, Read(a[0]), Read(a[1])); return pc + 1; return StepPresentation(label, a, pc);
default: default:
// Stub is per-instruction frequency (the VM handles ~30 ops; the rest hit here, e.g. // Stub is per-instruction frequency (the VM handles ~30 ops; the rest hit here, e.g.
// 0x258/0x259 stmt markers appear en masse), so gate it with Step — else --trace floods. // 0x258/0x259 stmt markers appear en masse), so gate it with Step — else --trace floods.