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