- 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
12 KiB
DOSTalgia 🕹️
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 (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
cds 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.binfiles, fixes broken CloneCD.cuereferences (where the referenced.binis actually.img), and mounts them in bothdosbox.confandjsdos.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 —
ConfigPatcherscans 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:
- Not an installer — INSTALL/SETUP/CONFIG executables are deprioritised
- DOS executables — Pure DOS apps are preferred over Windows ones
- Larger files — Bigger executables are more likely to be the game
- Shallow depth — Files closer to the root are preferred
- 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
.jsdosbundle 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
.jsdosis 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
With Docker Compose (easiest)
# 1. (Optional) Enable IGDB metadata auto-scrape
cp .env.example .env
# Edit .env with your Twitch credentials (see IGDB section below)
# 2. Build & run
docker compose up -d
With Docker
docker build -t dostalgia .
docker run -p 8765:8765 -v $(pwd)/data:/data \
-e TWITCH_CLIENT_ID=your_id \
-e TWITCH_CLIENT_SECRET=your_secret \
dostalgia
Development (without Docker)
Terminal 1 — Frontend dev server:
cd frontend && npm install && npm run dev
Terminal 2 — Quarkus dev server:
mvn quarkus:dev
Open http://localhost:5173 (Vite proxies API calls to Quarkus on port 8765)
Production build (local)
cd frontend && npm install && npm run build
mvn package -DskipTests
java -jar target/quarkus-app/quarkus-run.jar
Architecture
- Backend: Quarkus (Java 21, JAX-RS) — REST endpoints, zero external database
- Frontend: Svelte 5 SPA with hash-based routing
- Emulation: js-dos v8 loaded from CDN, runs DOSBox in WebAssembly
- Storage: JSON-per-game under
/data/games/{id}/game.json - Saves: Browser localStorage / indexedDB (managed by js-dos)
API
| Method | Path | Description |
|---|---|---|
| GET | /api/games |
List all games |
| GET | /api/games/:id |
Get game details |
| PATCH | /api/games/:id |
Update game metadata |
| DELETE | /api/games/:id |
Delete a game |
| POST | /api/upload |
Upload a game ZIP (multipart) |
| POST | /api/games/:id/cover |
Upload cover art |
| 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
{
"id": "doom",
"title": "Doom",
"year": 1993,
"genre": "FPS",
"developer": "id Software",
"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,
"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)
Dostalgia can auto-populate game metadata (year, genre, developer, publisher, cover art, screenshots, videos) from the IGDB database. This requires a Twitch API application.
Setup:
- Go to https://dev.twitch.tv/console/apps → Register Your Application
- Name:
Dostalgia(or anything), OAuth Redirect URL:http://localhost, Category: Other - Copy the Client ID and generate a Client Secret
- Provide them via environment variables:
| Method | How |
|---|---|
| Docker run | -e TWITCH_CLIENT_ID=xxx -e TWITCH_CLIENT_SECRET=yyy |
| Docker Compose | Copy .env.example to .env and fill in the values |
| 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.
Comparison with RomM
RomM 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:
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).