From b7e7133e0e14216f904f714449e5bd9efd2d0db1 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 3 Jun 2026 21:05:40 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20revert=20SKIP=5FEXT=20to=20original=20?= =?UTF-8?q?=E2=80=94=20exclude=20CD=20images=20from=20bundles?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ORIGINAL SKIP_EXT (when games worked): excluded .img, .iso, .ccd, .cue, .bin from bundles. My change included them, ballooning bundles to hundreds of MB. The WASM libzip MEMFS can't handle such large files → 'Unable to add .jsdos/jsdos.json into bundle.zip' + 'Not a zip archive' on every game. This is the ROOT CAUSE — confirmed by: - Same error on ALL js-dos versions (8.3.14/emu-8.3.3 AND 8.3.20/emu-8.3.8) → not a version issue - Warcraft CD-ROM with CD images → HUGE bundle → fails - Original code with SKIP_EXT excluding CD images → small bundles → works Also reverted CD mounting logic in buildDosboxConf since there are no CD images in the bundle to mount. CD image support will be re-implemented separately via separate file serving. --- src/main/java/com/dostalgia/GameService.java | 35 +++---------------- .../java/com/dostalgia/UploadResource.java | 24 ++++--------- 2 files changed, 11 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/dostalgia/GameService.java b/src/main/java/com/dostalgia/GameService.java index 92d59ed..461d1cc 100644 --- a/src/main/java/com/dostalgia/GameService.java +++ b/src/main/java/com/dostalgia/GameService.java @@ -168,7 +168,7 @@ public class GameService { // Build new config entries — preserve any CD images in the bundle List cdImages = findCdImagesInBundle(bundlePath); - byte[] newDosboxConf = buildDosboxConfBytes(executable, cdImages); + byte[] newDosboxConf = buildDosboxConfBytes(executable); byte[] newJsdosJson = buildJsdosJsonBytes(executable); // Patch the ZIP: read old, write new with modified config entries @@ -224,8 +224,8 @@ public class GameService { return cds; } - /** Build a dosbox.conf for a given executable path and optional CD images. */ - private byte[] buildDosboxConfBytes(String relExe, List cdImages) { + /** Build a dosbox.conf for a given executable path. */ + private byte[] buildDosboxConfBytes(String relExe) { var parts = splitExePath(relExe); String dir = parts[0]; String exe = parts[1]; @@ -236,31 +236,6 @@ public class GameService { sb.append("[sblaster]\nsbtype=sb16\nirq=7\ndma=1\nhdma=5\n\n"); sb.append("[dos]\nxms=true\nems=true\numb=true\n\n"); sb.append("[autoexec]\n@echo off\nmount c .\n"); - // Mount CD images as D:, E:, … so games can find their CD. - // Deduplicate by parent directory — prefer data formats over descriptors. - Set seenDirs = new java.util.HashSet<>(); - char driveLetter = 'D'; - for (String img : cdImages) { - int slashIdx = img.lastIndexOf('/'); - String parentDir = slashIdx >= 0 ? img.substring(0, slashIdx) : ""; - if (seenDirs.contains(parentDir)) continue; - String imgLower = img.toLowerCase(); - // Skip descriptor formats if a data format exists in the same directory - if (imgLower.endsWith(".cue") || imgLower.endsWith(".ccd")) { - boolean hasData = cdImages.stream().anyMatch(i -> { - int is = i.lastIndexOf('/'); - String ip = is >= 0 ? i.substring(0, is) : ""; - String il = i.toLowerCase(); - return ip.equals(parentDir) - && (il.endsWith(".img") || il.endsWith(".iso") || il.endsWith(".bin")); - }); - if (hasData) continue; - } - seenDirs.add(parentDir); - String flags = imgLower.endsWith(".bin") ? " -t cdrom -fs iso" : " -t cdrom"; - sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n"); - driveLetter++; - } sb.append("c:\n"); if (dir != null) { sb.append("path=c:\\\n"); @@ -365,7 +340,7 @@ public class GameService { // Build new config entries — preserve any CD images in the bundle List cdImages = findCdImagesInBundle(bundlePath); - byte[] newDosboxConf = buildDosboxConfBytes(setupExe, cdImages); + byte[] newDosboxConf = buildDosboxConfBytes(setupExe); byte[] newJsdosJson = buildJsdosJsonBytes(setupExe); try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath)); @@ -401,7 +376,7 @@ public class GameService { byte[] dosboxConf; byte[] jsdosConf; if (exe != null && !exe.isBlank()) { - dosboxConf = buildDosboxConfBytes(exe, cdImages); + dosboxConf = buildDosboxConfBytes(exe); jsdosConf = buildJsdosJsonBytes(exe); } else { // CD-only game — generate CD-only config diff --git a/src/main/java/com/dostalgia/UploadResource.java b/src/main/java/com/dostalgia/UploadResource.java index 1764b6a..61b3ab9 100644 --- a/src/main/java/com/dostalgia/UploadResource.java +++ b/src/main/java/com/dostalgia/UploadResource.java @@ -397,13 +397,11 @@ public class UploadResource { // ─── Bundle Creation ───────────────────────────────────────── - /** File extensions that are never game data and should be excluded from .jsdos bundles. - * Only formats DOSBox can't mount natively are stripped. - * Mountable formats (.iso, .cue, .img, .ccd) are kept and auto-mounted via imgmount. */ + /** File extensions that are never game data and should be excluded from .jsdos bundles. */ private static final java.util.Set SKIP_EXT = java.util.Set.of( - ".nrg", ".mdf", ".mds", // disk images DOSBox can't mount natively - ".sub", // subchannel data (accompanies .ccd — CCD itself is kept) - ".dmg" // Mac disk images + ".img", ".iso", ".nrg", ".mdf", ".mds", // disk images + ".ccd", ".sub", ".cue", ".bin", // CloneCD / CUE sheets + binaries + ".dmg" // Mac disk images ); /** File extensions that DOSBox can mount as CD-ROM via imgmount. */ @@ -517,7 +515,7 @@ public class UploadResource { Files.createDirectories(jsdos); if (exePath != null) { String relExe = extractDir.relativize(Path.of(exePath)).toString(); - Files.writeString(jsdos.resolve("dosbox.conf"), buildDosboxConf(relExe, cdImages)); + Files.writeString(jsdos.resolve("dosbox.conf"), buildDosboxConf(relExe)); Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe)); } else { // CD-only game — no executable, mount CD and show a DOS prompt @@ -709,7 +707,7 @@ public class UploadResource { return json.getBytes(java.nio.charset.StandardCharsets.UTF_8); } - private String buildDosboxConf(String relExe, List cdImages) { + private String buildDosboxConf(String relExe) { // DOS uses \\ as path separator; / is a switch character. // If the executable is in a subdirectory, cd into it first. var parts = splitDirExe(relExe); @@ -743,16 +741,6 @@ public class UploadResource { sb.append("[autoexec]\n"); sb.append("@echo off\n"); sb.append("mount c .\n"); - // Mount CD images as D:, E:, … so games can find their CD. - // Resolve one image per directory with format priority (.cue > .iso > .ccd > .img > .bin) - char driveLetter = 'D'; - for (String img : resolveCdImages(cdImages)) { - String imgLower = img.toLowerCase(); - String flags = (imgLower.endsWith(".bin") && !imgLower.endsWith(".cue")) - ? " -t cdrom -fs iso" : " -t cdrom"; - sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n"); - driveLetter++; - } sb.append("c:\n"); if (dir != null) { sb.append("path=c:\\\n");