Correct ADV History metadata ordering

This commit is contained in:
gamer147
2026-07-19 20:55:16 -04:00
parent 8f94ef86ac
commit 3fa09b8b42
7 changed files with 107 additions and 11 deletions

View File

@@ -18,7 +18,7 @@ public class AdvTextHistoryTests
(0x75, new[] { I(24) }),
(0x76, new[] { I(0xf0e0d0) }),
(0x7a, new[] { I(0), I(12), I(34) }),
(0x1d2, new[] { I(123), I(1) }),
(0x1d2, new[] { I(1), I(123) }),
(0xc4, new[] { I(77) }),
(0x6e, new[] { I(0), S(0) }),
(0x71, new[] { I(1) }),
@@ -76,7 +76,7 @@ public class AdvTextHistoryTests
{
(0x1bb, new[] { I(0) }),
(0x70, new[] { I(2), I(500), I(100), I(10), I(20) }),
(0x1d2, new[] { I(9), I(2) }),
(0x1d2, new[] { I(2), I(9) }),
(0xc4, new[] { I(88) }),
(0x6e, new[] { I(0), S(0) }),
(0x1bb, new[] { I(1) }),

View File

@@ -13,6 +13,7 @@ public class HistoryInteractionOpsTests
private static Operand P(int address) => new(T_LPTR, address);
private sealed class StopAfterHistoryReturnsException : Exception { }
private sealed class StopAfterHistoryVoiceException : Exception { }
private static void SeedSystem4AdvLayouts(Sys4ScriptProvider scripts, AdvTextHistory history)
=> Assert.Equal(9, AdvTextLayoutBootstrap.ApplyLeadingDefinitionsAndResets(
@@ -65,6 +66,55 @@ public class HistoryInteractionOpsTests
}
}
private sealed class Sc0000HistoryVoiceHost : RecordingHost
{
public VirtualMachine Vm = null!;
private long _now;
private int _modalSleeps;
private bool _pressedVoiceRow;
public AdvTextHistoryRenderBatch? ClickedBatch;
public override long InputClockMilliseconds => _now;
public override void Sleep(long duration)
{
base.Sleep(duration);
_now += System.Math.Max(16, duration);
if (!Vm.IsRawInputCallbackActive) return;
_modalSleeps++;
if (!_pressedVoiceRow)
{
ClickedBatch = HistoryRenders.LastOrDefault(batch => batch.Layout.OriginY < 600
&& Vm.TextHistory.TryFindVoicePair(batch.FirstRecordIndex, out _, out _));
if (ClickedBatch == null) return;
_pressedVoiceRow = true;
Vm.UpdatePointer(200, ClickedBatch.Layout.OriginY + 50);
Vm.UpdateMouseButtonState(0x1, true);
Vm.QueueInputCallback(4);
return;
}
if (_modalSleeps == 3)
{
Vm.UpdateMouseButtonState(0x1, false);
Vm.QueueInputCallback(10);
}
if (VoiceRequests.Count > 0) throw new StopAfterHistoryVoiceException();
}
public override void WaitForInput(int layoutSlot, Func<bool> serviceInputCallback)
{
Waits++;
bool hasRecentVoice = Vm.TextHistory.Entries.TakeLast(5)
.Any(entry => Vm.TextHistory.TryFindVoicePair(entry.FirstRecordIndex, out _, out _));
if (!hasRecentVoice) return;
Voices.Clear();
VoiceRequests.Clear();
Vm.UpdatePointer(684, 572);
while (serviceInputCallback()) { }
Assert.True(Vm.TryActivatePointer(684, 572));
while (serviceInputCallback()) { }
}
}
[Fact]
public void RealHistoryRendersMultipleRowsAfterSeveralSc0000Messages()
{
@@ -189,4 +239,29 @@ public class HistoryInteractionOpsTests
Assert.NotEmpty(visibleRows);
Assert.All(visibleRows, render => Assert.Equal(65, render.Layout.OriginX));
}
[Fact]
public void RealHistoryVoicedRowDispatchesItsRetainedVoicePair()
{
var scripts = Sys4ScriptProvider.Load(Table);
var host = new Sc0000HistoryVoiceHost();
var vm = new VirtualMachine(scripts.RequireByName("SC0000.BIN"), Table, host,
new VmOptions(MaxSteps: 2_000_000), scripts);
host.Vm = vm;
SeedSystem4AdvLayouts(scripts, vm.TextHistory);
vm.Globals[0x6c1] = 1;
Assert.Throws<StopAfterHistoryVoiceException>(() => vm.Run());
var batch = Assert.IsType<AdvTextHistoryRenderBatch>(host.ClickedBatch);
Assert.True(vm.TextHistory.TryFindVoicePair(batch.FirstRecordIndex,
out long expectedVoice, out long expectedVariant));
Assert.Equal((0x24L, 0L), (expectedVoice, expectedVariant));
Assert.Equal(new[] { (expectedVoice, checked((int)expectedVariant)) }, host.VoiceRequests);
var resources = ResourceMap.Load();
var voice = Assert.IsType<AssetEntry>(resources.Resolve("SC0000", expectedVoice));
Assert.Equal("MAN999.OGG", voice.Name);
Assert.NotEmpty(resources.ReadAudio(voice).Bytes);
}
}

View File

@@ -779,8 +779,8 @@ public sealed class VirtualMachine
if (enabled) _host.EndTextHistoryPresentation();
}
return pc + 1;
case "append-text-history-metadata": // 0x1d2: typed value attached to the current group
TextHistory.AppendMetadata(Read(a[0]), Read(a[1]), _advTextStyle); return pc + 1;
case "append-text-history-metadata": // 0x1d2: (metadata type, value)
TextHistory.AppendMetadata(Read(a[1]), Read(a[0]), _advTextStyle); return pc + 1;
case "step-text-history": // 0x1d0: cumulative delta from the latest retained boundary
if (TextHistory.TryStepGroup((int)Read(a[2]), out var historyEntry))
{