Fix AE001H cyclic color blending

This commit is contained in:
gamer147
2026-07-11 22:21:10 -04:00
parent f195934324
commit b41ae36168
8 changed files with 140 additions and 36 deletions

View File

@@ -105,6 +105,25 @@ public class AnimChannelTests
Assert.Equal(GfxState.PackColor(0x80, 0xFF0000), o.ColorTarget);
}
[Fact]
public void Op0x232_NegativeRgbPreservesNativeDefaultStaticColor()
{
var t = T();
var scene = ScriptAssembler.Assemble(t, "AE001H_COLOR", new List<(int, Operand[])>
{
(0x55, new[]{G(1), I(0xcb8e)}), (0x55, new[]{G(2), I(1200)}),
(0x55, new[]{G(3), I(224)}), (0x55, new[]{G(4), I(1)}),
(0x51, new[]{G(4), I(0), G(4)}),
(0x232, new[]{G(1), G(2), G(3), G(4)}), Exit(),
}, System.Array.Empty<string>());
var vm = new VirtualMachine(scene, t, new RecordingHost());
vm.Run();
var o = vm.Gfx.TryGet(0xcb8e)!;
Assert.Equal(0xffffffff, o.Color);
Assert.Equal(0xe0ffffff, o.ColorTarget);
Assert.Equal(0, o.StaticColorMode);
}
[Fact]
public void Op0x239_SetsSpritesheetGridCell()
{

View File

@@ -45,17 +45,43 @@ public class AnimInterpolatorTests
}
[Fact]
public void ColorAnim_PingPongsTintStrength_ObjectStaysOpaque()
public void ColorAnim_Mode0Textured_UsesRgbModulationAndIgnoresAlpha()
{
var g = VisibleObj(0x100);
// base = no tint (strength 0); target = full-strength (alpha 0xff) red glow => strength pulses 0<->255
g.SetColorAnim(0x100, period: 1000, target: GfxState.PackColor(0xFF, 0xFF0000));
g.SetColorAnim(0x100, period: 1000, target: GfxState.PackColor(0x80, 0xFF0000));
g.SnapshotVisibleObjects(0); // seeds start=0
var baseFrame = g.SnapshotVisibleObjects(0).Single();
Assert.Equal(255, baseFrame.Alpha); // object opacity ALWAYS opaque (never the color alpha)
Assert.Equal(0, baseFrame.TintStrength); // t=0 -> no tint
var peak = g.SnapshotVisibleObjects(500).Single();
Assert.Equal(255, peak.Alpha); // still opaque
Assert.Equal(255, peak.TintStrength); // t=1 -> full tint strength (the glow peak)
Assert.Equal((255, 0xffffffL, 0, true),
(baseFrame.Alpha, baseFrame.Tint, baseFrame.TintStrength, baseFrame.MultiplyTint));
Assert.Equal((255, 0xff0000L, 0, true),
(peak.Alpha, peak.Tint, peak.TintStrength, peak.MultiplyTint));
}
[Fact]
public void ColorAnim_Mode1_UsesSampledAlphaAsOpacity()
{
var g = VisibleObj(0x100);
g.SetStaticObjectColorResolved(0x100, mode: 1, alpha: 255, rgb: 0xffffff);
g.SetColorAnim(0x100, period: 1000, target: GfxState.PackColor(0x80, 0xffffff));
g.SnapshotVisibleObjects(0);
var peak = g.SnapshotVisibleObjects(500).Single();
Assert.Equal(0x80, peak.Alpha);
Assert.Equal(0, peak.TintStrength);
Assert.True(peak.MultiplyTint);
}
[Fact]
public void Ae001hMode0AlphaCycle_IsVisuallyInert()
{
var g = VisibleObj(0x100);
g.SetColorAnimResolved(0x100, period: 1200, alpha: 224, rgb: -1);
var start = g.SnapshotVisibleObjects(1000).Single();
var peak = g.SnapshotVisibleObjects(1600).Single();
Assert.Equal(0xe0ffffff, g.TryGet(0x100)!.ColorTarget);
Assert.Equal((255, 0xffffffL, 0, true),
(start.Alpha, start.Tint, start.TintStrength, start.MultiplyTint));
Assert.Equal((start.Alpha, start.Tint, start.TintStrength, start.MultiplyTint),
(peak.Alpha, peak.Tint, peak.TintStrength, peak.MultiplyTint));
}
}