- Connection: drop the hardwired COM12; replicate vRIO's endpoint picker — a combo of pipe:vplasma (the DOSBox-X namedpipe backend) + the COM ports, with Rescan and Open/Close. Nothing opens automatically; baud straps drive a COM open. - Demo (jumper 6) now runs the REAL firmware demonstration, not the vPLASMA self-test. The 10 demo screens are extracted verbatim from the ROM demo pointer table ($8000) into PlasmaFirmwareDemo.cs and looped through the parser. Added ESC I / ESC i (draw/display page select) as 1-operand commands — consumed but not acted on in the single-page model — so the demo's page commands don't desync the stream. - Orientation (jumper 4 / PD5) polarity fixed: unstrapped = horizontal 128x32 (the normal cockpit setup, now the default), installed = vertical. Verified: 29 unit tests pass (2 new: demo replay, page-select operand); the real demo screens render with the correct text/positioning/fonts, and the picker lists pipe:vplasma + COM ports with no auto-open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
76 lines
3.5 KiB
C#
76 lines
3.5 KiB
C#
namespace VPlasma.Core.Protocol;
|
||
|
||
/// <summary>
|
||
/// The cockpit plasma display's serial command set, as recovered from the
|
||
/// Tesla 4.10 sources and tools:
|
||
///
|
||
/// <para>The display is a 128×32 dot-matrix plasma panel on COM2 at
|
||
/// <b>9600 8N1</b>, no flow control. The game side
|
||
/// (<c>CODE\RP\MUNGA_L4\L4PLASMA.CPP</c>) renders everything into a local
|
||
/// 1bpp buffer and streams changed rows with the <c>ESC P</c> graphics
|
||
/// command, sending <c>ESC G 0</c> once at startup to hide the cursor. The
|
||
/// factory test tool (<c>VWETEST\VGLTEST\PLASMA.EXE</c>) 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.</para>
|
||
///
|
||
/// <para>Every multi-byte command begins with ESC (0x1B) followed by one
|
||
/// command letter:</para>
|
||
///
|
||
/// <code>
|
||
/// 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.
|
||
/// </code>
|
||
///
|
||
/// <para>Where the two sources disagree on <c>ESC G</c> (the game hides the
|
||
/// cursor with 00, the test tool with FF) both operands are treated as
|
||
/// hidden.</para>
|
||
/// </summary>
|
||
public static class PlasmaProtocol
|
||
{
|
||
/// <summary>Wire bit rate — the game opens PCS_9600, PCS_N81.</summary>
|
||
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';
|
||
|
||
/// <summary>Operand meaning "restore the default" for ESC K / ESC H.</summary>
|
||
public const byte OperandDefault = 0xFF;
|
||
}
|