• xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_synciv

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/cb3e68711619be177d113e6a
    Added Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncretro: parse a cartridge's title, year and publisher from its name

    A ROM set names files "Title (Year) (Publisher).int", so the launcher
    needs no database to show a shelf. Titles carry their own parentheses
    -- "Adventure (AD&D - Cloudy Mountain)" -- so the year is the LAST
    four-digit group, not the first, and dump markers like "[!]" belong to
    neither the publisher nor the title.

    A name that does not fit the pattern keeps its whole self as the
    title. A wrong guess reads worse than no guess.

    ---
    þ 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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/8f872c3eea13c7cb9817d226
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncivision: handle stacked dump markers and year ranges in titles

    sv_parse_title() strips only one trailing "[...]" dump marker, so a
    name with two stacked markers (e.g. "[a1][!]") keeps the inner one
    and misses both parse regexes. It also expects a bare 4-digit year,
    so a range like "(1982-83)" doesn't match either.

    Measured against the real 235-name cartridge set, these two gaps
    account for all 4 titles that fell back to the whole filename. Strip
    markers repeatedly, and accept an optional "-NN"/"-NNNN" suffix on
    the year, taking the first year of a range. Fallback count on the
    real set drops from 4 to 0.

    ---
    þ 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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/28a76a9bbcdb834d88db856e
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncretro: discover cartridges in a dumped ROM set

    A sysop drops a ROM set in and it is not a curated folder: it carries
    XML and torrent litter, BIOS images that are unplayable as cartridges,
    and short aliases of the same bytes. So the launcher decides what is a
    game rather than trusting the directory.

    Whitelist the cartridge extensions, reject anything outside the
    Intellivision's 2 KB to 64 KB range, and reject the two BIOS images by
    CONTENT, so a re-dropped set cannot smuggle one back in under a
    cartridge's name. Dedupe by size plus a hash of the first 4 KB: over
    the install's SMB view a symlink is indistinguishable from a regular
    file, so readlink cannot help and only the bytes can. The more
    descriptive of two names wins.

    md5_calc() returns base64 unless asked for hex. Ask.

    A name carrying a double quote, a dollar, a backtick or a backslash is
    reported unsafe: the door command line wraps the path in quotes, and
    those are the only characters that escape them.

    ---
    þ 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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/eb57a904e8d59589281aaeef
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncretro: keep a play-activity log

    One JSON object per completed play, appended. No aggregate counts
    file: data_dir is an SMB mount a second host also writes, so a read-modify-write of a counts file is a lost-update race waiting to
    happen. Most Played and Your Last Game are derived by scanning, which
    at BBS scale is a few thousand lines.

    A torn or hand-edited line is skipped rather than fatal, and a play
    that cannot be logged returns false rather than throwing: losing the
    record is not worth failing a player's session over.

    No in-game scores. Nothing in the libretro ABI reports one, and
    reading Astrosmash's points means a per-ROM RAM-address table that
    works for this core alone.

    ---
    þ 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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/3da06552004331704a338949
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncretro: collapse dump-quality variants in ROM discovery

    A ROM set carries several dumps of the same game that differ only by
    a trailing marker the title parser strips -- "... [!].int" beside
    "... [a1].bin". Their bytes differ, so the content dedupe (size plus
    a hash of the first 4 KB) cannot merge them, and the picker showed
    two or three identical-looking lines per game, some of them known-
    inferior rips. 12 of the 221 cartridges in the reference set were
    affected.

    sv_dump_rank() ranks a name's best trailing marker: 0 verified [!],
    1 no marker, 2 alternate [a*] (or anything unrecognized), 3 overdump
    [o*], 4 bad dump [b*]. sv_collapse_variants() groups by title + year
    + publisher (publisher stays in the key so different ports, e.g. the
    Intv Corp and Atarisoft Pac-Man, are never merged) and keeps the
    best-ranked entry per group, tying on the lexicographically smallest
    name so the result never depends on directory() order. sv_discover()
    calls it after the content dedupe and before the final sort.

    This hides files that exist on disk -- it is a display-layer pick,
    not a delete. The sysop's escape hatches are unchanged: [roms]
    exclude= in syncretro.ini, or deleting the losing dump directly.

    Tests cover the rank table (including stacked markers, where the
    best marker present wins), the collapse itself, the Pac-Man-ports must-not-merge case, and a same-rank tie.

    ---
    þ 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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/694d7815119d36ed9bbbacff
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncivision: dedupe sv_discover() on the full-file hash, not 4 KB

    sv_discover()'s dedupe key was size + md5(first 4 KB). Against the
    real 221-cartridge set that collides across genuinely different
    cartridges of the same size -- "Pac-Man (1983) (Atarisoft).int" and
    "Pac-Man (1983) (Intv Corp).int" are two different ports that share
    their first 4 KB but diverge later in the file, so the dedupe was
    silently dropping one of two real games from the picker.

    sv_discover() already computes the full-file md5 for every size-gated candidate, to check it against SV_BIOS_MD5, so keying the dedupe on
    that same full hash costs nothing extra. Compute it once into `full`,
    use it for both the BIOS guard and the dedupe key, and drop the
    now-unused 4 KB head hash.

    Added a discovery-section test that builds two same-size files whose
    first 4096 bytes are identical but whose tails differ (named after the
    real Pac-Man case) and asserts both survive sv_discover(), plus an
    assertion that genuinely identical full-file bytes still collapse to
    one entry.

    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 Fri Jul 10 01:39:22 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/44e8f4b74654807c3ad4a759
    Modified Files:
    xtrn/syncivision/syncivision_lib.js xtrn/syncivision/tests/test_syncivision_lib.js
    Log Message:
    syncretro: lay the cartridge list out in columns

    Two hundred titles do not fit a screen, so follow xtrn_sec.js: read
    down each column, collapse to one column below eighty, and derive the
    column count from the terminal's width rather than hardcoding two, so
    a wide terminal gets three.

    A cartridge with no year in its name shows no year, rather than the
    year zero.

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