Implement native-backed SC0000 SFX lifecycle

This commit is contained in:
gamer147
2026-07-11 02:15:17 -04:00
parent 9c4b331008
commit 2232216832
16 changed files with 413 additions and 64 deletions

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using Age.Engine.Model;
using Age.Engine.Sys4;
using Age.Engine.Vm;
using Xunit;
public class SfxOpsTests
{
[Fact]
public void Sc0000SfxLifecycleAndBgmFadeReachHost()
{
var table = OpcodeTableJson.Load(Paths.OpcodesJson);
var script = ScriptAssembler.Assemble(table, "SFX",
new List<(int, Operand[])>
{
(0xb4, new[] { new Operand(0, 0x28), new Operand(0, 0) }),
(0xb5, new[] { new Operand(0, 0) }),
(0xb6, new[] { new Operand(0, 0) }),
(0xc2, new[] { new Operand(0, 25), new Operand(0, 3000) }),
(0xd9, Array.Empty<Operand>()),
(0x2, Array.Empty<Operand>()),
}, Array.Empty<string>());
var host = new RecordingHost();
var vm = new VirtualMachine(script, table, host);
vm.Run();
Assert.Equal("exit", vm.HaltReason);
Assert.Equal((0x28L, 0), Assert.Single(host.SfxLoads));
Assert.Equal(0, Assert.Single(host.SfxStarts));
Assert.Equal(0, Assert.Single(host.SfxReleases));
Assert.Equal((25, 3000L), Assert.Single(host.BgmFades));
}
}

View File

@@ -17,6 +17,10 @@ internal sealed class RecordingHost : IHost
public readonly List<(int Slot, int X, int Y)> TextCursors = new();
public readonly List<(int Surface, int X, int Y, string Text)> SurfaceStrings = new();
public readonly List<long> SleptDurations = new();
public readonly List<(long Resource, int Channel)> SfxLoads = new();
public readonly List<int> SfxStarts = new();
public readonly List<int> SfxReleases = new();
public readonly List<(int Target, long Duration)> BgmFades = new();
public void ShowText(int offset, string text) => Lines.Add((offset, text));
public void SetAdvTextCursor(int layoutSlot, int x, int y) => TextCursors.Add((layoutSlot, x, y));
public void DrawStringToSurface(int surfaceSlot, int x, int y, string text)
@@ -44,6 +48,10 @@ internal sealed class RecordingHost : IHost
public (int Width, int Height) GetTextureSize(int slot) => (0, 0);
public void PlayBgm(long id) { }
public void PlayVoice(long id) { }
public void LoadSoundEffect(long resourceId, int channel) => SfxLoads.Add((resourceId, channel));
public void StartSoundEffect(int channel) => SfxStarts.Add(channel);
public void ReleaseSoundEffect(int channel) => SfxReleases.Add(channel);
public void FadeBgm(int targetPercent, long durationMs) => BgmFades.Add((targetPercent, durationMs));
}
internal sealed class MapProvider : IScriptProvider