From 1854afaa733e28cec17b64b90b509760eb75740c Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 2 Aug 2026 11:18:23 -0500 Subject: [PATCH] plasma: hide the cursor before anything draws The firmware parks a cursor artifact wherever text last ended, and nothing ever turned it off - the native games did, once at startup (ESC G 0, L4PLASMA.CPP), which is why the cabinet never showed it. Seen on the bench as a stray block sitting in the Descent 3 nameplate. ShowGreetingAsync now sends cursor-hidden as its first act on every plasma open, before the clear and greeting, so every path that follows - greeting, feedback text, bitmap rows - draws on a cursorless panel. PlasmaDisplay gains the CursorAsync wrapper for the ESC G command the command builder already had. Co-Authored-By: Claude Opus 5 --- src/RioJoy.Core/Plasma/PlasmaDisplay.cs | 9 +++++++++ src/RioJoy.Tray/RioCoordinator.cs | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/src/RioJoy.Core/Plasma/PlasmaDisplay.cs b/src/RioJoy.Core/Plasma/PlasmaDisplay.cs index 3b5a3d8..aeea3e1 100644 --- a/src/RioJoy.Core/Plasma/PlasmaDisplay.cs +++ b/src/RioJoy.Core/Plasma/PlasmaDisplay.cs @@ -25,6 +25,15 @@ public sealed class PlasmaDisplay public Task ClearAsync(CancellationToken ct = default) => WriteLockedAsync(new[] { PlasmaCommands.Clear() }, ct); + /// + /// Set the cursor mode (ESC G n): 0 hidden, 1 steady, 3 flashing. + /// The native games send ESC G 0 once at startup + /// (L4PLASMA.CPP) — without it the firmware's cursor artifact sits + /// wherever text last ended. + /// + public Task CursorAsync(byte mode, CancellationToken ct = default) => + WriteLockedAsync(new[] { PlasmaCommands.Cursor(mode) }, ct); + public Task CursorHomeAsync(CancellationToken ct = default) => WriteLockedAsync(new[] { PlasmaCommands.CursorHome() }, ct); diff --git a/src/RioJoy.Tray/RioCoordinator.cs b/src/RioJoy.Tray/RioCoordinator.cs index 4aa13c1..ff56cdb 100644 --- a/src/RioJoy.Tray/RioCoordinator.cs +++ b/src/RioJoy.Tray/RioCoordinator.cs @@ -337,6 +337,11 @@ public sealed class RioCoordinator : IDisposable { try { + // Hide the cursor before anything draws, as the native games did + // once at startup (ESC G 0, L4PLASMA.CPP): the firmware otherwise + // leaves its cursor artifact wherever text last ended, which reads + // as a stray block parked in the nameplate. + await plasma.CursorAsync(0).ConfigureAwait(false); await plasma.ClearAsync().ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(greeting)) await plasma.PosTextAsync(greeting!).ConfigureAwait(false); // (0,0) = auto-center