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
80 lines
5.5 KiB
Markdown
80 lines
5.5 KiB
Markdown
# 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.
|