128 lines
4.6 KiB
C#
128 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Age.Engine.Hosting;
|
|
using Age.Engine.Model;
|
|
using Age.Engine.Sys4;
|
|
using Age.Engine.Vm;
|
|
using Xunit;
|
|
|
|
public class BattleFrontierOpsTests
|
|
{
|
|
private const int Immediate = 0, InlineString = 2, GlobalInt = 3, GlobalString = 5,
|
|
LocalString = 11;
|
|
|
|
private static OpcodeTable Table() => OpcodeTableJson.Load(Paths.OpcodesJson);
|
|
private static Operand I(long value) => new(Immediate, value);
|
|
private static Operand G(int address) => new(GlobalInt, address);
|
|
|
|
[Fact]
|
|
public void SurfaceRectCopy_ForwardsTheCompleteBlitRequest()
|
|
{
|
|
var table = Table();
|
|
var script = ScriptAssembler.Assemble(table, "SURFACE_COPY", new List<(int, Operand[])>
|
|
{
|
|
(0x207, new[] { I(72), I(67), I(12), I(15), I(3), I(4), I(30), I(33) }),
|
|
(0x2, Array.Empty<Operand>()),
|
|
}, Array.Empty<string>());
|
|
var host = new RecordingHost();
|
|
|
|
new VirtualMachine(script, table, host).Run();
|
|
|
|
Assert.Equal(new SurfaceRectCopy(72, 67, 12, 15, 3, 4, 30, 33),
|
|
Assert.Single(host.SurfaceCopies));
|
|
}
|
|
|
|
[Fact]
|
|
public void ScalarBattleHelpers_PreserveNativeSignedBehaviorAndStringAliasing()
|
|
{
|
|
var table = Table();
|
|
var script = ScriptAssembler.Assemble(table, "BATTLE_SCALARS", new List<(int, Operand[])>
|
|
{
|
|
(0x191, new[] { G(0x100), I(int.MinValue) }),
|
|
(0x193, new[] { new Operand(GlobalString, 0x500), new Operand(GlobalString, 0x500),
|
|
new Operand(InlineString, 0) }),
|
|
(0x1c8, new[] { new Operand(LocalString, 0), I(-42) }),
|
|
(0x55, new[] { new Operand(GlobalString, 0x501), new Operand(LocalString, 0) }),
|
|
(0x2, Array.Empty<Operand>()),
|
|
}, new[] { "/99" });
|
|
var vm = new VirtualMachine(script, table, new RecordingHost());
|
|
vm.GlobalStrings[0x500] = "17";
|
|
|
|
vm.Run();
|
|
|
|
Assert.Equal(int.MinValue, vm.Globals[0x100]);
|
|
Assert.Equal("17/99", vm.GlobalStrings[0x500]);
|
|
Assert.Equal("-42", vm.GlobalStrings[0x501]);
|
|
}
|
|
|
|
[Fact]
|
|
public void MonotonicAndFrameTimeOps_StoreNativeLowDwordSamples()
|
|
{
|
|
var table = Table();
|
|
var host = new SequencedClockHost(0x1_0000_0005, 100, 116);
|
|
var script = ScriptAssembler.Assemble(table, "BATTLE_CLOCK", new List<(int, Operand[])>
|
|
{
|
|
(0xd0, new[] { G(0x100) }),
|
|
(0x23c, Array.Empty<Operand>()),
|
|
(0x23c, Array.Empty<Operand>()),
|
|
(0x2, Array.Empty<Operand>()),
|
|
}, Array.Empty<string>());
|
|
var vm = new VirtualMachine(script, table, host);
|
|
|
|
vm.Run();
|
|
|
|
Assert.Equal(5, vm.Globals[0x100]);
|
|
Assert.Equal(100u, vm.Gfx.PreviousFrameTimeMilliseconds);
|
|
Assert.Equal(116u, vm.Gfx.CurrentFrameTimeMilliseconds);
|
|
}
|
|
|
|
[Fact]
|
|
public void MovieActivityAndAnimationServiceFlags_ControlBattlePollingAndReset()
|
|
{
|
|
var table = Table();
|
|
var host = new RecordingHost();
|
|
host.ActiveMovieSurfaces.Add(7);
|
|
var script = ScriptAssembler.Assemble(table, "BATTLE_CONTROL", new List<(int, Operand[])>
|
|
{
|
|
(0x23a, new[] { G(0x100), I(7) }),
|
|
(0x23a, new[] { G(0x101), I(8) }),
|
|
(0x238, new[] { I(400) }),
|
|
(0x24e, new[] { I(2) }),
|
|
(0x243, Array.Empty<Operand>()),
|
|
(0x2, Array.Empty<Operand>()),
|
|
}, Array.Empty<string>());
|
|
var vm = new VirtualMachine(script, table, host);
|
|
|
|
vm.Run();
|
|
|
|
Assert.Equal(1, vm.Globals[0x100]);
|
|
Assert.Equal(0, vm.Globals[0x101]);
|
|
Assert.Equal(400, vm.Gfx.AnimClockDurationTicks);
|
|
Assert.Equal(1, vm.Gfx.AnimClockGeneration);
|
|
Assert.Equal(2, vm.Gfx.AnimationServiceFlags);
|
|
}
|
|
|
|
[Fact]
|
|
public void DelayedCombatVoice_ForwardsAllSchedulingOperands()
|
|
{
|
|
var table = Table();
|
|
var host = new RecordingHost();
|
|
var script = ScriptAssembler.Assemble(table, "BATTLE_VOICE", new List<(int, Operand[])>
|
|
{
|
|
(0x2c0, new[] { I(123), I(0), I(275) }),
|
|
(0x2, Array.Empty<Operand>()),
|
|
}, Array.Empty<string>());
|
|
|
|
new VirtualMachine(script, table, host).Run();
|
|
|
|
Assert.Equal((123L, 0, 275L), Assert.Single(host.ScheduledVoiceRequests));
|
|
}
|
|
|
|
private sealed class SequencedClockHost : RecordingHost
|
|
{
|
|
private readonly Queue<long> _samples;
|
|
public SequencedClockHost(params long[] samples) => _samples = new Queue<long>(samples);
|
|
public override long InputClockMilliseconds => _samples.Dequeue();
|
|
}
|
|
}
|