https://gitlab.synchro.net/main/sbbs/-/commit/465b69d75e64a110152f6b8b
Modified Files:
src/doors/syncscumm/door/sst_io.c src/doors/syncscumm/test/test_sst_io_present_pending.c
Log Message:
syncscumm: clear the present-pending flag past the dedupe early-return
cc6f2373ec added a retry for a present() frame a static screen
stranded: a gated call retains the frame (g_pending_idx/g_pending_pal, g_present_pending=1) and sst_io_tick() re-invokes sst_io_present()
with it once the gate clears. The clear (g_present_pending = 0) sat
AFTER the whole-frame dedupe early-return, so a retry whose retained
frame happened to equal g_last_fb took the dedupe return and never
reached the clear.
Repro: a gate defers frame A, retaining it; while still congested the
engine presents frame B that is byte-identical to g_last_fb (e.g. a
cursor blink-and-revert -- video_term.cpp's dirty check keys off the
engine's own dirty/cursor state, not what was actually sent); since
idx != g_pending_idx the retain overwrites g_pending_idx with B (==
g_last_fb); the gate clears and sst_io_tick() retries with
g_pending_idx, which now dedupes out. From then on sst_io_tick()
re-invokes sst_io_present() every poll forever on an idle static
screen: a 64000-byte memcmp per poll, plus a stats redraw + wire flush
every poll if the Ctrl-S bar is on.
Move the clear to fire for every call that gets past BOTH defer gates
(pacing and backpressure), before the g_need_st handling. Past both
gates the frame is no longer stranded -- it either goes out below or
turns out identical to what the terminal already shows (dedupe); in
both cases whatever was retained for it has been handled. A later
frame that defers again is re-retained by the gate code, unaffected by
clearing here.
Also factor the retain snippet (memcpy idx/pal into g_pending_*, set g_present_pending=1) that was duplicated verbatim at both gates into a
single sst_present_retain() helper, called at both call sites, so the
two copies can no longer drift out of hand-sync.
Adds a convergence regression to test_sst_io_present_pending.c: gate a
retry of the exact frame just sent (so the retained frame equals
g_last_fb), let sst_io_tick() retry it into the dedupe path, and
assert sst_io_test_present_pending() reads 0 afterward, plus that a
further tick is a true no-op. Verified RED against the pre-fix
sst_io.c (assertion failure) and GREEN with this change.
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)