• src/doors/syncretro/syncretro_dirty.c syncretro_dirty.h syncretro_io.c

    From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Wed Jul 22 20:38:40 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/e28eea3ed4aec6d6bf0e38ba
    Modified Files:
    src/doors/syncretro/syncretro_dirty.c syncretro_dirty.h syncretro_io.c test_dirty.c
    Log Message:
    syncretro: band-align dirty rects for cell-anchored terminals

    Add a band_align option to sr_dirty_find(): snap each rect height to LCM(cell_h, 6) -- a whole number of both text cells and 6px sixel bands
    -- and fall back to a full frame if a bottom-clamped rect can't cover
    its own changed rows. This is the discipline termgfx's SCUMM dirty path
    already carries to keep foot from backfilling a partial trailing band as
    a black strip. Passed 0 for now (SyncTERM path unchanged, byte-for-byte)
    so the correctness machinery lands before the non-SyncTERM gate opens.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Sat Jul 25 23:10:02 2026
    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)