• src/doors/syncscumm/test/

    From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 03:02:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/816a78bdbc0c9d5899115862
    Added Files:
    src/doors/syncscumm/test/test_sst_mouse.c
    Modified Files:
    src/doors/syncscumm/door/sst_io.c sst_io.h src/doors/syncscumm/test/unit_sst_io.sh
    Log Message:
    syncscumm: parse SGR mouse into a game-coordinate event queue

    Enable DEC 1003/1006/1016 mouse (via termgfx/mouse) alongside the other
    startup probes, parse the SGR reports and the DECRQM reply in
    csi_final(), and map each report -- pixel-granular under 1016, else the
    cell centre in real cell pixels -- onto the 320x200 game surface through
    the same fit+center rect the frame is drawn in (factored out of the
    present path so the two can't disagree). Reports land in a small input
    FIFO the backend drains next. Coordinate-mapping unit test added.

    Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 03:02:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/42f2aba29d711c8778ce34cf
    Added Files:
    src/doors/syncscumm/test/test_sst_input.c
    Modified Files:
    src/doors/syncscumm/door/sst_io.c sst_io.h src/doors/syncscumm/test/unit_sst_io.sh
    Log Message:
    syncscumm: decode keyboard into the input event queue

    Negotiate the kitty/evdev key modes through termgfx keymode and decode
    kitty CSI-u, SyncTERM evdev and legacy CSI/SS3 keys into neutral
    SST_KEY_* codes queued on the same FIFO Task 3/4's mouse decode uses.
    Ctrl-S (stats) and quit (q/Ctrl-C) stay door-level under every key
    mode; everything else -- including + / - -- is forwarded, so ScummVM's
    own menu and text fields see the keys. Drops the door + / - volume
    hotkey (the engine's GMM Options dialog carries the volume sliders),
    along with the now-dead volume-step machinery it was the only caller
    of.

    A legacy byte or a legacy (non-kitty) CSI/SS3 nav key queues a single
    key-down with no synthetic release -- unlike door_input.c's WWKeyboard
    bracket, ScummVM's discrete keydown/keyup stream has no Down()-poll to
    satisfy, so there is nothing for an auto-release to protect against.
    kitty and evdev report real press/release edges and use them as-is.

    Tested via a new sst_io_test_feed() seam (SST_TEST) that runs raw wire
    bytes through the same parser sst_io_pump() uses, covering printable
    bytes, the freed +, legacy arrow/F-key/Home/End/SS3 sequences, and the still-reserved Ctrl-S/quit. Full unit_sst_io.sh suite and boot_bass.sh
    still pass; a standalone -Wall -Wextra -Werror compile of sst_io.c is
    clean.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 03:02:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/5474fcd59c4d7d25ecdaaf38
    Added Files:
    src/doors/syncscumm/test/test_sst_input_evdev.c
    Modified Files:
    src/doors/syncscumm/door/sst_io.c src/doors/syncscumm/test/test_sst_input.c unit_sst_io.sh
    Log Message:
    syncscumm: gate the door-quit hotkey on Ctrl-Q, not bare q

    The kitty and evdev keyboard decode paths in sst_io.c reserved an
    unmodified 'q' as the door-quit hotkey. Those are exactly the paths
    that carry every keystroke on kitty terminals (Foot, kitty, WezTerm)
    and SyncTERM in evdev mode, so a bare 'q' never reached ScummVM at
    all -- it quit the door instead of landing in the Global Main Menu's
    save-name field, where names like "quicksave" need a literal 'q'.

    Gate quit on Ctrl-Q in both paths instead, mirroring how Ctrl-S
    (stats) is already gated and matching syncconquer/door/door_input.c's
    actual convention (quit is Ctrl-Q there too, never bare 'q'). Ctrl-C
    quit is untouched -- it was already correctly ctrl-gated in both
    paths. Bare 'q' now falls through and is queued as an ordinary key.
    The legacy P_NORMAL byte path's bare-'q' quit is unchanged; it is
    out of scope for this fix.

    Also corrected the in-code comment above the kitty block, which
    inaccurately claimed this mirrors door_input.c consuming "Ctrl+letter
    hotkeys across all three input modes" -- it now describes what the
    code actually reserves (Ctrl-Q/Ctrl-C quit, Ctrl-S stats) and that
    bare letters forward to the game.

    Added regression coverage to test/test_sst_input.c (kitty CSI-u path, negotiated via the same "CSI?u" reply csi_final() already parses) and
    a new test/test_sst_input_evdev.c (evdev physical-key path, its own
    process since termgfx's "evdev wins" guard blocks enabling evdev in
    a process that already negotiated kitty) -- both use the existing
    SST_TEST sst_io_test_feed() seam, no new scaffolding. Verified both
    fail against the pre-fix code and pass against the fix.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 03:02:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/cc6f2373ec6861bc5d8289c8
    Added Files:
    src/doors/syncscumm/test/test_sst_io_present_pending.c
    Modified Files:
    src/doors/syncscumm/door/sst_io.c sst_io.h syncscumm.cpp src/doors/syncscumm/test/unit_sst_io.sh
    Log Message:
    syncscumm: retry a present() frame a static screen stranded

    sst_io_present() can defer a frame at the DSR-ack pacing gate or the backpressure gate without sending it and without updating g_last.
    present() is edge-driven off ScummVM's own dirty flag, so on a static
    screen (the F5 Sky control panel once fully drawn, or the frame right
    after a speech-toggle X finishes erasing) nothing calls present()
    again to retry it -- the frame just sits there until an unrelated
    redraw (a mouse move) happens to trigger one, which is why both
    defects only clear once the mouse moves.

    Retain the deferred frame's idx/pal in new g_pending_idx/g_pending_pal
    buffers at the two defer gates (not the startup grace/canvas-hold
    gates, which already self-retry every boot-loop frame), and add
    sst_io_tick(): a no-op unless a frame is pending, otherwise it retries
    via the exact same sst_io_present() call and therefore the exact same pacing/backpressure gates, so it can never overrun the link. Wire it
    into pollEvent() so it runs every poll, static screen or not.

    Adds test/test_sst_io_present_pending.c (new SST_TEST seams sst_io_test_set_inflight()/sst_io_test_present_pending()) to test/unit_sst_io.sh, reproducing the strand and proving the retry
    delivers the frame with no further engine-side present() call.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 03:02:00 2026
    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
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 22:07:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/5133fcb733ace568b6fff5cf
    Added Files:
    src/doors/syncscumm/test/boot_queen.sh xtrn/syncqueen/.gitignore README.md getdata.js install-xtrn.ini scummvm.example.ini
    Log Message:
    syncscumm: add Flight of the Amazon Queen as a bundled title

    Flight of the Amazon Queen is officially freeware, and ScummVM hosts
    both English builds. This adds the xtrn/syncqueen package: an
    install-xtrn.ini describing the door (native, DOOR32.SYS, per-user
    saves), a getdata.js that fetches both the Talkie and Floppy builds over
    HTTPS and verifies each against ScummVM's published sha256 before
    unpacking, a reference scummvm.example.ini, and a README.

    It is the first title to use the audio-aware data selection: audio
    sessions hear the speech build, silent terminals read the floppy
    captions, chosen per session. A headless boot test exercises both
    variants.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 22:07:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/68fc3de4d89064c9e5eae21c
    Added Files:
    src/doors/syncscumm/test/boot_bass_pkg.sh xtrn/syncbass/.gitignore README.md getdata.js install-xtrn.ini scummvm.example.ini
    Log Message:
    syncscumm: re-home Beneath a Steel Sky into an xtrn/syncbass package

    Beneath a Steel Sky had only a development entry -- the door run straight
    from the build tree against a test-fixture game copy. This gives it a
    proper installable package alongside syncqueen: xtrn/syncbass, with an install-xtrn.ini (native door, DOOR32.SYS, per-user saves under data/user/<####>/syncbass/), a getdata.js that fetches the freeware CD
    build
    over HTTPS and verifies it against ScummVM's published sha256, a
    reference scummvm.example.ini, and a README.

    Unlike Flight of the Amazon Queen, which ships two genuinely distinct
    builds, BASS needs only one: the CD build renders both speech and
    on-screen subtitles from a single data set. So the package installs it
    flat in the package directory itself and the door, given no --path,
    defaults to that directory -- where sst_select_datadir finds no talkie/
    or floppy/ sub-dir and falls back to the single build for every session;
    audio then rides the subtitles-auto default -- speech to a terminal that
    can play it, subtitles to one that cannot. The CD build is
    self-contained: it carries sky.cpt, the sky engine's required data file,
    so no SYNCSCUMM_DATA search set is needed (only the freeware floppy
    build, which this package does not use, omits it).

    A headless package boot test (boot_bass_pkg.sh) verifies the
    self-contained in-band path boots clean without a SYNCSCUMM_DATA search
    set.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 18 23:14:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/122c363e7d5d2965b33ad49c
    Added Files:
    src/doors/syncscumm/test/boot_spacequest0.sh xtrn/spacequest0/.gitignore README.md getdata.js install-xtrn.ini scummvm.example.ini
    Modified Files:
    src/doors/syncscumm/deploy.js
    Log Message:
    syncscumm: add Space Quest 0 as a fetch-only AGI door package

    Space Quest 0: Replicated (Jeff Stewart, 2003) is a fan-made prequel to Sierra's Space Quest series, built on the AGI interpreter -- the first
    title for the AGI engine just added to the build. This adds an
    xtrn/spacequest0 package for it: install-xtrn.ini (native door,
    DOOR32.SYS, per-user saves under data/user/<####>/spacequest0/),
    getdata.js, a reference scummvm.example.ini, and a README.

    Unlike Beneath a Steel Sky and Flight of the Amazon Queen -- officially relicensed freeware -- this is a fan game that builds on Sierra's
    copyrighted and trademarked IP, with no redistribution grant of its own.
    So the package bundles NO game data: getdata.js downloads the ZIP from
    the author's own host (wiw.org), verifies a pinned sha256 + size, and
    unpacks only the AGI resource files (skipping the ZIP's bundled DOS
    interpreter -- unused by ScummVM, and its spaced .exe name trips the
    Archive object's safe-filename guard anyway). The game bytes never enter
    this repository; the author's site is the distributor, and a .gitignore whitelist keeps only the package's own source tracked. Installing it is
    the sysop's decision to serve a fan game on Sierra's IP -- declining
    getdata.js leaves the door registered but unplayable.

    deploy.js learns the new package (and a stale --path comment is fixed); boot_spacequest0.sh headless-boots it as game id sq0 -- the AGI-engine acceptance check (500 frames).

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 00:11:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/5c0e476e753d7327dc3b6c93
    Added Files:
    src/doors/syncscumm/test/boot_cascadequest.sh xtrn/cascadequest/.gitignore README.md getdata.js install-xtrn.ini scummvm.example.ini
    Modified Files:
    src/doors/syncscumm/deploy.js
    Log Message:
    syncscumm: add Cascade Quest as a fetch-only SCI door package

    Cascade Quest (Phil Fortier / "Troflip") is an original freeware
    adventure built on Sierra's SCI interpreter -- the first title for the
    SCI engine just added to the build, and the first to exercise it. This
    adds an xtrn/cascadequest package: install-xtrn.ini (native door,
    DOOR32.SYS, per-user saves under data/user/<####>/cascadequest/),
    getdata.js, a reference scummvm.example.ini, and a README.

    Unlike Space Quest 0, Cascade Quest is NOT built on a third party's IP --
    it's the author's own story and art, so its licensing is cleaner. It is
    still fetch-only, though: it carries no explicit redistribution grant and
    the author now sells a commercial reboot (Cascadia Quest), so the package bundles NO game data. getdata.js downloads the ZIP from the author-
    community host (sciprogramming.com), verifies a pinned sha256 + size, and unpacks only the SCI resource files (resource.map/001/cfg), skipping the
    ZIP's bundled DOS interpreter. The game bytes never enter this
    repository; a .gitignore whitelist tracks only the package's own source.

    ScummVM detects the resources as game id sci-fanmade and names the title Cascade Quest. The per-user save path has no /saves subdir -- the path is already unique per user and per game, so saves and scummvm.ini coexist in data/user/<####>/cascadequest/. deploy.js learns the new package; boot_cascadequest.sh headless-boots it (the SCI-engine acceptance check,
    500 frames).

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 05:16:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/007fd261d3eed481048e3b47
    Added Files:
    src/doors/syncscumm/test/boot_betrayedalliance.sh xtrn/betrayedalliance/.gitignore README.md getdata.js install-xtrn.ini scummvm.example.ini syncscumm.example.ini
    Modified Files:
    src/doors/syncscumm/deploy.js
    Log Message:
    syncscumm: add Betrayed Alliance Book 1 as an MIT-licensed SCI door

    Betrayed Alliance Book 1 (Ryan Slattery / Slattstudio) is an original
    EGA, parser-driven SCI adventure -- the second SCI title after Cascade
    Quest, and the cleanest provenance of the fetch-only games: it ships an explicit MIT LICENSE.TXT permitting redistribution outright (unlike Space
    Quest 0's Sierra IP or Cascade Quest's un-granted freeware). This adds an xtrn/betrayedalliance package: install-xtrn.ini, getdata.js, reference scummvm.example.ini + syncscumm.example.ini, and a README.

    Because it is MIT-licensed it could legally be bundled, but the package
    still fetches it -- lighter repo, always the pinned release, consistent
    with the other titles. getdata.js downloads the pinned release-v1.3.3.1 "-minimal" zip from the author's own GitHub release, verifies a pinned
    sha256 + size, and unpacks ONLY the SCI resources (resource.map/001, RESOURCE.CFG) plus the game's LICENSE.TXT -- kept with the data to honor
    the MIT notice clause. The release zip nests everything under a top-level folder and bundles a whole DOSBox package (DOSBox.exe, SCIV.EXE, drivers)
    for modern Windows; the extract recurses into the folder, flattens it,
    and matches only those files, so the DOSBox payload is never written.

    ScummVM detects the resources as game id sci-fanmade and names the title "Betrayed Alliance 1.3.3.1" -- the newest version its detection tables recognize (engines/sci/detection_tables.h), and the pinned zip's
    resource.map is a byte-exact match. Per-user saves land in data/user/<####>/betrayed/ (the dir is shortened from the full title so
    the cmd, with the sci-fanmade target, stays under the 100-char cap).
    deploy.js learns the package; boot_betrayedalliance.sh headless-boots it
    as a second SCI-engine acceptance check (500 frames).

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 05:16:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/dd147db90bfc47fe5a07aa3a
    Modified Files:
    src/doors/syncscumm/test/boot_bass.sh boot_bass_pkg.sh boot_cascadequest.sh boot_queen.sh boot_sixel.sh boot_spacequest0.sh subtitles.sh
    Log Message:
    syncscumm: point boot-test scripts at the renamed binary

    The binary rename (build/scummvm -> build/syncscumm) missed the test
    harness: the boot_*.sh acceptance scripts and subtitles.sh still
    referenced build/scummvm, so they failed to find the binary after a
    fresh build. Update all seven to build/syncscumm.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 05:16:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/8aad77a78300c24767c42792
    Added Files:
    src/doors/syncscumm/test/boot_drascula.sh xtrn/syncdrascula/.gitignore README.md drascula.dat getdata.js install-xtrn.ini scummvm.example.ini syncscumm.example.ini
    Modified Files:
    src/doors/syncscumm/deploy.js
    Log Message:
    syncscumm: add Drascula: The Vampire Strikes Back as a door

    Drascula is freeware -- its author released it for free redistribution
    and ScummVM hosts it -- so xtrn/syncdrascula/getdata.js fetches it: the
    game (drascula-1.0.zip -> Packet.001) and the optional CD soundtrack (drascula-audio-mp3-2.0.zip -> audio/track*.mp3), each verified against
    its published .sha256, from ScummVM's own download host. gameid
    "drascula", a flat single build like Beneath a Steel Sky.

    Unlike the other titles, the drascula engine needs ScummVM's own
    drascula.dat engine-data file, which is not part of the fetched game
    data; it ships committed in the package (the door finds it via --path).

    The CD music is loud relative to the dialogue, so the package ships
    "[audio] music_volume = 30". deploy.js gains the package; a detection-
    based boot_drascula.sh is the acceptance check -- Drascula's intro is audio/input-driven, so it does not free-run under the headless dump, and detecting the game id is the valid headless signal.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 05:16:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/b1564e2e2c5618e0281b1500
    Added Files:
    src/doors/syncscumm/test/boot_lure.sh xtrn/synclure/.gitignore README.md getdata.js install-xtrn.ini lure.dat scummvm.example.ini syncscumm.example.ini
    Modified Files:
    src/doors/syncscumm/deploy.js
    Log Message:
    syncscumm: add Lure of the Temptress as a door

    Lure of the Temptress is freeware -- Revolution Software released it for
    free redistribution and ScummVM hosts it -- so xtrn/synclure/getdata.js
    fetches lure-1.1.zip from ScummVM's own download host, verified against
    its published .sha256, and unpacks just the VGA disk resources
    (Disk1.vga .. Disk4.vga) plus the freeware LICENSE.txt, flattening the archive's lure/ subfolder. Taking VGA alone -- not the EGA build,
    Lure.exe or the PDFs the archive also carries -- makes ScummVM detect a
    single game id "lure" rather than a VGA/EGA pair.

    Like drascula, the lure engine needs ScummVM's own lure.dat engine-data
    file, which is not part of the fetched game data; it ships committed in
    the package (the door finds it via --path).

    Lure's music is the engine's internal Adlib synth, which the mixer emits quieter than the other titles' digital audio, so the package raises the
    door's [audio] volume to compensate. deploy.js gains the package;
    boot_lure.sh is a normal frame-based acceptance check (Lure's intro
    free-runs, unlike Drascula's).

    This completes the freeware curated engines -- sky, queen, agi, sci,
    drascula and lure each now have a title (the scumm engine's games are commercial, sysop-supplied).

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 18:26:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/5d0829a7e6b17d661df4396f
    Added Files:
    src/doors/syncscumm/test/test_termgfx_termio.c test_termgfx_termio_audio.c test_termgfx_termio_audio_backlog.c test_termgfx_termio_audio_ini_headroom.c test_termgfx_termio_audio_ini_off.c test_termgfx_termio_audio_ini_tune.c test_termgfx_termio_audio_static.c test_termgfx_termio_audio_tone.c test_termgfx_termio_audio_underrun.c test_termgfx_termio_bottom_dirty.c test_termgfx_termio_canvas.c test_termgfx_termio_datadir.c test_termgfx_termio_gfxmax.c test_termgfx_termio_input.c test_termgfx_termio_input_evdev.c test_termgfx_termio_mouse.c test_termgfx_termio_nogfx.c test_termgfx_termio_present_pending.c test_termgfx_termio_sixelmax_override.c test_termgfx_termio_xterm_ceiling.c unit_termgfx_termio.sh
    Removed Files:
    src/doors/syncscumm/test/test_sst_input.c test_sst_mouse.c
    Log Message:
    syncscumm: migrate sst_io unit tests to termgfx_termio

    The unit tests still compiled and linked against door/sst_io.c, which
    an earlier commit moved into the shared termgfx_termio.c. Rename the
    test sources/driver to match (test_sst_io*.c/test_sst_input*.c/ test_sst_mouse.c/test_sst_datadir.c -> test_termgfx_termio_*.c,
    unit_sst_io.sh -> unit_termgfx_termio.sh), repoint every cc line at termgfx/termgfx_termio.c, and rename sst_io_*/SST_KEY_*/SST_MOD_*/ SST_EV_*/sst_input_event_t references to their termgfx_termio_*/
    TERMGFX_* equivalents, matching what Task 3 actually named things (sst_select_datadir() and the SST_TEST gate kept their old names, so
    those stay).

    Several macros door/sst_io.h used to declare publicly (SST_FB_W/H, SST_AUDIO_RATE, SST_CHUNK_MS, SST_PREBUFFER_CHUNKS) are no longer
    visible from termgfx_termio.h: the framebuffer size moved to the
    public TERMGFX_TERMIO_FB_W/H, and the audio tuning constants became
    file-static inside termgfx_termio.c. Repointed the tests at the former
    and gave the audio tests their own local copies of the latter (same
    values) so they keep compiling without guessing a literal.

    Assertions and test logic are unchanged; all 20 test binaries build
    and pass via test/unit_termgfx_termio.sh, and test/unit_sst_quant.sh (sst_quant.c was not moved) still passes untouched.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 18:26:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/b341bad04abd60f198eae319
    Modified Files:
    src/doors/syncscumm/test/repro_fade.c
    Log Message:
    syncscumm: repoint the repro_fade tool onto termgfx_termio

    The termio extraction deleted door/sst_io.h; test/repro_fade.c (a headless fade-pacing measurement tool, not part of the unit suite) still included it
    and drove the old sst_io_* API, so it no longer compiled. Rename its calls
    to termgfx_termio_* and its SST_FB_W/H to TERMGFX_TERMIO_FB_W/H, matching the unit-test migration. Verified it compiles and links against libtermgfx.

    Caught by the final whole-branch review.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 23:59:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/91efc43b9738a886b8c00300
    Added Files:
    src/doors/syncscumm/test/test_termgfx_quant.c unit_termgfx_quant.sh src/doors/termgfx/termgfx_quant.c termgfx_quant.h
    Modified Files:
    src/doors/syncscumm/door/module.mk video_term.cpp src/doors/termgfx/CMakeLists.txt
    Removed Files:
    src/doors/syncscumm/test/unit_sst_quant.sh
    Log Message:
    termgfx: relocate syncscumm's quantizer as termgfx_quant

    Move the deterministic median-cut RGB888->256-color quantizer out of syncscumm's door/ (sst_quant.{c,h}) into the shared termgfx library as termgfx_quant.{c,h}, so the upcoming truecolor present path can reuse
    it from termgfx_termio.c's present_rgbx (Task 3).

    Pure move + rename: sst_quant_ -> termgfx_quant_, SST_QUANT_ ->
    TERMGFX_QUANT_, and the include guard to the conforming
    TERMGFX_QUANT_H_ (was the already-nonstandard
    SYNCSCUMM_SST_QUANT_H_). No algorithm/output change -- the quant unit
    test (relocated to test_termgfx_quant.c / unit_termgfx_quant.sh) still
    passes byte-for-byte.

    video_term.cpp now includes termgfx_quant.h and calls
    termgfx_quant_rgb(); module.mk drops sst_quant.o since the door now
    links it from libtermgfx.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sun Jul 19 23:59:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/ed96e305648879fab20f557c
    Added Files:
    src/doors/syncscumm/test/test_termgfx_present_rgbx.c unit_termgfx_present_rgbx.sh
    Log Message:
    syncscumm: unit-test the truecolor present_rgbx path

    Task 4 of the termgfx truecolor present plan: a headless test for termgfx_termio_present_rgbx(), the 32-bit XRGB present path Task 3
    added. Drives it via the existing SYNCSCUMM_SIXELOUT capture mode (no
    tty needed) with a 64x48 frame -- deliberately not 320x200, to
    exercise the w/h-parameterized geometry present_rgbx() takes -- and
    decodes the captured sixel's palette registers.

    Three assertions: a solid-color frame's register matches the source
    RGB on the sixel encoder's 0-100 scale (proving the R,G,B,X byte
    order and the quantize/encode path); a two-color frame yields both
    colors as distinct registers (proving the quantizer sees distinct
    colors); and re-running the solid frame with per-pixel garbage in the
    X byte produces byte-identical output to the X=255 run (proving the
    pad byte is dropped, not just untested).

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Wed Jul 22 16:22:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/6512285c1be7fcf8528fecb2
    Added Files:
    src/doors/syncscumm/test/test_sixel_palette_used.c
    Modified Files:
    src/doors/termgfx/README.md sixel.c sixel.h
    Log Message:
    termgfx sixel: add SIXEL_PAL_USED to emit only referenced registers

    Replace sixel_encode()'s boolean emit_palette with a tri-state: SIXEL_PAL_NONE/FULL (the legacy 0/1, byte-identical output) and a new SIXEL_PAL_USED that (re)defines only the color registers an image
    actually references, at their original index. Register-resetting
    terminals (xterm/foot/Windows Terminal) must carry a palette on every
    image, and all 256 is mostly wasted bytes; USED cuts a typical dirty
    box from ~3.8KB of palette to a few hundred bytes with no wrong-color
    risk, since every referenced index is in the emitted set by
    construction. Persistent terminals keep FULL/NONE so a palette-less
    box can still rely on a prior frame's registers.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net