https://gitlab.synchro.net/main/sbbs/-/commit/e2a4cacb378a4313c37f70d6
Modified Files:
src/doors/syncretro/syncretro_io.c test_dirty.c
Log Message:
syncretro: size every patch in whole sixel bands, not just whole cells
A dirty-rect patch was sized in whole text cells, which is what the cursor address in front of it needs. It is not what the decoder behind it needs.
A sixel is read six pixel rows at a time, and SyncTERM's 8x16 cell makes patches 16, 32 and 80 rows tall -- none of them a whole number of bands,
so every patch ended in a partial one.
cterm did not clear its band mask between bands until d65cb83886
(2026-06-28). Below that, any column of a partial final band not covered
by the band's first colour keeps the PREVIOUS band's pixels, and the band
is blitted full height regardless. Each patch therefore left a stale
sliver at its foot, which a sprite moving across the screen smears into a dotted trail behind it. SourceForge #258; reported against SyncArcade as
GitLab #1214 once b3caee6dd4 (2026-08-04) made patches land where they
were addressed and the trail became visible.
Only SyncTERM was exposed. Every other terminal already took the
band_align path, which snaps a rect to LCM(cell, 6) and so has always
emitted whole bands; SyncTERM was passed band_align=0 on the reasoning
that a cell-anchored patch is enough. Cell alignment is not band
alignment, and 16 is not a multiple of 6.
So band_align now applies to every sixel client. The height rounding in
the geometry routine moves with it: it kept the image an exact multiple of
the cell height precisely so band_align's hcell clamp could never strand a sub-cell remainder, and it was gated on the same condition. Splitting the
two would trade a stale sliver under each patch for a stale strip along
the bottom of the frame.
Measured over a 14-second capture against a 1.327 peer: 51 of 53 sixels
had a partial final band before, none after; patch heights go 16/32/80 -> 48/96, and the wire grows 26559 -> 27267 bytes, 2.7%. The added rows are unchanged background and cost almost nothing once run-length encoded.
test_dirty pins the property the terminals actually depend on -- a rect
height divisible by six -- across cell heights 16, 8, 13, 7, 6 and 5,
rather than the LCM of one particular cell.
Reported by Keyop.
Co-Authored-By: Claude Opus 5 (1M context) <
noreply@anthropic.com>
---
þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net