• exec/load/syncretro_getco

    From Rob Swindell (on Debian L@VERT to Git commit to main/sbbs/m on Sat Jul 11 04:50:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/81a28642a529ebb45554b394
    Added Files:
    exec/load/syncretro_getcore.js syncretro_lib.js syncretro_lobby.js xtrn/syncivision/README.md syncretro.example.ini xtrn/syncivision/tests/test_syncretro_lib.js xtrn/syncnes/.gitignore README.md getcore.js install-xtrn.ini lobby.js syncretro.example.ini
    Modified Files:
    src/doors/syncretro/LAUNCHER.md deploy.js xtrn/syncivision/.gitignore getcore.js install-xtrn.ini lobby.js test_lobby_headless.js
    Removed Files:
    xtrn/syncivision/syncretro.ini
    Log Message:
    syncretro: one lobby for every console, and stop re-reading every ROM

    Adding the NES meant copying the lobby, the model layer and the core
    downloader into a second install directory -- and forking all three
    forever. They serve several installs, not one door, so they move to
    exec/load/ beside game_lobby.js:

    exec/load/syncretro_lib.js discovery, the ROM cache, the activity
    store (was xtrn/syncivision/*_lib.js)
    exec/load/syncretro_lobby.js the picker, the board, the door command
    line -- and it knows no console
    exec/load/syncretro_getcore.js the libretro buildbot downloader

    The rule that falls out, and is worth stating: a lib serving ONE door
    stays in the door dir (syncdoom_lib.js, syncduke_lib.js are right where
    they belong); a lib serving several goes to exec/load/.

    What remains in an install dir is what is ABOUT that console. Its lobby.js
    IS the console definition -- name, core, key profile, what a cartridge
    looks like, which BIOS it needs -- and it is code, not configuration,
    because an NES is an NES on every BBS. syncretro.ini keeps only what is genuinely a sysop's: [audio], [video], [disc], and [roms] dir/exclude. It
    is now seeded from a tracked syncretro.example.ini by the installer, as
    the sibling doors do, so an upgrade never overwrites an edited config.

    THE ROM CACHE. Drawing the menu opened, read and hashed EVERY cartridge,
    every time. The arithmetic was never the cost -- the round trips were: an install is typically an SMB mount, so a remote node paid one open + read + close per ROM just to see the list, and a sysop can feel it. The hash is
    cached in data/syncretro/roms.<id>.json, keyed by name + size + mtime, so
    a warm run opens exactly ONE file instead of one per ROM. Measured on the
    live 198-cartridge set: 212 opens -> 0, 62 ms -> 13 ms even locally, where
    an open is cheap. A cold run says so rather than appearing to hang.

    The cache is DERIVED, which is what lets it be written with none of the
    care plays.jsonl needs (data_dir is shared with a second host): a lost
    update costs a re-hash, never a wrong answer. Temp-file + rename; a torn,
    stale or missing cache reads as cold.

    The NES: xtrn/syncnes -- lobby.js, getcore.js (FCEUmm, GPLv2, fetched from
    the libretro buildbot), install-xtrn.ini, the example config. It needs NO
    BIOS, unlike the Intellivision; the exception is .fds, which needs
    disksys.rom and is therefore out of the default extension whitelist.

    deploy.js finds every console install itself (an xtrn/*/lobby.js that
    drives the shared lobby -- which IS the definition of a SyncRetro console),
    so a console added later gets the binary without editing the deploy step.

    plays.jsonl gains a console field, so one append-only log serves them all
    and each board shows only its own. A record with no console field predates
    the field, when the Intellivision was the only console there was: it IS an Intellivision play, and is counted as one.

    READMEs for both installs, in the shape of syncdoom's.

    ---
    þ 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 Mon Jul 13 00:36:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/6ff320f8017e1fa00cfdae7c
    Modified Files:
    exec/load/syncretro_getcore.js src/doors/syncretro/main.c retro_core.c retro_core.h
    Log Message:
    syncretro: say why the door cannot start; getcore.js can install for a host

    The NES door on the Windows node of a BBS whose install directory is shared with a Linux node did not start, and said nothing at all about why. Two defects, and the second is the one that made the first invisible.

    THE CORE WAS NEVER INSTALLED THERE. getcore.js only ever knew about the host
    it was RUNNING on, so a sysop who ran it on the Linux node installed the .so, was told "core installed", and left the Windows node with a door that had no .dll to load. A shared install serving several hosts needs a core for EACH -- they sit side by side, and nothing was able to put the second one there. getcore.js now takes `-platform <name>` (and `-arch`), so either host can install for the other.

    THE DOOR DIED IN SILENCE. Every fatal startup error -- no core, an unloadable core, an unreadable cartridge -- was an fprintf to stderr, and rc_core_open() ran BEFORE sr_io_init(): the terminal did not exist yet. A door's stderr reaches nobody (on Windows the BBS spawns it with no console at all), so the player saw "Loading SyncRetro...", the door exited, and the BBS took the
    screen back. No message, no log line, nothing to go on but "it doesn't work".

    So the terminal now comes up BEFORE the core, and a fatal error is written where the person who hit it can read it: what failed, in a sentence, and what the sysop should do about it. retro_core.c keeps the reason as a string (rc_core_error()) instead of only printing it, because printing it was the problem.

    SyncRetro cannot start.

    cannot load the core 'fceumm_libretro.dll': ... No such file or directory

    Sysop: the core must match the door binary -- a 32-bit .dll for the Win32
    .exe, a .so for the *nix build. getcore.js installs the right one for the
    host it runs on.

    ---
    þ 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 Tue Jul 21 21:53:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/e18c28da96b9c1d4d0bee1c3
    Modified Files:
    exec/load/syncretro_getcore.js syncretro_getroms.js
    Log Message:
    syncretro: fall back to the mirror for cores and ROMs

    Both shared fetchers now download through xtrn_mirror_download(), which
    covers syncnes, syncivision and syncarcade at once -- their per-door
    wrappers are unchanged.

    The libretro buildbot serves every platform's build under the same
    <core>.zip, so a flat mirror directory cannot hold more than one of them
    under that name; the mirrored copy is platform-qualified instead (fceumm_libretro.so-linux-x86_64.zip). Those are nightly builds, so no
    checksum is pinned and what the mirror holds is a snapshot: useful when
    the buildbot is unreachable, not a replacement for it. Only the
    platforms the mirror stocks resolve; anywhere else the fallback 404s and
    the buildbot failure stands, as before.

    The ROM table already pinned size and md5 per entry. That check moves
    into the verify callback so a truncated transfer retries against the
    mirror rather than simply failing, while a ROM that changed upstream is
    still never installed -- its licence was verified against those bytes.

    Verified: the FCEUmm core and all 20 ROMs installing from the mirror and
    from their official sources, and a re-run correctly reporting everything already present without touching the network.

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