• src/doors/syncdoom/syncdoom.c src/doors/syncduke/syncduke.h syncduke_i

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Sat Jul 11 18:22:41 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/842d355b5535e0369bcf846a
    Modified Files:
    src/doors/syncdoom/syncdoom.c src/doors/syncduke/syncduke.h syncduke_input.c syncduke_io.c
    Log Message:
    syncduke,syncdoom: reclaim the status-line row; fix DOOM keypad-plus

    Adopt SyncConquer's DECSSDT status-line hide in SyncDuke and SyncDOOM.
    On entry each door emits termgfx_term_status_off (DECSSDT Ps=0) before
    the canvas probe, so SyncTERM frees its 25th row and the game fills the
    full 80x25 / 640x400 canvas instead of the 640x384 it draws into while
    the status line is visible. The prefixed DECRQSS query's reply is
    captured (a rolling-window scan in the input pump) and restored on exit
    via termgfx_term_status_set, mirroring SyncConquer's door_term_restore.

    Also fix SyncDOOM's numeric-keypad '+': it emitted the character '+',
    but DOOM binds screen-size-up and automap zoom-in to KEY_EQUALS ('='),
    not '+'. keypad-'-' worked only because screen-size-down is KEY_MINUS
    ('-'), which the keypad character happens to match. Map keypad-'+' to
    '=' in both the evdev and kitty numpad tables so it resizes and zooms
    with the same parity keypad-'-' already had; the main '+'/'=' keys are untouched.

    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 Linux)@VERT to Git commit to main/sbbs/master on Sun Jul 12 05:11:38 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/b740154ce8b57a09f7c86f9a
    Modified Files:
    src/doors/syncdoom/syncdoom.c src/doors/syncduke/syncduke.h syncduke_input.c syncduke_io.c
    Log Message:
    syncdoom/syncduke: bottom-row status bar, tier detail, text-grid fix

    Move the live stats strip (Ctrl-S) from the top row to the terminal's
    bottom row in both doors. In the sixel tier that row is already reserved
    empty (recompute_geom fits the image into vh-cellh so a sixel never
    reaches the last text row -- the Windows-Terminal scroll guard), so a
    bottom strip is genuinely non-invasive there, and it clears Doom's
    top-row message line and Duke's top-row pickup/quote messages. In the
    text tier the strip's row is excluded from the cell-diff so the game
    never repaints under it. Toggling the overlay off now erases the bottom
    row explicitly, since the graphics tiers never repaint that reserved
    row.

    Restyle the strip as a full-width status bar, following SyncConquer's
    idiom: set the background attribute first, then erase-to-end-of-line, so
    the erase paints the whole row in the bar color (black-on-cyan) instead
    of leaving a black tail. This also drops the old right-justify plus
    narrowing bookkeeping -- the background-color erase handles a shorter
    readout's stale tail.

    SyncDOOM: name the active text sub-tier in the readout (half-block, blocks+shades, quadrant, sextant) instead of flattening every one to
    "text", matching SyncDuke; and add the per-frame image size and encode
    time (KB / enc ms) fields SyncDuke already shows, timed with xpdev's xp_timer().

    SyncDuke: fix the text tier drawing past the screen canvas. It sized the character grid as px_w/8 by px_h/16, hardcoding an 8x16 cell, which
    overcounts on any terminal whose real cell differs (e.g. Windows
    Terminal) and spills the render past the canvas. Use the measured grid
    (the cursor-probe's g_grid_cols/rows, via new syncduke_term_cols/rows accessors, with px-over-cell and 80/24 fallbacks) -- identical to
    SyncTERM's true 8px cells, correct elsewhere. This mirrors how SyncDOOM
    already sizes its text grid.

    ---
    þ Synchronet þ Vertrauen þ Home of Synchronet þ [vert/cvs/bbs].synchro.net
  • From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Tue Aug 4 23:44:37 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/20100f171c1ac34728d57557
    Modified Files:
    src/doors/syncdoom/syncdoom.c src/doors/syncduke/syncduke.h syncduke_input.c syncduke_io.c src/doors/syncmoo1/syncmoo1.h syncmoo1_input.c syncmoo1_io.c src/doors/syncretro/syncretro.h syncretro_input.c syncretro_io.c test_axis.c src/doors/termgfx/sixel.c sixel.h term.c term.h src/doors/termgfx/test/test_term_sdm.c
    Log Message:
    doors: measure the mode-80 sense rather than infer it, where a version can't

    b3caee6dd4 (2026-08-04) picks the DECSDM sequence that means
    sixel-at-cursor from the peer's CTerm revision. That only answers for
    CTerm. The VT340 manual documents mode 80 backwards, so a terminal built
    from those specs reads the two sequences the way CTerm <= 1.327 does and
    says nothing about itself in its DA1 reply -- and the doors were assuming
    ?80l for every such client.

    There is a way to tell without asking. A terminal drawing at the cursor
    leaves it at the bottom of the image; one anchoring at the screen origin
    leaves it untouched. That difference is visible over the wire where the
    mode's polarity is not. The technique is hackerb9's testdecsdm.sh (github.com/hackerb9/vt340test), pointed out by Deuce.

    termgfx_sixel_vscale_probe() already measured cursor advance across two slivers, to decide whether the terminal honours the raster pan -- and had
    to assume a mode to do it. It now runs that measurement TWICE, once under
    each sequence, and reports six cursor rows instead of three. The half that moved the cursor is the half that drew at it: that answers the polarity,
    and its own two advances still answer the pan question. One write, one
    round trip, no probe that any door did not already send.

    termgfx_term_sixel_at_cursor_probed() puts the measurement ahead of the revision. The two never both apply in practice -- a client that reports a revision is not probed -- so this is precedence for the code's sake rather
    than a contested case.

    SyncRetro had no such probe to extend, and gains one: emitted before the
    first frame, with a collector in its CSI 'R' path that claims the six
    reports ahead of the DSR pace-ack handler. Frames wait for the answer, so nothing is ever painted at the wrong anchor.

    The termgfx_termio doors (SyncSCUMM, SyncRPG) stay on the revision alone.
    The probe is itself a sixel, so its slivers necessarily precede the first frame, and that module's tests pin "the first DCS on the wire is the
    frame" across five raster parsers and an image count. Correct on every
    CTerm client and on every terminal reading DECSDM the modern way; wrong
    only on a non-CTerm one built from the manual, for which no named example
    is known. sixel.h records the reasoning.

    A door that tracks the sequence it last sent must record what the probe
    leaves behind (termgfx_sixel_probe_trailing_sdm), because the probe sets
    the mode behind that bookkeeping: believing the older value, a door skips
    the very re-assert the probe made necessary and spends the session in the
    wrong mode. That is intermittent, not deterministic -- it needs the probe
    to have run at all -- and cost a repeated-run test to see.

    Verified against a fake terminal that models each polarity rather than
    echoing canned replies: it tracks the mode in effect and advances its
    cursor only for sixels drawn at one, so the reports are computed from the behaviour under test. All four doors settle on the right sequence for both polarities, with no CTerm version on offer.

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

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