Extract VM ADV text opcode handler

This commit is contained in:
gamer147
2026-08-03 00:04:52 -04:00
parent 07010298bd
commit 4712343c79
4 changed files with 214 additions and 143 deletions

View File

@@ -187,6 +187,9 @@ ADV-binding, and presentation labels remain in their respective dispatcher group
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 `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. publication, skip-aware blocking fades/crossfades, foreground-transition waits, and graphics command-queue clear.
`engine/Age.Engine/Vm/VirtualMachine.AdvText.cs` owns live ADV text emission, layout/cursor/wait-indicator state,
text style and glyph-delay control, direct surface-string and retained numeric-glyph rendering, and retained
text/wait-object bindings; text history and input/skip/auto services remain separate.
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

@@ -661,6 +661,13 @@ do not mix mechanical moves with semantic changes.
labels and aliases at their existing positions and routes them through guarded `StepPresentation`; movie-mask 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. transition dispatch remains with the movie handler. Runtime validation remains green.
The seventh bounded `VirtualMachine.Step` extraction moved live ADV text emission, layout/cursor/wait-indicator
state, text style and glyph-delay control, direct surface-string and retained numeric-glyph rendering, and
retained text/wait-object bindings into `engine/Age.Engine/Vm/VirtualMachine.AdvText.cs`. The top-level
dispatcher retains all labels at their existing positions and routes the separated groups through guarded
`StepAdvText`; the complete instruction remains available for emission and layout-reset bytecode offsets.
Text-history and input/skip/auto services remain outside the 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.
@@ -1034,7 +1041,7 @@ Continue step 2 of the **codebase consolidation** maintenance slice: behavior-ne
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, with retained presentation/transition dispatch now isolated as well, families routed through domain handlers, with retained presentation/transition dispatch now isolated as well,
extract the ADV text-layout/rendering opcode family next without replacing the proven dispatcher or changing and ADV text-layout/rendering dispatch isolated, extract the ADV text-history opcode family next without
public types, commands, and generated output. 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,187 @@
using Age.Engine.Hosting;
using Age.Engine.Model;
namespace Age.Engine.Vm;
public sealed partial class VirtualMachine
{
private int StepAdvText(string label, Instruction ins, int pc)
{
var a = ins.Args;
switch (label)
{
case "show-text":
RefreshAdvReadSkipState();
foreach (var o in a)
{
if (!IsStr(o)) continue;
int off = o.Type == T_STR ? (int)o.Value : ins.Offset;
_cur.EmitSeen.TryGetValue(off, out var c); c++; _cur.EmitSeen[off] = c;
if (c > _o.EmitCap) { HaltReason = $"LOOP:line@0x{off:x}×{c}"; return HALT; }
string text = ReadStr(o);
Emitted.Add((off, text, _cur.Script.Name));
int layoutSlot = a.Count > 0 ? (int)Read(a[0]) : 0;
string[] scriptStack;
lock (_debugControlLock) scriptStack = _activeFrameNames.ToArray();
var liveRun = new AdvLiveTextRun(
off, TextHistory.GetLayoutSnapshot(layoutSlot), _advTextStyle, text, scriptStack);
TextHistory.AppendText(layoutSlot, off, text, _advTextStyle);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(liveRun.Layout.Slot);
AdvRetainedTextRunResult? retained = _host.ShowText(
Gfx, binding, liveRun, _messageGlyphDelayMilliseconds);
if (retained is { } result)
TextHistory.SetCursor(
result.LayoutSlot, result.CursorX, result.CursorY);
}
return pc + 1;
case "define-adv-text-layout": // 0x70: configure layout and begin a logical retained group
TextHistory.DefineLayout((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]),
(int)Read(a[3]), (int)Read(a[4]));
return pc + 1;
case "reset-adv-text-layout": // 0x71: reset layout and begin the next logical retained group
{
int requestedSlot = (int)Read(a[0]);
TextHistory.ResetLayout(requestedSlot);
var layout = TextHistory.GetLayoutSnapshot(requestedSlot);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(layout.Slot);
if (binding.FirstObjectHandle >= 0 && binding.ObjectCapacity > 0)
Gfx.EraseRange(binding.FirstObjectHandle, binding.ObjectCapacity);
_host.SetAdvTextCursor(layout.Slot, layout.CursorX, layout.CursorY);
_host.ResetRenderedAdvTextLayout(Gfx, binding);
_cur.ReadMessageOffset = ins.Offset;
_sharedProfile.ReadText.CommitPending();
RefreshAdvReadSkipState();
return pc + 1;
}
case "set-adv-text-reset-cursor": // 0x79: configure cursor restored by a later 0x71
TextHistory.SetResetCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
return pc + 1;
case "set-adv-text-cursor": // 0x7a (layout slot, x, y); slot 0 means current natively
TextHistory.SetCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
_host.SetAdvTextCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2])); return pc + 1;
case "set-adv-text-bounds": // 0x1c1: layout-local right/bottom overflow boundaries
TextHistory.SetBounds((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
return pc + 1;
case "configure-adv-wait-indicator": // 0x73: per-layout animated input-wait marker
_host.ConfigureAdvWaitIndicator(new AdvWaitIndicatorConfig(
(int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]), (int)Read(a[3]),
(int)Read(a[4]), (int)Read(a[5]), (int)Read(a[6]), (int)Read(a[7]),
(int)Read(a[8]), Read(a[9])));
return pc + 1;
case "u0041B9F0":
case "set-adv-wait-indicator-enabled": // 0x1ce: explicit marker service start/stop
_host.SetAdvWaitIndicatorEnabled(Read(a[0]) != 0);
return pc + 1;
case "u00420CE0":
case "publish-adv-text-layout": // 0x20a: publish layout and current marker frame if active
{
int requestedSlot = (int)Read(a[0]);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(requestedSlot);
_host.PublishAdvTextLayout(Gfx, binding);
return pc + 1;
}
case "draw-string": // 0x204 (surface slot, x, y, string)
_host.DrawStringToSurface((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]), ReadStr(a[3]),
_advTextStyle);
return pc + 1;
case "u00420A60": // pre-reference compatibility
case "draw-formatted-integer": // 0x205 (surface slot, x, y, value, field width, flags)
{
int x = (int)Read(a[1]);
string text = FormatIntegerForSurface(
ref x, unchecked((int)Read(a[3])), (int)Read(a[4]), (int)Read(a[5]));
_host.DrawStringToSurface((int)Read(a[0]), x, (int)Read(a[2]), text, _advTextStyle);
return pc + 1;
}
case "set-font-size":
_advTextStyle = _advTextStyle with { PrimaryFontSize = (int)Read(a[0]) }; return pc + 1;
case "set-ruby-font-size":
_advTextStyle = _advTextStyle with { RubyFontSize = (int)Read(a[0]) }; return pc + 1;
case "u0041B3D0":
case "set-text-line-spacing":
_advTextStyle = _advTextStyle with { LineSpacing = (int)Read(a[0]) }; return pc + 1;
case "set-font-bold":
_advTextStyle = _advTextStyle with { Bold = Read(a[0]) != 0 }; return pc + 1;
case "set-text-color":
_advTextStyle = _advTextStyle with { TextColor = Read(a[0]) }; return pc + 1;
case "set-text-effect-color":
_advTextStyle = _advTextStyle with { EffectColor = Read(a[0]) }; return pc + 1;
case "set-text-render-mode":
_advTextStyle = _advTextStyle with { RenderMode = (int)Read(a[0]) }; return pc + 1;
case "set-text-effect-offset":
_advTextStyle = _advTextStyle with
{
EffectOffsetX = (int)Read(a[0]),
EffectOffsetY = (int)Read(a[1])
};
return pc + 1;
case "set-adv-text-layout-origin": // 0x198; slot 0 selects the current layout
case "u0041B540":
TextHistory.SetLayoutOrigin((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
return pc + 1;
case "get-message-glyph-delay": // 0x7f
case "u00414C60":
Write(a[0], _messageGlyphDelayMilliseconds); return pc + 1;
case "set-message-glyph-delay": // 0x1b5
case "u0041B5F0":
_messageGlyphDelayMilliseconds = System.Math.Max(0, (int)Read(a[0]));
_host.SetMessageGlyphDelayMilliseconds(_messageGlyphDelayMilliseconds);
return pc + 1;
case "end-text-line":
TextHistory.EndLine((int)Read(a[0]), _advTextStyle); return pc + 1;
case "set-font":
_advTextStyle = _advTextStyle with { FontFace = ReadStr(a[0]) }; return pc + 1;
case "comment": case "display-furigana": case "dev_ukn":
return pc + 1;
case "u0041F3A0":
case "register-numeric-glyph-style": // 0x13a: (style)(surface)(atlas x/y)(digit w/h)
{
int styleIndex = unchecked((int)Read(a[0]));
if (!Gfx.RegisterNumericGlyphStyle(styleIndex, unchecked((int)Read(a[1])),
unchecked((int)Read(a[2])), unchecked((int)Read(a[3])),
unchecked((int)Read(a[4])), unchecked((int)Read(a[5]))))
{
HaltReason ??= $"numeric-glyph-style-index-out-of-range:{styleIndex}";
return HALT;
}
return pc + 1;
}
case "u00422460":
case "draw-decimal-glyphs": // 0x23b: retained decimal glyph draw
{
int styleIndex = unchecked((int)Read(a[1]));
if (!Gfx.DrawDecimalGlyphs(Read(a[0]), styleIndex, unchecked((int)Read(a[2])),
unchecked((int)Read(a[3])), unchecked((int)Read(a[4])),
unchecked((int)Read(a[5])), unchecked((int)Read(a[6]))))
{
HaltReason ??= (uint)styleIndex >= 11
? $"numeric-glyph-style-index-out-of-range:{styleIndex}"
: $"numeric-glyph-style-unregistered:{styleIndex}";
return HALT;
}
return pc + 1;
}
case "set-adv-wait-indicator-handle": // 0x212 (layout)(retained handle)
{
int requestedSlot = (int)Read(a[0]);
TextHistory.SetWaitIndicatorObjectHandle(requestedSlot, Read(a[1]));
AdvTextLayoutSnapshot layout =
TextHistory.GetLayoutSnapshot(requestedSlot);
_host.BindAdvWaitIndicator(
TextHistory.GetPresentationBinding(layout.Slot),
layout);
return pc + 1;
}
case "set-adv-text-object-range": // 0x213 (layout)(first handle)(count)
{
TextHistory.SetTextObjectRange((int)Read(a[0]), Read(a[1]), Read(a[2]));
return pc + 1;
}
default:
throw new InvalidOperationException($"Non-ADV-text opcode routed to ADV-text handler: {label}");
}
}
}

View File

@@ -1963,91 +1963,20 @@ public sealed partial class VirtualMachine
return pc + 1; return pc + 1;
} }
case "show-text": case "show-text":
RefreshAdvReadSkipState(); case "define-adv-text-layout":
foreach (var o in a) case "reset-adv-text-layout":
{ case "set-adv-text-reset-cursor":
if (!IsStr(o)) continue; case "set-adv-text-cursor":
int off = o.Type == T_STR ? (int)o.Value : ins.Offset; case "set-adv-text-bounds":
_cur.EmitSeen.TryGetValue(off, out var c); c++; _cur.EmitSeen[off] = c; case "configure-adv-wait-indicator":
if (c > _o.EmitCap) { HaltReason = $"LOOP:line@0x{off:x}×{c}"; return HALT; }
string text = ReadStr(o);
Emitted.Add((off, text, _cur.Script.Name));
int layoutSlot = a.Count > 0 ? (int)Read(a[0]) : 0;
string[] scriptStack;
lock (_debugControlLock) scriptStack = _activeFrameNames.ToArray();
var liveRun = new AdvLiveTextRun(
off, TextHistory.GetLayoutSnapshot(layoutSlot), _advTextStyle, text, scriptStack);
TextHistory.AppendText(layoutSlot, off, text, _advTextStyle);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(liveRun.Layout.Slot);
AdvRetainedTextRunResult? retained = _host.ShowText(
Gfx, binding, liveRun, _messageGlyphDelayMilliseconds);
if (retained is { } result)
TextHistory.SetCursor(
result.LayoutSlot, result.CursorX, result.CursorY);
}
return pc + 1;
case "define-adv-text-layout": // 0x70: configure layout and begin a logical retained group
TextHistory.DefineLayout((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]),
(int)Read(a[3]), (int)Read(a[4]));
return pc + 1;
case "reset-adv-text-layout": // 0x71: reset layout and begin the next logical retained group
{
int requestedSlot = (int)Read(a[0]);
TextHistory.ResetLayout(requestedSlot);
var layout = TextHistory.GetLayoutSnapshot(requestedSlot);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(layout.Slot);
if (binding.FirstObjectHandle >= 0 && binding.ObjectCapacity > 0)
Gfx.EraseRange(binding.FirstObjectHandle, binding.ObjectCapacity);
_host.SetAdvTextCursor(layout.Slot, layout.CursorX, layout.CursorY);
_host.ResetRenderedAdvTextLayout(Gfx, binding);
_cur.ReadMessageOffset = ins.Offset;
_sharedProfile.ReadText.CommitPending();
RefreshAdvReadSkipState();
return pc + 1;
}
case "set-adv-text-reset-cursor": // 0x79: configure cursor restored by a later 0x71
TextHistory.SetResetCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
return pc + 1;
case "set-adv-text-cursor": // 0x7a (layout slot, x, y); slot 0 means current natively
TextHistory.SetCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
_host.SetAdvTextCursor((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2])); return pc + 1;
case "set-adv-text-bounds": // 0x1c1: layout-local right/bottom overflow boundaries
TextHistory.SetBounds((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]));
return pc + 1;
case "configure-adv-wait-indicator": // 0x73: per-layout animated input-wait marker
_host.ConfigureAdvWaitIndicator(new AdvWaitIndicatorConfig(
(int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]), (int)Read(a[3]),
(int)Read(a[4]), (int)Read(a[5]), (int)Read(a[6]), (int)Read(a[7]),
(int)Read(a[8]), Read(a[9])));
return pc + 1;
case "u0041B9F0": case "u0041B9F0":
case "set-adv-wait-indicator-enabled": // 0x1ce: explicit marker service start/stop case "set-adv-wait-indicator-enabled": // 0x1ce: explicit marker service start/stop
_host.SetAdvWaitIndicatorEnabled(Read(a[0]) != 0);
return pc + 1;
case "u00420CE0": case "u00420CE0":
case "publish-adv-text-layout": // 0x20a: publish layout and current marker frame if active case "publish-adv-text-layout": // 0x20a: publish layout and current marker frame if active
{ case "draw-string":
int requestedSlot = (int)Read(a[0]);
AdvTextLayoutPresentationBinding binding =
TextHistory.GetPresentationBinding(requestedSlot);
_host.PublishAdvTextLayout(Gfx, binding);
return pc + 1;
}
case "draw-string": // 0x204 (surface slot, x, y, string)
_host.DrawStringToSurface((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2]), ReadStr(a[3]),
_advTextStyle);
return pc + 1;
case "u00420A60": // pre-reference compatibility case "u00420A60": // pre-reference compatibility
case "draw-formatted-integer": // 0x205 (surface slot, x, y, value, field width, flags) case "draw-formatted-integer": // 0x205 (surface slot, x, y, value, field width, flags)
{ return StepAdvText(label, ins, pc);
int x = (int)Read(a[1]);
string text = FormatIntegerForSurface(
ref x, unchecked((int)Read(a[3])), (int)Read(a[4]), (int)Read(a[5]));
_host.DrawStringToSurface((int)Read(a[0]), x, (int)Read(a[2]), text, _advTextStyle);
return pc + 1;
}
case "wait-for-input": case "wait-for-input":
RefreshAdvReadSkipState(); RefreshAdvReadSkipState();
// Faithful headless: no player => halt here rather than plow past every prompt (see VmOptions). // Faithful headless: no player => halt here rather than plow past every prompt (see VmOptions).
@@ -2387,31 +2316,17 @@ public sealed partial class VirtualMachine
case "clear-text-history": // 0x85: bound the backlog to the current ordinary ADV block case "clear-text-history": // 0x85: bound the backlog to the current ordinary ADV block
TextHistory.Clear(); return pc + 1; TextHistory.Clear(); return pc + 1;
case "set-font-size": case "set-font-size":
_advTextStyle = _advTextStyle with { PrimaryFontSize = (int)Read(a[0]) }; return pc + 1;
case "set-ruby-font-size": case "set-ruby-font-size":
_advTextStyle = _advTextStyle with { RubyFontSize = (int)Read(a[0]) }; return pc + 1;
case "u0041B3D0": case "u0041B3D0":
case "set-text-line-spacing": case "set-text-line-spacing":
_advTextStyle = _advTextStyle with { LineSpacing = (int)Read(a[0]) }; return pc + 1;
case "set-font-bold": case "set-font-bold":
_advTextStyle = _advTextStyle with { Bold = Read(a[0]) != 0 }; return pc + 1;
case "set-text-color": case "set-text-color":
_advTextStyle = _advTextStyle with { TextColor = Read(a[0]) }; return pc + 1;
case "set-text-effect-color": case "set-text-effect-color":
_advTextStyle = _advTextStyle with { EffectColor = Read(a[0]) }; return pc + 1;
case "set-text-render-mode": case "set-text-render-mode":
_advTextStyle = _advTextStyle with { RenderMode = (int)Read(a[0]) }; return pc + 1;
case "set-text-effect-offset": case "set-text-effect-offset":
_advTextStyle = _advTextStyle with
{
EffectOffsetX = (int)Read(a[0]),
EffectOffsetY = (int)Read(a[1])
};
return pc + 1;
case "set-adv-text-layout-origin": // 0x198; slot 0 selects the current layout case "set-adv-text-layout-origin": // 0x198; slot 0 selects the current layout
case "u0041B540": case "u0041B540":
TextHistory.SetLayoutOrigin((int)Read(a[0]), (int)Read(a[1]), (int)Read(a[2])); return StepAdvText(label, ins, pc);
return pc + 1;
case "get-message-window-alpha": // 0x131: process-owned message:MesWinAlpha setting case "get-message-window-alpha": // 0x131: process-owned message:MesWinAlpha setting
case "u00415F70": case "u00415F70":
Write(a[0], _messageWindowAlphaSetting); return pc + 1; Write(a[0], _messageWindowAlphaSetting); return pc + 1;
@@ -2434,21 +2349,16 @@ public sealed partial class VirtualMachine
return pc + 1; return pc + 1;
case "get-message-glyph-delay": // 0x7f case "get-message-glyph-delay": // 0x7f
case "u00414C60": case "u00414C60":
Write(a[0], _messageGlyphDelayMilliseconds); return pc + 1;
case "set-message-glyph-delay": // 0x1b5 case "set-message-glyph-delay": // 0x1b5
case "u0041B5F0": case "u0041B5F0":
_messageGlyphDelayMilliseconds = System.Math.Max(0, (int)Read(a[0])); return StepAdvText(label, ins, pc);
_host.SetMessageGlyphDelayMilliseconds(_messageGlyphDelayMilliseconds);
return pc + 1;
case "u00415BF0": case "u00415BF0":
case "reset-message-skip-input": // 0x101 clears transient input/run bits, not op 0x88 state case "reset-message-skip-input": // 0x101 clears transient input/run bits, not op 0x88 state
return pc + 1; return pc + 1;
case "end-text-line": case "end-text-line":
TextHistory.EndLine((int)Read(a[0]), _advTextStyle); return pc + 1;
case "set-font": case "set-font":
_advTextStyle = _advTextStyle with { FontFace = ReadStr(a[0]) }; return pc + 1;
case "comment": case "display-furigana": case "dev_ukn": case "comment": case "display-furigana": case "dev_ukn":
return pc + 1; return StepAdvText(label, ins, pc);
case "create-texture": case "create-texture":
case "set-texture": case "set-texture":
case "u00422E80": // pre-reference compatibility case "u00422E80": // pre-reference compatibility
@@ -2459,32 +2369,9 @@ public sealed partial class VirtualMachine
return StepSurface(label, a, pc); return StepSurface(label, a, pc);
case "u0041F3A0": case "u0041F3A0":
case "register-numeric-glyph-style": // 0x13a: (style)(surface)(atlas x/y)(digit w/h) case "register-numeric-glyph-style": // 0x13a: (style)(surface)(atlas x/y)(digit w/h)
{
int styleIndex = unchecked((int)Read(a[0]));
if (!Gfx.RegisterNumericGlyphStyle(styleIndex, unchecked((int)Read(a[1])),
unchecked((int)Read(a[2])), unchecked((int)Read(a[3])),
unchecked((int)Read(a[4])), unchecked((int)Read(a[5]))))
{
HaltReason ??= $"numeric-glyph-style-index-out-of-range:{styleIndex}";
return HALT;
}
return pc + 1;
}
case "u00422460": case "u00422460":
case "draw-decimal-glyphs": // 0x23b: retained decimal glyph draw case "draw-decimal-glyphs": // 0x23b: retained decimal glyph draw
{ return StepAdvText(label, ins, pc);
int styleIndex = unchecked((int)Read(a[1]));
if (!Gfx.DrawDecimalGlyphs(Read(a[0]), styleIndex, unchecked((int)Read(a[2])),
unchecked((int)Read(a[3])), unchecked((int)Read(a[4])),
unchecked((int)Read(a[5])), unchecked((int)Read(a[6]))))
{
HaltReason ??= (uint)styleIndex >= 11
? $"numeric-glyph-style-index-out-of-range:{styleIndex}"
: $"numeric-glyph-style-unregistered:{styleIndex}";
return HALT;
}
return pc + 1;
}
case "get-texture-size": case "get-texture-size":
case "fill-surface-rect": case "fill-surface-rect":
case "u00420D50": case "u00420D50":
@@ -2569,22 +2456,9 @@ public sealed partial class VirtualMachine
case "gfx-set-scale-current": // 0x1fd (handle)(sx%)(sy%)(sz%) -> current scale matrix case "gfx-set-scale-current": // 0x1fd (handle)(sx%)(sy%)(sz%) -> current scale matrix
case "set-current-rotation-axis-angle": case "set-current-rotation-axis-angle":
return StepRetainedObject(label, a, pc); return StepRetainedObject(label, a, pc);
case "set-adv-wait-indicator-handle": // 0x212 (layout)(retained handle) case "set-adv-wait-indicator-handle":
{ case "set-adv-text-object-range":
int requestedSlot = (int)Read(a[0]); return StepAdvText(label, ins, pc);
TextHistory.SetWaitIndicatorObjectHandle(requestedSlot, Read(a[1]));
AdvTextLayoutSnapshot layout =
TextHistory.GetLayoutSnapshot(requestedSlot);
_host.BindAdvWaitIndicator(
TextHistory.GetPresentationBinding(layout.Slot),
layout);
return pc + 1;
}
case "set-adv-text-object-range": // 0x213 (layout)(first handle)(count)
{
TextHistory.SetTextObjectRange((int)Read(a[0]), Read(a[1]), Read(a[2]));
return pc + 1;
}
case "gfx-elem-erase": case "gfx-elem-erase":
return StepRetainedObject(label, a, pc); return StepRetainedObject(label, a, pc);
case "gfx-elem-release": // 0x1fa (surface slot) case "gfx-elem-release": // 0x1fa (surface slot)