• src/doors/syncmoo1/syncmoo1_io.c

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Sunday, July 12, 2026 05:11:38
    https://gitlab.synchro.net/main/sbbs/-/commit/4a11464eb46b2fb3fbf317c7
    Modified Files:
    src/doors/syncmoo1/syncmoo1_io.c
    Log Message:
    syncmoo1: clear on geometry change, and center with a fractional cell

    Two rendering bugs on a maximized Windows Terminal, both latent in the sibling doors too (only syncretro was fixed, via the shared termgfx_geom_center_ex).

    The black box. Nothing wiped the screen when the geometry changed. The door starts on the default 80x25/640x400 assumption; when the terminal's
    grid/canvas
    probe reply lands mid-intro it recomputes a different image position and size, but the previous frame's footprint -- and 1oom's pre-sixel "Loading Master of Orion" text -- were never cleared, so a stale black rectangle sat in the background behind the new frame. Emit ESC[2J when the drawn geometry differs from the last frame sent (guarded off the first frame, which term_enter
    already
    cleared). Same fix the sibling doors' tier-change path applies; here the trigger
    is the probe-driven geometry change.

    The off-center image. Centering used cw = canvas / grid_cols, an integer that truncates. On a window whose pixels-per-cell isn't an exact 8x16, the lost fraction of a cell put the image a cell or two off ("kind of centered"). Adopt termgfx_geom_center_ex with the true fractional cell so the column/row round correctly.

    Verified: the geometry-change ESC[2J now fires on the wire when a probe reply changes the grid, and the door renders correctly on a real WT sixel session (user-confirmed). ctest 4/4.

    ---
    þ 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 Tuesday, July 21, 2026 01:49:54
    https://gitlab.synchro.net/main/sbbs/-/commit/d6ab9c05fab10fa46155986f
    Modified Files:
    src/doors/syncmoo1/syncmoo1_io.c
    Log Message:
    syncmoo1: drain paced-frame acks before the sixel vscale probe

    On xterm (and any terminal that draws a sixel at its encoded size rather
    than honoring the raster pan), the picture intermittently rendered at
    half height and the in-game mouse cursor tracked at twice the vertical
    rate -- the game's idea of the pointer drifted from the hardware cursor.

    Both symptoms were one cause: a wrong vertical-scaling verdict. The probe paints two thin slivers (pan=1, then pan=2), each bracketed by a cursor- position report, and infers "scales" when the pan=2 sliver advanced the
    cursor further than the pan=1 one. The three reports must be the probe's
    own [home, after-pan1, after-pan2].

    But sm_io_vscale_probe() fires from present(), AFTER the first few frames
    have already gone out and been paced -- and each paced frame is acked by a cursor report of its own. When a frame's ack was still in flight as the
    probe armed, sm_input_vscale_collect() claimed that straggling pace-ack as
    the probe's `home`, shifting the window by one: the true [1,3,5] (equal
    two-row advances -- xterm ignores pan) was read as [1,1,3] and looked like
    it had scaled. The door then sent a half-height pan=2 encode to a terminal
    that draws at the encoded size, and sm_map_mouse() -- which assumes the
    image fills the full fitted height -- put the cursor at 2x the Y rate. The
    race made it intermittent: whether a leftover ack landed inside the three- report window depended on timing.

    Fix: quiesce the pace pipeline before arming. Wait for every outstanding present()-sent DSR to be acked (draining routes those reports to sm_io_pace_ack(), since the collector is not yet armed), so the probe's
    own three reports are the only cursor reports in flight once it arms. The synchronous probe that follows blocks further presents, so no new DSR can appear before the verdict. Bounded by the probe's existing grace; a silent terminal just proceeds to the safe full-size fallback.

    This restores the invariant the sibling doors already hold a different way
    -- SyncDOOM and SyncDuke run the probe before the first frame (SyncDuke
    holds frame one for it; SyncDOOM reads its own accumulator with nothing in flight), so a stray report is inert there. syncmoo1 paints early frames,
    so it drains instead. Verified on xterm -ti vt340: the probe now collects
    a clean [1,3,5], the verdict is "does not scale", and frames stay pan=1 at
    full height with the cursor aligned.

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