Extract VM ADV text opcode handler
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
187
engine/Age.Engine/Vm/VirtualMachine.AdvText.cs
Normal file
187
engine/Age.Engine/Vm/VirtualMachine.AdvText.cs
Normal 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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user