Files
docker-dosbox-novnc/TODO.md
T
jensandClaude Sonnet 5 afb18f1b38 Add ScummVM support and generalize manifest zip lookup
Add scummvm to the Dockerfile. Its binary lives at /usr/games/scummvm
(Debian's convention for game packages), not reliably on $PATH under a
non-login shell, so manifests reference it by absolute path.

Generalize the manifest schema from a bare "zip" filename (implicitly
under Games\dosbox\ on the SMB share) to "zip_path" (a full path
relative to the share root), since the SCUMM games' zips live in their
own folders (Games\Monkey Island\, Games\Indiana Jones\, etc.) rather
than being colocated with their manifest like stuntcar/t7g were.
Manifests themselves still all live in the Games\dosbox\ catalog
directory regardless of where the actual zip sits.

Added and verified (install/start/stop/uninstall via monkey2) manifests
for: monkey, monkey2, atlantis, indy3, tentacle. Skipped the German CD
release of Day of the Tentacle (loose files at the zip root, no single
top-level folder - incompatible with the current extraction convention)
and Curse of Monkey Island (untested, much larger).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NiNnj78HGx1KWyCCo39HSz
2026-07-28 14:29:11 +02:00

5.5 KiB

TODO

  • ~Reduce image size of jayfield/dosbox-novnc (currently 2.3GB). Done in two steps:

    1. Merged the game download/extract steps and the unzip/smbclient install into a single layer (so the downloaded zips and the packages only needed to extract them no longer persist in the final image). 2.31GB -> 1.6GB.
    2. Stopped baking the games into the image at all (927MB of that was just t7g's two CD ISOs). run.sh mounts a named volume (dosbox-games) so installed games persist across --rm restarts. 1.6GB -> ~690MB. Container now needs network access to vlda-01 at runtime (not just build time) to install games.
    3. Dropped the auto-download at container startup entirely. scripts/setup_server.py is a small stdlib-only HTTP server (started alongside Xvnc/fluxbox/websockify) that serves an HTML page on ${SETUP_PORT} (70${DISPLAY_NUM}, published as 7099 by run.sh) listing every *.zip on the SMB share with an Installed/Install status per game; the user clicks "Install" to fetch+extract a specific game into ${GAMES_HOME} on demand.
  • Manifest-driven games + Start/Stop/Uninstall: games are no longer discovered from raw *.zip files on the share. setup_server.py lists *.json manifests instead (one per game, in the Games\dosbox\ catalog directory), each declaring name/title/zip_path/start_cmd. The web page grew Start/Stop/Uninstall buttons alongside Install, driven entirely by that manifest — nothing about a game's identity or how to run it is hardcoded in the image anymore. Started as a stuntcar-only pilot, now extended to 6 games (see the SCUMM item below). t7g still has no manifest and won't show up in the setup page until one is added (t7g.json with a start_cmd for its dosbox-0.74-3.conf). game.sh/scripts/start_game.sh (the old docker exec-based launch path, with its hardcoded DOSBOX_VERSION/run.bat convention) were intentionally left untouched during the pilot and still overlap with the new Start button — worth reconciling (or removing) once every remaining game has a manifest.

  • Create manifests for SCUMM engine games Done: scummvm added to the Dockerfile (/usr/games/scummvm, not on $PATH by default under a non-login shell — manifests use the absolute path). Manifests live in the usual Games\dosbox\*.json catalog directory on the share, but their zip_path now points at wherever the game's zip actually already lived (Games\Monkey Island\..., Games\Indiana Jones\..., etc.) — this required generalizing the manifest schema from a bare zip filename (implicitly under Games\dosbox\) to a full zip_path relative to the share root, since these games weren't colocated with dosbox's. Added and verified end-to-end (install/start/stop/uninstall) via monkey2:

    • monkey — The Secret of Monkey Island
    • monkey2 — Monkey Island 2: LeChuck's Revenge
    • atlantis — Indiana Jones and the Fate of Atlantis
    • indy3 — Indiana Jones and the Last Crusade
    • tentacle — Day of the Tentacle

    Skipped the German CD release of Day of the Tentacle on the share (Day Of The Tentacle (CD DOS, German).zip) — unlike every other zip here, it doesn't wrap its contents in a single top-level folder (loose files at the zip root plus a stray MANIAC/ dir for the embedded Maniac Mansion easter egg), so it doesn't fit the current "zip's top-level folder == install name" extraction convention. Also skipped Curse of Monkey Island (much larger, untested) — could be added the same way if wanted.

    ScummVM's own game-target IDs (monkey, monkey2, atlantis, indy3, tentacle) happened to exactly match each zip's existing top-level folder name, so no change was needed to the install/extraction logic itself, only to where zips are looked up from.

  • Get game sound actually audible during play. --device /dev/snd is passed through and alsa-utils is installed, so DOSBox can write to an ALSA device inside the container, but VNC/noVNC only ever streams video, not audio — nothing currently carries that sound out to the browser.

    Target latency is a few tens of ms, not seconds — that rules out the "obvious" approach of a PulseAudio null sink piped through ffmpeg into a compressed (mp3/ogg) HTTP/Icecast-style stream consumed by an <audio> tag: codec frame buffering plus the <audio> element's own jitter buffer realistically puts that in the 1-3s range, no matter how it's tuned.

    Concrete approach instead: PulseAudio null sink → capture raw/lightly-buffered PCM (small frames, e.g. parec with a short --latency) → push those frames to the browser over a plain WebSocket (new endpoint alongside setup_server.py, or a small dedicated process) → browser side, feed them straight into the Web Audio API via an AudioWorkletNode (not <audio>, not ScriptProcessorNode — that's deprecated and has worse latency) for near-real-time scheduled playback. No container/codec framing in the path at all.

    Build this to be reusable across the other noVNC-family projects (docker-xserver-novnc, docker-sdr-novnc), not dosbox-specific — it's a "browser audio + noVNC" concern, nothing about it is really about DOSBox. Follow the docker-common/scripts/signals.sh precedent (see the docker-common repo): keep the generic PulseAudio-sink/WebSocket/AudioWorklet piece project-agnostic there, then copy it (not symlink) into each project's own scripts/ the same way signal handling is shared, so a fix in one place gets propagated by hand to the others.