Own every pixel each frame, and bring the cursor back as a blinking block
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 19s
akbasic CI Build / sanitizers (push) Failing after 13s
akbasic CI Build / coverage (push) Failing after 16s
akbasic CI Build / akgl_build (push) Failing after 18s
akbasic CI Build / mutation_test (push) Failing after 17s
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 19s
akbasic CI Build / sanitizers (push) Failing after 13s
akbasic CI Build / coverage (push) Failing after 16s
akbasic CI Build / akgl_build (push) Failing after 18s
akbasic CI Build / mutation_test (push) Failing after 17s
The blinking backspace was not the backspace. The sink skipped rows it believed were already clear, tracked in a drawn[] array, which assumes a frame inherits the frame before it. SDL_RenderPresent swaps buffers, so a frame inherits the one two back: a row erased once is clean in one buffer and dirty in the other, and presenting alternates between them. The first character of a backspaced wrap flickered forever. It reproduces on X11 and never under the dummy driver or a software renderer, which is why the suite stayed green through two rounds of fixing it. The sink now repaints every row it owns every frame -- a frame either owns every pixel it presents or inherits pixels it cannot reason about. Confirmed on real hardware with the reported input: the wrapped tail's row reads zero across five successive captures. The cursor returns as a blinking block, half a second per cycle, off SDL's clock. It sits in the cell after the text rather than under it, which is what made the underscore unreadable, and it wraps to the next row when a line exactly fills one -- where the next character actually lands. The new regression test paints stale pixels by hand, which is what a swapped-in buffer hands back, so the case is covered without real hardware. Every new assertion was checked by reverting the fix and watching it fail. Recorded honestly in TODO.md section 5: the same buffer swap means the graphics verbs were never reliable across frames either. A one-shot DRAW lands in one buffer and the next present shows the other. Making that work needs a persistent surface, which is its own commit. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,14 @@
|
||||
#include <akbasic/input.h>
|
||||
#include <akbasic/sink.h>
|
||||
|
||||
/**
|
||||
* @brief One full cursor blink in milliseconds, half on and half off.
|
||||
*
|
||||
* Half a second, which is about what a Commodore does and is slow enough to read
|
||||
* under.
|
||||
*/
|
||||
#define AKBASIC_SINK_CURSOR_BLINK_MS 500
|
||||
|
||||
/** @brief How many saved SSHAPE regions the graphics backend will hold at once. */
|
||||
#define AKBASIC_AKGL_MAX_SHAPES 16
|
||||
|
||||
@@ -113,12 +121,10 @@ typedef struct
|
||||
char text[64][256];
|
||||
|
||||
/**
|
||||
* Which rows carried glyphs when this sink last rendered. A row that has
|
||||
* emptied since -- scrolled away, cleared, or shortened -- still has to be
|
||||
* erased, and after it is erased there is no longer anything in the grid to
|
||||
* say it once had something in it.
|
||||
* Milliseconds for one full cursor blink, half on and half off. Zero holds
|
||||
* the cursor solid, which is what a test wanting a deterministic frame sets.
|
||||
*/
|
||||
bool drawn[64];
|
||||
uint64_t cursorperiodms;
|
||||
|
||||
/*
|
||||
* The line editor. Nothing here is live except while readline is running,
|
||||
|
||||
Reference in New Issue
Block a user