using VPlasma.Core.Protocol; namespace VPlasma.Core.Device; /// /// Canned wire streams for the UI's Self test button: each page is a /// byte sequence exactly as a host would send it over COM2, fed through the /// same parser as live traffic — so the button doubles as an end-to-end /// exercise of the command set without a host attached. /// public static class PlasmaSelfTest { public const int PageCount = 3; /// The wire bytes for self-test page (0-based). public static byte[] BuildPage(int page) => page switch { 0 => BuildBanner(), 1 => BuildCharset(), 2 => BuildGraphics(), _ => throw new ArgumentOutOfRangeException(nameof(page)), }; private static void Esc(List b, byte cmd, params byte[] operands) { b.Add(PlasmaProtocol.Esc); b.Add(cmd); b.AddRange(operands); } private static void Text(List b, string s) { foreach (char c in s) b.Add((byte)c); } /// Big-font banner over small-font attribute samples. private static byte[] BuildBanner() { var b = new List(); Esc(b, PlasmaProtocol.CmdClearScreen); Esc(b, PlasmaProtocol.CmdCursorMode, 0x00); Esc(b, PlasmaProtocol.CmdFontSelect, 0x04); // 12×16 cells: 10 × 2 Text(b, " vPLASMA"); Esc(b, PlasmaProtocol.CmdFontSelect, 0x00); // 6×8 cells: 21 × 4 Esc(b, PlasmaProtocol.CmdHomeCursor); b.Add(PlasmaProtocol.LineFeed); b.Add(PlasmaProtocol.LineFeed); Text(b, "128x32 PLASMA DISPLAY"); // exactly one 21-cell row Esc(b, PlasmaProtocol.CmdAttributes, 1); Text(b, "HALF "); Esc(b, PlasmaProtocol.CmdAttributes, 2); Text(b, "UNDER "); Esc(b, PlasmaProtocol.CmdAttributes, 3); Text(b, "REV"); Esc(b, PlasmaProtocol.CmdAttributes, 4); Text(b, " FLASH"); Esc(b, PlasmaProtocol.CmdAttributes, PlasmaProtocol.OperandDefault); return b.ToArray(); } /// The printable set 0x20..0x6F — a full 21×4 grid, minus a cell. private static byte[] BuildCharset() { var b = new List(); Esc(b, PlasmaProtocol.CmdClearScreen); Esc(b, PlasmaProtocol.CmdCursorMode, 0x00); for (byte c = 0x20; c <= 0x6F; ++c) b.Add(c); return b.ToArray(); } /// The rest of the charset plus an ESC P pattern block. private static byte[] BuildGraphics() { var b = new List(); Esc(b, PlasmaProtocol.CmdClearScreen); Esc(b, PlasmaProtocol.CmdCursorMode, 0x00); for (byte c = 0x70; c <= 0x7E; ++c) b.Add(c); // A framed checkerboard sent the way the game sends everything: // full-width ESC P rows (screen 0, xbyte 0, 16 bytes, 1 row each). for (int y = 10; y < VPlasmaDevice.Height; ++y) { Esc(b, PlasmaProtocol.CmdGraphicsWrite, 0, (byte)y, 0, VPlasmaDevice.WidthBytes, 1); bool edge = y is 10 or VPlasmaDevice.Height - 1; for (int x = 0; x < VPlasmaDevice.WidthBytes; ++x) { byte fill = edge ? (byte)0xFF : (y & 2) == 0 ? (byte)0xAA : (byte)0x55; if (!edge) { if (x == 0) fill |= 0x80; // left frame edge if (x == VPlasmaDevice.WidthBytes - 1) fill |= 0x01; // right frame edge } b.Add(fill); } } return b.ToArray(); } }