fix: revert SKIP_EXT to original — exclude CD images from bundles
Build & Deploy / build-and-deploy (push) Successful in 39s
Build & Deploy / build-and-deploy (push) Successful in 39s
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.
This commit is contained in:
@@ -168,7 +168,7 @@ public class GameService {
|
|||||||
|
|
||||||
// Build new config entries — preserve any CD images in the bundle
|
// Build new config entries — preserve any CD images in the bundle
|
||||||
List<String> cdImages = findCdImagesInBundle(bundlePath);
|
List<String> cdImages = findCdImagesInBundle(bundlePath);
|
||||||
byte[] newDosboxConf = buildDosboxConfBytes(executable, cdImages);
|
byte[] newDosboxConf = buildDosboxConfBytes(executable);
|
||||||
byte[] newJsdosJson = buildJsdosJsonBytes(executable);
|
byte[] newJsdosJson = buildJsdosJsonBytes(executable);
|
||||||
|
|
||||||
// Patch the ZIP: read old, write new with modified config entries
|
// Patch the ZIP: read old, write new with modified config entries
|
||||||
@@ -224,8 +224,8 @@ public class GameService {
|
|||||||
return cds;
|
return cds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Build a dosbox.conf for a given executable path and optional CD images. */
|
/** Build a dosbox.conf for a given executable path. */
|
||||||
private byte[] buildDosboxConfBytes(String relExe, List<String> cdImages) {
|
private byte[] buildDosboxConfBytes(String relExe) {
|
||||||
var parts = splitExePath(relExe);
|
var parts = splitExePath(relExe);
|
||||||
String dir = parts[0];
|
String dir = parts[0];
|
||||||
String exe = parts[1];
|
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("[sblaster]\nsbtype=sb16\nirq=7\ndma=1\nhdma=5\n\n");
|
||||||
sb.append("[dos]\nxms=true\nems=true\numb=true\n\n");
|
sb.append("[dos]\nxms=true\nems=true\numb=true\n\n");
|
||||||
sb.append("[autoexec]\n@echo off\nmount c .\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<String> 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");
|
sb.append("c:\n");
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
sb.append("path=c:\\\n");
|
sb.append("path=c:\\\n");
|
||||||
@@ -365,7 +340,7 @@ public class GameService {
|
|||||||
|
|
||||||
// Build new config entries — preserve any CD images in the bundle
|
// Build new config entries — preserve any CD images in the bundle
|
||||||
List<String> cdImages = findCdImagesInBundle(bundlePath);
|
List<String> cdImages = findCdImagesInBundle(bundlePath);
|
||||||
byte[] newDosboxConf = buildDosboxConfBytes(setupExe, cdImages);
|
byte[] newDosboxConf = buildDosboxConfBytes(setupExe);
|
||||||
byte[] newJsdosJson = buildJsdosJsonBytes(setupExe);
|
byte[] newJsdosJson = buildJsdosJsonBytes(setupExe);
|
||||||
|
|
||||||
try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath));
|
try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath));
|
||||||
@@ -401,7 +376,7 @@ public class GameService {
|
|||||||
byte[] dosboxConf;
|
byte[] dosboxConf;
|
||||||
byte[] jsdosConf;
|
byte[] jsdosConf;
|
||||||
if (exe != null && !exe.isBlank()) {
|
if (exe != null && !exe.isBlank()) {
|
||||||
dosboxConf = buildDosboxConfBytes(exe, cdImages);
|
dosboxConf = buildDosboxConfBytes(exe);
|
||||||
jsdosConf = buildJsdosJsonBytes(exe);
|
jsdosConf = buildJsdosJsonBytes(exe);
|
||||||
} else {
|
} else {
|
||||||
// CD-only game — generate CD-only config
|
// CD-only game — generate CD-only config
|
||||||
|
|||||||
@@ -397,13 +397,11 @@ public class UploadResource {
|
|||||||
|
|
||||||
// ─── Bundle Creation ─────────────────────────────────────────
|
// ─── Bundle Creation ─────────────────────────────────────────
|
||||||
|
|
||||||
/** File extensions that are never game data and should be excluded from .jsdos bundles.
|
/** 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. */
|
|
||||||
private static final java.util.Set<String> SKIP_EXT = java.util.Set.of(
|
private static final java.util.Set<String> SKIP_EXT = java.util.Set.of(
|
||||||
".nrg", ".mdf", ".mds", // disk images DOSBox can't mount natively
|
".img", ".iso", ".nrg", ".mdf", ".mds", // disk images
|
||||||
".sub", // subchannel data (accompanies .ccd — CCD itself is kept)
|
".ccd", ".sub", ".cue", ".bin", // CloneCD / CUE sheets + binaries
|
||||||
".dmg" // Mac disk images
|
".dmg" // Mac disk images
|
||||||
);
|
);
|
||||||
|
|
||||||
/** File extensions that DOSBox can mount as CD-ROM via imgmount. */
|
/** File extensions that DOSBox can mount as CD-ROM via imgmount. */
|
||||||
@@ -517,7 +515,7 @@ public class UploadResource {
|
|||||||
Files.createDirectories(jsdos);
|
Files.createDirectories(jsdos);
|
||||||
if (exePath != null) {
|
if (exePath != null) {
|
||||||
String relExe = extractDir.relativize(Path.of(exePath)).toString();
|
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));
|
Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe));
|
||||||
} else {
|
} else {
|
||||||
// CD-only game — no executable, mount CD and show a DOS prompt
|
// 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);
|
return json.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String buildDosboxConf(String relExe, List<String> cdImages) {
|
private String buildDosboxConf(String relExe) {
|
||||||
// DOS uses \\ as path separator; / is a switch character.
|
// DOS uses \\ as path separator; / is a switch character.
|
||||||
// If the executable is in a subdirectory, cd into it first.
|
// If the executable is in a subdirectory, cd into it first.
|
||||||
var parts = splitDirExe(relExe);
|
var parts = splitDirExe(relExe);
|
||||||
@@ -743,16 +741,6 @@ public class UploadResource {
|
|||||||
sb.append("[autoexec]\n");
|
sb.append("[autoexec]\n");
|
||||||
sb.append("@echo off\n");
|
sb.append("@echo off\n");
|
||||||
sb.append("mount c .\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");
|
sb.append("c:\n");
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
sb.append("path=c:\\\n");
|
sb.append("path=c:\\\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user