• src/doors/termgfx/termgfx_termio.c termgfx_termio.h

    From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Sun Jul 19 23:59:32 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/4668dc2f1f2cd8a9f0b27a84
    Modified Files:
    src/doors/termgfx/termgfx_termio.c termgfx_termio.h
    Log Message:
    termgfx: add a truecolor (XRGB) present entry point to termgfx_termio

    Add termgfx_termio_present_rgbx(xrgb, w, h), a sibling of the existing
    indexed termgfx_termio_present() that takes a native-resolution 32-bit
    frame (memory byte order R,G,B,X; the 4th byte is ignored padding;
    stride w*4) instead of an 8-bit-indexed frame plus palette. It is the
    entry point the upcoming syncrpg door needs, where the source surface is truecolor with no fixed palette of its own.

    The new path mirrors present()'s tier / geometry / pacing flow but
    produces the encoder input from XRGB:

    - sixel tier: nearest-neighbor scale the XRGB frame to packed RGB888 at
    the fit ew x eh, quantize it with the shared termgfx_quant_rgb(), then
    sixel_encode() the resulting indices + palette -- the same encoder the
    indexed path uses.
    - JXL tier: scale to RGB888 and jxl_encode() it directly, skipping the
    indexed round-trip sst_emit_jxl() does.
    - no-graphics tier: nothing to draw, same as present().

    Supporting changes, all additive:

    - sst_scale_rgbx_to_rgb(): NN XRGB -> packed RGB888 scale helper, taking
    the source w/h as parameters (a truecolor source has no fixed
    SST_FB_W x SST_FB_H surface).
    - g_rgb_buf/g_rgb_cap: hoisted out of the WITH_JXL block so the sixel
    truecolor tier can reuse the shared RGB scratch in a no-libjxl build.
    - sst_image_rect_src(): the source-parameterized core of sst_image_rect,
    which becomes a thin SST_FB_W x SST_FB_H wrapper over it. Passing those
    two constants reproduces the wrapper's former behavior exactly (the
    source dims feed only the termgfx_geom_fit() call), so the indexed
    present()/mouse geometry is byte-identical.
    - sst_emit_jxl_rgb(): the tail of sst_emit_jxl() fed already-packed RGB.

    The indexed present() path is left byte-identical -- its dedupe /
    dirty-rect / retain machinery keys off the indexed g_last_fb surface and
    is deliberately not shared; the pacing / backpressure gates, which key
    off the tier-agnostic link state, are. A gated truecolor frame is dropped rather than retained (there is no rgbx tick()-retry buffer), since a
    truecolor source drives its own redraw cadence.

    Compile/link smoke check only: syncscumm links the new symbol into
    libtermgfx but does not call it yet (it stays on the indexed path). The functional unit test lands in the following task.

    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 Thu Jul 23 23:03:46 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/136378ac726525e7c07f188c
    Modified Files:
    src/doors/termgfx/termgfx_termio.c termgfx_termio.h
    Log Message:
    termgfx: stats field, idle-on-top, CSI-S F4, clear-on-resize, mouse opt-out

    Shared-layer changes, all additive APIs or internal fixes:

    - termgfx_termio_set_stats_extra(): an optional door-owned token appended
    to the Ctrl-S strip (syncrpg shows the game resolution). The strip is
    byte-for-byte unchanged for doors that never set it.

    - Draw the idle-disconnect countdown AFTER the frame image. It is split
    out of termgfx_stats_draw() into termgfx_idle_draw(), called past the
    image emit in both present paths and from the static-scene paints. The
    JXL tier reserves no bottom row, so a height-constrained (e.g. 320x240)
    game would otherwise hide the disconnect warning behind the picture.
    The debug stats bar stays before the image and is suppressed while the
    countdown owns the row.

    - Decode F4 from CSI-S. Kitty and legacy keep F1/F2/F4 on the P/Q/S
    finals, so F4 arrives as "CSI 1;<mods>S", which collided with the
    XTSMGRAPHICS reply and was silently dropped -- Foot's F4 did nothing.
    The reply's required '?' marker disambiguates them; with no marker,
    dispatch F4. F3's 'R' stays ambiguous with CPR and is left to CSI 13~
    or evdev.

    - Erase the display on an image-rect change in the truecolor present
    path. A frame that shrinks (a door cycling to a smaller resolution)
    otherwise leaves the taller previous frame's bottom rows on screen.
    One 2J per change, guarded, so there is no per-frame flicker.

    - termgfx_termio_set_mouse(0): a keyboard-only door opt-out. It sends the
    mouse DISABLE rather than enable, so motion tracking (mode 1003) no
    longer streams hover reports that reset the idle clock (motion counts
    as activity) for a door that never reads the mouse. Stray reports are
    dropped outright as a backstop.

    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)