namespace VPlasma.Core.Protocol; /// /// The cockpit plasma display's serial command set, as recovered from the /// Tesla 4.10 sources and tools: /// /// The display is a 128×32 dot-matrix plasma panel on COM2 at /// 9600 8N1, no flow control. The game side /// (CODE\RP\MUNGA_L4\L4PLASMA.CPP) renders everything into a local /// 1bpp buffer and streams changed rows with the ESC P graphics /// command, sending ESC G 0 once at startup to hide the cursor. The /// factory test tool (VWETEST\VGLTEST\PLASMA.EXE) additionally /// exercises a text mode: printable ASCII renders at a cursor, with escape /// commands for clear/home, cursor visibility, font select, and text /// attributes (intensity/underline/reverse/flash), plus BS/HT/LF/VT/CR /// cursor motion. /// /// Every multi-byte command begins with ESC (0x1B) followed by one /// command letter: /// /// /// ESC @ clear screen, reset text state /// ESC L home the cursor (0,0) /// ESC G n cursor mode: 00/FF hidden, 01 steady, 03 flashing /// ESC K n select font n (FF = default font 0) /// ESC H n text attributes: index 0..16 into the /// intensity/underline/reverse/flash combos the /// test tool enumerates; FF = defaults /// ESC P s y x w h data… graphics write: screen s (single-screen, ignored), /// top row y (0..31), left byte column x (0..15), /// w bytes per row, h rows, then w*h data bytes, /// MSB = leftmost pixel. The game always sends /// whole rows: x=0, w=16, h=1. /// /// /// Where the two sources disagree on ESC G (the game hides the /// cursor with 00, the test tool with FF) both operands are treated as /// hidden. /// public static class PlasmaProtocol { /// Wire bit rate — the game opens PCS_9600, PCS_N81. public const int BaudRate = 9600; public const byte Esc = 0x1B; // Single-byte cursor-motion controls (PLASMA.EXE's /b /c /l /t /v options). public const byte BackSpace = 0x08; public const byte HorizontalTab = 0x09; public const byte LineFeed = 0x0A; public const byte VerticalTab = 0x0B; public const byte CarriageReturn = 0x0D; // ESC command letters. public const byte CmdClearScreen = (byte)'@'; public const byte CmdCursorMode = (byte)'G'; public const byte CmdAttributes = (byte)'H'; public const byte CmdFontSelect = (byte)'K'; public const byte CmdHomeCursor = (byte)'L'; public const byte CmdGraphicsWrite = (byte)'P'; // Cursor positioning, confirmed from the firmware dump (FIRMWARE.md): the // cursor is a pixel position, ESC Q sets its row (Y, 0-31) and ESC R its // column (X, 0-127) — the exact range checks the firmware enforces. public const byte CmdSetRow = (byte)'Q'; public const byte CmdSetColumn = (byte)'R'; // Page select (the firmware's 10 double-buffered screens): ESC I picks the // draw page, ESC i the displayed page. vPLASMA models a single page, so // these are consumed (1 operand each) but not acted on — enough to replay // the built-in demo, which uses them heavily. public const byte CmdDrawPage = (byte)'I'; public const byte CmdDisplayPage = (byte)'i'; /// Operand meaning "restore the default" for ESC K / ESC H. public const byte OperandDefault = 0xFF; }