docs: comprehensive README covering all features
Build & Deploy / build-and-deploy (push) Successful in 14s

- Browser play with js-dos & auto save states
- IGDB metadata/media integration (auto scrape, search, apply)
- File structure handling (flattening, subdirectories, CD mounting, path patching)
- Smart executable detection algorithm explained
- One-click Setup launcher (on-the-fly streaming)
- Windows game detection & UI marking
- Comparison with RomM feature-by-feature
- Cache-busting note for executable changes
- Architecture pipeline diagram
This commit is contained in:
Hermes Agent
2026-06-10 16:42:03 +02:00
parent 7cc5bddf73
commit 618d81770d
+163 -20
View File
@@ -1,6 +1,95 @@
# Dostalgia # DOSTalgia 🕹️
A nostalgic DOS game hub. Upload your old DOS games, scrape artwork, and play them directly in the browser via js-dos (WebAssembly DOSBox). A nostalgic DOS game hub. Upload your old DOS games, auto-scrape artwork and metadata from IGDB, and play them directly in your browser via js-dos (DOSBox compiled to WebAssembly).
## Features
### 🎮 Play in the browser
Every uploaded game is packaged into a `.jsdos` bundle — a standard ZIP with embedded DOSBox configuration. When you hit **Play**, js-dos v8 is loaded from CDN and starts the emulator instantly in your browser. No plugins, no native installs.
**Save states are automatic** — js-dos persists your game progress to the browser's storage. Come back anytime and pick up where you left off.
### 📡 IGDB metadata & media
Dostalgia integrates with [IGDB](https://www.igdb.com/) (via Twitch OAuth2) to auto-populate game info:
- **Auto Scrape** — On upload, Dostalgia searches IGDB by title and fills in year, genre, developer, publisher, description, and cover art. If IGDB finds a DOS result, it prioritises it.
- **Manual Search** — From the game detail page you can search IGDB by any query, browse results with cover thumbnails and DOS badges, and apply the one you want.
- **Media** — Videos (YouTube embeds) and screenshots (1080p) are fetched and displayed in a scrollable media gallery with a preview player.
Everything degrades gracefully — if Twitch credentials aren't configured, uploads and editing work fine, just without auto-scrape.
### 📦 Handles any file structure
DOS games come in all shapes. Dostalgia handles them transparently:
- **Flattening** — If your ZIP has a single root directory (e.g. `doom/` with all files inside), the extractor flattens it so the game files sit at the bundle root. No extra nesting.
- **Subdirectory games** — If files are deeper, the autoexec automatically `cd`s to the right directory before launching the executable.
- **CD images** — Games shipped on CD-ROM often need the disc mounted. Dostalgia detects `.iso`, `.cue`, `.img`, `.ccd`, and `.bin` files, fixes broken CloneCD `.cue` references (where the referenced `.bin` is actually `.img`), and mounts them in both `dosbox.conf` and `jsdos.json`.
- **CD-only games** — If the archive contains only CD images with no executable, a CD-only bundle is created that mounts the disc and drops you at the DOS prompt.
- **Hardcoded paths** — `ConfigPatcher` scans game config files for hardcoded absolute paths (e.g. `C:\FALLOUT1\MASTER.DAT`) that broke after flattening, and rewrites them to relative paths.
### 🔍 Smart executable detection
On upload, Dostalgia scans every `.exe`, `.com`, and `.bat` file and picks the best candidate as the main executable using a scoring system:
1. **Not an installer** — INSTALL/SETUP/CONFIG executables are deprioritised
2. **DOS executables** — Pure DOS apps are preferred over Windows ones
3. **Larger files** — Bigger executables are more likely to be the game
4. **Shallow depth** — Files closer to the root are preferred
5. **Self-extractor filtering** — PKZIP/PKSFX stubs are filtered out
All discovered executables are stored and available in the **Edit** page, where you can pick a different one via radio buttons.
> **⚠️ Cache note:** If you change the executable, the `.jsdos` bundle is patched in-place. Your browser may serve a cached version of the old bundle — if the game doesn't launch with the new executable, **hard-refresh** the play page (Ctrl+Shift+R / Cmd+Shift+R).
### 🛠 One-click Setup launcher
Many DOS games include a `SETUP.EXE`, `INSTALL.EXE`, or `CONFIG.EXE` used to configure sound, controls, and graphics. When Dostalgia detects one:
- A **🛠 Setup** button appears on the game detail page
- Clicking it launches the setup executable *without modifying the main game bundle*
- The setup bundle is generated **on-the-fly** by the server — a modified `.jsdos` is streamed with the setup executable in the autoexec, then discarded. Nothing is written to disk.
### 🪟 Windows game detection
DOSBox can't run Windows executables. Dostalgia's `PlatformDetector` reads MZ/PE/NE headers to detect Windows executables:
- The game detail page shows a **🪟 Requires Windows 3.1** badge
- The **Play** button is disabled with "Unplayable" text
- If you click Play anyway, a warning overlay explains the limitation with a **Try anyway** fallback
- Setup executables that are Windows-native are also filtered out from the Setup button
## How it works
```
┌──────────────────────────────────────────┐
│ Upload ZIP (multipart) │
└────────────┬─────────────────────────────┘
┌──────────────────────────┐
│ Unzip & flatten dirs │
│ Fix .cue references │
│ Fix absolute paths │
└────────────┬─────────────┘
┌──────────────────────────┐
│ Detect executables │
│ Detect CD images │
│ Detect platform (DOS/W) │
└────────────┬─────────────┘
┌──────────────────────────┐
│ Build .jsdos bundle │
│ (ZIP + dosbox.conf + │
│ jsdos.json) │
└────────────┬─────────────┘
┌──────────────────────────┐
│ Auto-scrape IGDB │
│ (year, genre, cover, │
│ videos, screenshots) │
└────────────┬─────────────┘
┌──────────────────────────┐
│ Save game.json │
└──────────────────────────┘
```
## Quick Start ## Quick Start
@@ -50,22 +139,27 @@ java -jar target/quarkus-app/quarkus-run.jar
## Architecture ## Architecture
- **Backend**: Quarkus (Java 21, JAX-RS) — ~5 REST resource classes, zero database - **Backend**: Quarkus (Java 21, JAX-RS) — REST endpoints, zero external database
- **Frontend**: Svelte 5 SPA with hash-based routing - **Frontend**: Svelte 5 SPA with hash-based routing
- **Emulation**: js-dos v8 loaded from CDN, runs DOSBox in WebAssembly - **Emulation**: js-dos v8 loaded from CDN, runs DOSBox in WebAssembly
- **Storage**: JSON-per-game under `/data/games/{id}/game.json` - **Storage**: JSON-per-game under `/data/games/{id}/game.json`
- **Saves**: Browser localStorage / indexedDB (managed by js-dos)
## API ## API
| Method | Path | Description | Method | Path | Description
|--------|------|-------------| --- | --- | ---
| GET | `/api/games` | List all games | GET | `/api/games` | List all games
| GET | `/api/games/:id` | Get game details | GET | `/api/games/:id` | Get game details
| PATCH | `/api/games/:id` | Update game metadata | PATCH | `/api/games/:id` | Update game metadata
| DELETE | `/api/games/:id` | Delete a game | DELETE | `/api/games/:id` | Delete a game
| POST | `/api/upload` | Upload a game ZIP (multipart) | POST | `/api/upload` | Upload a game ZIP (multipart)
| POST | `/api/games/:id/cover` | Upload cover art | POST | `/api/games/:id/cover` | Upload cover art
| GET | `/api/igdb/search?q=` | Search IGDB (placeholder) | GET | `/api/games/:id/setup-bundle` | Stream a setup .jsdos bundle (on-the-fly)
GET | `/api/games/:id/download` | Download the game's .jsdos bundle
GET | `/api/igdb/status` | Check if IGDB is configured
GET | `/api/igdb/search?q=` | Search IGDB for a game
POST | `/api/igdb/scrape/:id` | Auto-scrape or apply specific IGDB result
## Game JSON Schema ## Game JSON Schema
@@ -76,15 +170,28 @@ java -jar target/quarkus-app/quarkus-run.jar
"year": 1993, "year": 1993,
"genre": "FPS", "genre": "FPS",
"developer": "id Software", "developer": "id Software",
"bundle_file": "doom.jsdos", "publisher": "id Software",
"description": "You've signed up for...",
"bundle_file": "doom/doom.jsdos",
"executable": "DOOM.EXE",
"executables": ["DOOM.EXE", "SETUP.EXE"],
"setup_exe": "SETUP.EXE",
"has_setup": true,
"platform": "dos",
"bundle_size": 4194304,
"has_cover": true, "has_cover": true,
"ready": true "screenshots": ["https://..."],
"videos": ["dQw4w9WgXcQ"],
"igdb_id": 3498,
"ready": true,
"created_at": "2026-05-27T10:00:00Z",
"updated_at": "2026-05-27T10:00:00Z"
} }
``` ```
## IGDB Metadata (Optional) ## IGDB Metadata (Optional)
Dostalgia can auto-populate game metadata (year, genre, developer, cover art, screenshots, videos) from the [IGDB](https://www.igdb.com/) database. This requires a Twitch API application. Dostalgia can auto-populate game metadata (year, genre, developer, publisher, cover art, screenshots, videos) from the [IGDB](https://www.igdb.com/) database. This requires a Twitch API application.
**Setup:** **Setup:**
@@ -93,10 +200,46 @@ Dostalgia can auto-populate game metadata (year, genre, developer, cover art, sc
3. Copy the **Client ID** and generate a **Client Secret** 3. Copy the **Client ID** and generate a **Client Secret**
4. Provide them via environment variables: 4. Provide them via environment variables:
| Method | How | Method | How
|--------|-----| --- | ---
| Docker run | `-e TWITCH_CLIENT_ID=xxx -e TWITCH_CLIENT_SECRET=yyy` | Docker run | `-e TWITCH_CLIENT_ID=xxx -e TWITCH_CLIENT_SECRET=yyy`
| Docker Compose | Copy `.env.example` to `.env` and fill in the values | Docker Compose | Copy `.env.example` to `.env` and fill in the values
| Local dev | `export TWITCH_CLIENT_ID=xxx TWITCH_CLIENT_SECRET=yyy` | Local dev | `export TWITCH_CLIENT_ID=xxx TWITCH_CLIENT_SECRET=yyy`
IGDB features degrade gracefully — if credentials aren't set, uploads and metadata editing still work, just without auto-scrape. IGDB features degrade gracefully — if credentials aren't set, uploads and metadata editing still work, just without auto-scrape.
## Comparison with RomM
[RomM](https://www.romm.app/) is a popular ROM manager with web-based emulation. Here's how Dostalgia compares specifically for MS-DOS games:
| Feature | Dostalgia | RomM |
|---|---|---|
| **Emulator** | js-dos v8 (dedicated DOSBox WebAssembly) | EmulatorJS with dosbox-pure core |
| **Bundle format** | Auto-generated .jsdos with embedded config | Raw ZIP + manual .conf file |
| **Executable detection** | Automatic (smart scoring: depth, size, platform, installer filtering) | Manual — user must type `mount`, `cd`, and `exe` commands or write a .conf |
| **CD mounting** | Automatic — detects .iso/.cue/.img/.ccd/.bin, fixes broken cues, mounts in config | Manual — user must write `imgmount` commands in .conf |
| **Setup executable** | Auto-detected, one-click launch via on-the-fly streaming bundle | Not supported — user must run setup manually from DOS prompt |
| **Windows detection** | PE/NE header analysis, UI badge, disabled play button with fallback | Not supported |
| **IGDB integration** | Yes — auto-scrape, manual search, cover, genre, dev, publisher, videos, screenshots | Not for DOS specifically |
| **Config patching** | Automatic — `ConfigPatcher` rewrites hardcoded `C:\` paths in game configs | Not available |
| **GOG DOS games** | Supported (after flattening + path patching) | Explicitly NOT supported |
| **Database** | None — JSON files per game | PostgreSQL |
| **Upload size** | 2 GB limit | Depends on configuration |
| **Save states** | Yes (browser storage via js-dos) | Yes (via EmulatorJS) |
| **Target audience** | DOS-only, streamlined | Multi-platform, general-purpose |
**When to use RomM:** If you're managing ROMs across many platforms (NES, SNES, Genesis, PS1, etc.) alongside DOS games.
**When to use Dostalgia:** If you have a focused DOS collection and want a zero-fuss experience where you upload a ZIP and everything just works — executable detection, CD mounting, metadata, screenshots.
## Publishing the Docker image
The Docker image is fully self-contained (Java JAR + static frontend, no database). To publish:
```bash
docker build -t dostalgia .
docker tag dostalgia ghcr.io/yourname/dostalgia:latest
docker push ghcr.io/yourname/dostalgia:latest
```
Secrets are never baked into the image — users provide `TWITCH_CLIENT_ID` / `TWITCH_CLIENT_SECRET` at runtime via environment variables (or skip IGDB entirely).