• src/doors/syncdoom/i_termmusic.csrc/doors/syncdoom/CMakeLists.txt i_so

    From Rob Swindell (on Debian Linux)@VERT to Git commit to main/sbbs/master on Tue Jun 30 01:47:05 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/48adddb34d32072991d0d1ce
    Added Files:
    src/doors/syncdoom/i_termmusic.c
    Modified Files:
    src/doors/syncdoom/CMakeLists.txt i_sound.c m_menu.c syncdoom.c src/doors/syncduke/syncduke_input.c syncduke_io.c syncduke_stubs.c src/doors/termgfx/audio.c audio.h audio_mgr.c audio_mgr.h audio_midi.c
    Log Message:
    doors: SyncDOOM terminal music + cross-session audio caching (both doors)

    Wires music into SyncDOOM and adds a shared, cross-session OGG cache to
    termgfx so both doors stop re-rendering and re-uploading the same tracks.

    SyncDOOM music (new):
    - i_termmusic.c: a Doom music_module_t that renders each level's MUS/MIDI
    lump to OPL3 PCM (termgfx_midi_render/libADLMIDI -- adl_openData auto-
    detects MUS, no mus2mid) and loops it over SyncTERM's audio APC. Wired in
    i_sound.c's InitMusicModule(); title-song tier-deferral + stop-on-exit.
    - m_menu.c: restore a "Sound Volume" item (replacing the moot-in-a-terminal
    Graphic Detail toggle) so the existing Music Volume slider is reachable.

    termgfx audio caching (shared -> both doors):
    - Full-song loops: render cap 120s -> 600s (Doom tracks run to ~374s; the
    old cap looped them mid-song).
    - Door-side OGG disk cache: encode once, write to <data>/<door>/audio (the
    SCFG data_dir via $SBBSDATA, else beside the WADs/GRP), ship from disk
    after -- render happens once globally.
    - C;L client-cache skip: at tier-ready query SyncTERM's persistent cache and,
    on a name hit, Load straight from it -- no render AND no upload. Mirrors
    the zmachine's C;L pattern; name-presence (content-addressed), not MD5.
    - Cache names are consumer-namespaced + descriptive: <door>/music/<hash>_v<n>
    and <door>/sfx/<num> -- distinct + attributable in SyncTERM's one per-BBS
    cache dir (vs the terse, collision-prone shared m/ a/). Both doors content-
    hash music so a shared dir never serves the wrong track. Render-version tag
    invalidates cleanly if the synth changes.

    Input fix (both doors): the parsers now swallow APC/DCS/OSC/PM string
    sequences (ESC _ ... ESC \). The new C;L reply is an APC literally containing "C;L", and the old parsers leaked it as keystrokes -- the 'l' hit Load Game.

    Music-vs-SFX balance capped low (OPL music is sustained + peak-normalised). Each play logs which path it took (client-cached / disk-cached / rendered).

    Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

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