Fix ADV transition and nested input lifecycles

This commit is contained in:
gamer147
2026-07-29 18:16:09 -04:00
parent 09d765d89d
commit da7e0e25ce
13 changed files with 251 additions and 78 deletions

View File

@@ -6,6 +6,28 @@ using Xunit;
public class WaitForInputTests
{
private sealed class NestedWaitHost : RecordingHost
{
public VirtualMachine Vm = null!;
public bool SawDormantParentCallback;
public bool SawParentCallbackRestored;
public override void WaitForInput(int layoutSlot, System.Func<bool> serviceInputCallback)
{
Waits++;
SawDormantParentCallback =
Vm.RawInputCallbackScriptName == "PARENT"
&& !Vm.IsRawInputCallbackActive;
}
public override void Sleep(long duration)
{
SawParentCallbackRestored =
Vm.RawInputCallbackScriptName == "PARENT"
&& Vm.IsRawInputCallbackActive;
}
}
// wait-for-input (0x72) fires per page. Synthesize a two-page scene and assert it fires exactly
// twice — full handling, no dependency on a real scene's (stubbed) line count.
[Fact]
@@ -28,4 +50,35 @@ public class WaitForInputTests
Assert.Equal(new[] { "page one", "page two" }, vm.Emitted.Select(e => e.Text).ToArray());
Assert.Equal("exit", vm.HaltReason);
}
[Fact]
public void DormantParentRawInputCallbackDoesNotOwnNestedDialogueWait()
{
var t = OpcodeTableJson.Load(Paths.OpcodesJson);
var child = ScriptAssembler.Assemble(t, "CHILD", new List<(int, Operand[])>
{
(0x6e, new[] { new Operand(2, 0), new Operand(0, 0) }),
(0x72, new[] { new Operand(0, 0) }),
(0x2, System.Array.Empty<Operand>()),
}, new[] { "nested dialogue" });
var parent = ScriptAssembler.Assemble(t, "PARENT", new List<(int, Operand[])>
{
// FIELD-style timed mouse callback remains registered while call-script enters an ADV scene.
(0xcc, new[] { new Operand(0, 50), new Operand(0, 0xffff_ffff) }),
(0x3, new[] { new Operand(0, 5) }),
(0xc8, new[] { new Operand(0, 0) }),
(0x2, System.Array.Empty<Operand>()),
}, System.Array.Empty<string>());
var host = new NestedWaitHost();
var vm = new VirtualMachine(parent, t, host, provider: new MapProvider(new() { [5] = child }));
host.Vm = vm;
vm.Run();
Assert.True(host.SawDormantParentCallback);
Assert.True(host.SawParentCallbackRestored);
Assert.Equal(1, host.Waits);
Assert.False(vm.IsRawInputCallbackActive);
Assert.Equal("exit", vm.HaltReason);
}
}