PlasmaCommands.GraphicsWrite/GraphicsRow port the display firmware graphics command (ESC P s y x w h, MSB-left); PlasmaDisplay.RowAsync writes a locked whole-row update; the line protocol gains `plasma row <y> <hex32>`. The router plasma slot becomes a bounded FIFO queue: rows stream in order (a frame must not tear), texts still coalesce to the newest, clear flushes, cap 128 with counted drops. Docs updated; 442 tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
108 lines
4.0 KiB
C#
108 lines
4.0 KiB
C#
using RioJoy.Core.Plasma;
|
||
using Xunit;
|
||
|
||
namespace RioJoy.Core.Tests.Plasma;
|
||
|
||
public class PlasmaCommandsTests
|
||
{
|
||
[Fact]
|
||
public void EscSequences_AreCorrect()
|
||
{
|
||
Assert.Equal(new byte[] { 27, (byte)'@' }, PlasmaCommands.Clear());
|
||
Assert.Equal(new byte[] { 27, (byte)'L' }, PlasmaCommands.CursorHome());
|
||
Assert.Equal(new byte[] { 27, (byte)'R', 10 }, PlasmaCommands.CursorX(10));
|
||
Assert.Equal(new byte[] { 27, (byte)'Q', 20 }, PlasmaCommands.CursorY(20));
|
||
Assert.Equal(new byte[] { 27, (byte)'H', 3 }, PlasmaCommands.FontAttr(3));
|
||
Assert.Equal(new byte[] { 27, (byte)'K', 5 }, PlasmaCommands.Font(5));
|
||
}
|
||
|
||
[Fact]
|
||
public void Box_DrawAndFill_HaveExpectedLayout()
|
||
{
|
||
Assert.Equal(new byte[] { 27, (byte)'X', 1, 2, 3, 4 }, PlasmaCommands.BoxDraw(1, 2, 3, 4));
|
||
// Fill inserts a leading 0 parameter.
|
||
Assert.Equal(new byte[] { 27, (byte)'x', 0, 1, 2, 3, 4 }, PlasmaCommands.BoxFill(1, 2, 3, 4));
|
||
}
|
||
|
||
[Fact]
|
||
public void Text_EncodesOneBytePerChar()
|
||
{
|
||
Assert.Equal(new byte[] { (byte)'A', (byte)'B', (byte)'C' }, PlasmaCommands.Text("ABC"));
|
||
}
|
||
|
||
[Fact]
|
||
public void GraphicsWrite_LaysOutHeaderThenData()
|
||
{
|
||
// ESC P s y x w h data… (s=0, single-screen hardware).
|
||
byte[] cmd = PlasmaCommands.GraphicsWrite(5, 2, 2, 2, new byte[] { 0xAA, 0xBB, 0xCC, 0xDD });
|
||
Assert.Equal(new byte[] { 27, (byte)'P', 0, 5, 2, 2, 2, 0xAA, 0xBB, 0xCC, 0xDD }, cmd);
|
||
}
|
||
|
||
[Fact]
|
||
public void GraphicsRow_IsAWholeRowWrite()
|
||
{
|
||
// The native game's shape: x=0, w=16, h=1 — one full 128-px row.
|
||
var row = new byte[16];
|
||
row[0] = 0x80; // leftmost pixel (MSB-first)
|
||
byte[] cmd = PlasmaCommands.GraphicsRow(31, row);
|
||
byte[] expected = new byte[] { 27, (byte)'P', 0, 31, 0, 16, 1 }.Concat(row).ToArray();
|
||
Assert.Equal(expected, cmd);
|
||
}
|
||
|
||
[Fact]
|
||
public void GraphicsWrite_RejectsOutOfPanelSpans()
|
||
{
|
||
Assert.Throws<ArgumentOutOfRangeException>(() => PlasmaCommands.GraphicsRow(32, new byte[16]));
|
||
Assert.Throws<ArgumentOutOfRangeException>(
|
||
() => PlasmaCommands.GraphicsWrite(0, 15, 2, 1, new byte[2])); // spills past byte column 15
|
||
Assert.Throws<ArgumentOutOfRangeException>(
|
||
() => PlasmaCommands.GraphicsWrite(31, 0, 16, 2, new byte[32])); // spills past row 31
|
||
Assert.Throws<ArgumentException>(
|
||
() => PlasmaCommands.GraphicsWrite(0, 0, 16, 1, new byte[15])); // data length mismatch
|
||
}
|
||
|
||
[Theory]
|
||
[InlineData(0, 5, 7)]
|
||
[InlineData(3, 5, 7)]
|
||
[InlineData(4, 10, 14)]
|
||
[InlineData(5, 10, 14)]
|
||
[InlineData(7, 5, 7)]
|
||
public void GetFontSize_MatchesLegacy(int font, int w, int h)
|
||
{
|
||
Assert.Equal(new FontSize(w, h), PlasmaCommands.GetFontSize(font));
|
||
}
|
||
|
||
[Fact]
|
||
public void ResolvePosText_ShortText_PicksFont5_AndCenters()
|
||
{
|
||
// "HELLO" (5) is non-score and ≤9 → font 5 (10×14). Centered around (56,15).
|
||
(byte x, byte y, byte font, int len) = PlasmaCommands.ResolvePosText("HELLO", 0, 0, 0);
|
||
Assert.Equal(5, font);
|
||
Assert.Equal(5, len);
|
||
Assert.Equal(31, x); // 56 - (5*10/2)
|
||
Assert.Equal(8, y); // 15 - (14/2)
|
||
}
|
||
|
||
[Fact]
|
||
public void ResolvePosText_LongText_Font2_AndCapsLength()
|
||
{
|
||
string text = new string('1', 24);
|
||
(byte x, byte y, byte font, int len) = PlasmaCommands.ResolvePosText(text, 0, 0, 0);
|
||
Assert.Equal(2, font);
|
||
Assert.Equal(20, len); // capped
|
||
Assert.Equal(6, x); // 56 - (20*5/2)
|
||
Assert.Equal(12, y); // 15 - (7/2)
|
||
}
|
||
|
||
[Fact]
|
||
public void ResolvePosText_ScoreFont_AndExplicitPosition_Unchanged()
|
||
{
|
||
// font 2 (score) keeps its font; non-zero position is not re-centered.
|
||
(byte x, byte y, byte font, int len) = PlasmaCommands.ResolvePosText("AB", 5, 6, 2);
|
||
Assert.Equal(2, font);
|
||
Assert.Equal(2, len);
|
||
Assert.Equal(5, x);
|
||
Assert.Equal(6, y);
|
||
}
|
||
}
|