https://gitlab.synchro.net/main/sbbs/-/commit/8a24b913810d0be8da1f9236
Added Files:
src/doors/syncscumm/test/test_sst_io_bottom_dirty.c
Modified Files:
src/doors/syncscumm/door/sst_io.c src/doors/syncscumm/test/unit_sst_io.sh
Log Message:
syncscumm: force a full frame when a dirty box can't cover its own
bottom rows
sst_dirty_sixel_present()'s per-box height snap rounds a box's height
up to a whole vstep (LCM(cell,6)), then, only at the frame bottom,
rounds back down to stay vstep-aligned. At the confirmed live geometry
(canvas 1200x600, cell 20x20 -> vstep=60, eh=580, ehc=576) a box whose
changed rows fall in [540,576) rounds down to rh=0 and was
continue-dropped entirely -- its changed pixels never reached the
wire. When another box in the same present() still sent fine, the
caller took the dirty-rect path instead of falling back to a full
frame, so the bottom strand was never repainted on an otherwise-static
scene. Live symptom on Windows Terminal sixel: a stale mouse-cursor
sprite left un-erased along the bottom of the image.
Reuse the function's existing "fall back to a full frame" return-0
signal: if the bottom clamp leaves a box's own changed rows
[ry+rh, ry2) uncovered, return 0 instead of shipping a box that
silently drops them. This subsumes the old rh<=0 drop case. A full
frame always encodes the whole ehc height with no partial band at the
bottom, so it cleanly erases the cursor on both WT and Foot.
Adds test_sst_io_bottom_dirty.c, reproducing the live geometry exactly
via real socket-driven terminal negotiation: RED against the unfixed
code (no full-frame raster header ever appears), GREEN after the fix,
plus a second assertion that a non-bottom-only change still takes the
cheap dirty-rect path (no bandwidth regression for the common case).
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net