https://gitlab.synchro.net/main/sbbs/-/commit/43148eec46fb78eeb5132088
Modified Files:
src/doors/syncretro/syncretro_dirty.c syncretro_dirty.h syncretro_io.c test_dirty.c src/doors/termgfx/sixel.c sixel.h src/doors/termgfx/test/CMakeLists.txt test_sixel_palette_used.c
Log Message:
syncretro: patch across a palette change instead of repainting
A palette change forced the whole-frame path, because redefining a sixel
colour register recolours every pixel already on screen drawn with it, so
the parts that would NOT be repainted are exactly the parts that go
wrong. That is a heavy way to buy correctness: a Street Fighter II
transition repaints ~75KB where the movement provoking it is a fraction
of that, and the picture is corrected top-to-bottom, so the bottom third
-- some 40KB downstream -- is the last part to stop being wrong. It reads
as a flash across the lower part of the screen.
Which cells a redefined register spoils is computable, though. Pass the
set of registers whose colour moved to sr_dirty_find() as `stale`: a cell
of the previous frame drawn with one of them is dirty even though not one
of its pixels changed, and it comes back as a rectangle like any other
change. The palette gate then has nothing left to protect and is dropped.
That leaves the definitions themselves. A SyncTERM patch deliberately
carries no palette (its registers persist), and all 256 would dwarf a
small box, so the first patch of a frame whose palette moved carries
exactly the registers that moved -- sixel_encode_delta(). Terminals that
reset registers per image already had this right: their patches
self-describe with the used-colour subset, and a redefinition there
cannot reach pixels that are already drawn.
Measured over a 3600-frame attract loop at 80x25. Of the frames that
change palette, 45.7% (sf2) and 68.5% (tmnt) now patch; on those frames
the sixel drops to 40.4% and 41.8% of the whole-frame repaint they used
to cost -- 37KB to 15KB, 49KB to 21KB. Whole-run bytes fall to 96.3% and
91.3%, and to 99.6%/100% on games that barely touch their palette
(pacman, galaga), which is the expected shape: this only pays where the
palette moves.
Verified against a model of the client -- its persistent registers and
the index plane it holds, updated exactly as the door emits -- by
comparing the colour it would draw against the colour the frame calls
for, every pixel of every frame: zero wrong pixels across six games. sixel_encode() and sixel_encode_aspect() are byte-identical to before
over five geometries and all three palette modes, which is what the other
six termgfx doors depend on.
Also registers test_sixel_palette_used.c with CTest. It was in the tree
but in no build file, so nothing ran it; it compiles sixel.c alone, so
unlike its neighbours it needs no door build.
Co-Authored-By: Claude Opus 5 (1M context) <
noreply@anthropic.com>
--- SBBSecho 3.37-Linux
* Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)