From 5f5cb8411f18bfc5e940cd653ddcf90876be5823 Mon Sep 17 00:00:00 2001 From: David Alvarez Date: Wed, 27 May 2026 16:49:15 +0200 Subject: [PATCH] feat: SETUP.EXE detection + separate setup .jsdos bundle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a game archive contains SETUP.EXE, INSTALL.EXE, CONFIG.EXE or CUSTOM.EXE (or .com/.bat variants), the upload now: - Detects and stores the path in game metadata (setup_exe / has_setup) - Generates a second .jsdos bundle with SETUP.EXE as autoexec: - Standard mode: {gameId}.setup.jsdos (full game + setup autoexec) - Sockdrive mode: .jsdos-setup/ directory alongside .jsdos/ - Both bundles share the same game files; only the autoexec differs Frontend changes: - Router strips query params from hash so ?setup=1 doesn't leak into id - GameDetail shows a "Setup" button between Play and Edit (only when game.has_setup is true), navigating to /play/{id}?setup=1 - Play.svelte detects ?setup=1, loads setupBundleUrl() instead, and shows setup-specific overlay text Persistence is handled automatically by js-dos v8 via the built-in auto-save mechanism (ci.persist() → browser OPFS), so any config changes made via SETUP.EXE survive across sessions. --- frontend/src/App.svelte | 3 +- frontend/src/lib/api.js | 11 +- frontend/src/pages/GameDetail.svelte | 17 ++- frontend/src/pages/Play.svelte | 26 ++++- src/main/java/com/dostalgia/Game.java | 8 ++ src/main/java/com/dostalgia/GameService.java | 18 +++ .../java/com/dostalgia/UploadResource.java | 110 ++++++++++++++++++ 7 files changed, 185 insertions(+), 8 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index a535a82..eae9ebf 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -10,7 +10,8 @@ function parseHash() { const hash = window.location.hash.slice(1) || "/"; - const parts = hash.split("/").filter(Boolean); + const [pathPart] = hash.split("?"); // strip query params + const parts = pathPart.split("/").filter(Boolean); if (parts.length === 0 || (parts.length === 1 && parts[0] === "")) { route = "/"; gameId = null; diff --git a/frontend/src/lib/api.js b/frontend/src/lib/api.js index 559f640..f12cde1 100644 --- a/frontend/src/lib/api.js +++ b/frontend/src/lib/api.js @@ -102,7 +102,7 @@ export function artworkUrl(path) { return `/artwork/${path}`; } -/** Get game bundle URL */ +/** Get game bundle URL for normal play */ export function bundleUrl(game) { if (!game) return null; if (game.bundle_type === "sockdrive") { @@ -110,3 +110,12 @@ export function bundleUrl(game) { } return `/games/${game.id}.jsdos`; } + +/** Get game bundle URL for setup mode (runs SETUP.EXE instead) */ +export function setupBundleUrl(game) { + if (!game) return null; + if (game.bundle_type === "sockdrive") { + return `/api/sockdrive/${game.id}/file?path=.jsdos-setup/dosbox.conf`; + } + return `/games/${game.id}.setup.jsdos`; +} diff --git a/frontend/src/pages/GameDetail.svelte b/frontend/src/pages/GameDetail.svelte index e82b8af..d4c9c99 100644 --- a/frontend/src/pages/GameDetail.svelte +++ b/frontend/src/pages/GameDetail.svelte @@ -1,5 +1,5 @@