fix: smarter CD image selection per directory with format priority
Build & Deploy / build-and-deploy (push) Successful in 43s
Build & Deploy / build-and-deploy (push) Successful in 43s
Replace the broken descriptor-preference logic with a clean two-pass approach: group images by parent directory, then pick the best format per directory with priority .cue > .iso > .ccd > .img > .bin. js-dos DOSBox's imgmount does NOT support .ccd (CloneCD descriptor) natively, but .cue is widely supported. When both exist, .cue wins. When only .ccd exists, it falls back to mounting the .img directly.
This commit is contained in:
@@ -564,6 +564,46 @@ public class UploadResource {
|
|||||||
return json.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
return json.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Resolve one CD image per parent directory with best-format priority.
|
||||||
|
* Priority: .cue > .iso > .ccd > .img > .bin
|
||||||
|
* js-dos DOSBox (Emscripten) supports .cue natively, but .ccd often fails. */
|
||||||
|
private static List<String> resolveCdImages(List<String> cdImages) {
|
||||||
|
// Group by parent directory
|
||||||
|
java.util.Map<String, java.util.List<String>> byDir = new java.util.LinkedHashMap<>();
|
||||||
|
for (String img : cdImages) {
|
||||||
|
int slashIdx = img.lastIndexOf('/');
|
||||||
|
String parentDir = slashIdx >= 0 ? img.substring(0, slashIdx) : "";
|
||||||
|
byDir.computeIfAbsent(parentDir, k -> new java.util.ArrayList<>()).add(img);
|
||||||
|
}
|
||||||
|
List<String> result = new java.util.ArrayList<>();
|
||||||
|
for (var entry : byDir.entrySet()) {
|
||||||
|
String best = pickBestCdImage(entry.getValue());
|
||||||
|
if (best != null) result.add(best);
|
||||||
|
}
|
||||||
|
result.sort(String::compareTo);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String pickBestCdImage(java.util.List<String> images) {
|
||||||
|
// Priority: .cue [5] > .iso [4] > .ccd [3] > .img [2] > .bin [1]
|
||||||
|
String best = null;
|
||||||
|
int bestScore = -1;
|
||||||
|
for (String s : images) {
|
||||||
|
String lo = s.toLowerCase();
|
||||||
|
int score = lo.endsWith(".cue") ? 5
|
||||||
|
: lo.endsWith(".iso") ? 4
|
||||||
|
: lo.endsWith(".ccd") ? 3
|
||||||
|
: lo.endsWith(".img") ? 2
|
||||||
|
: lo.endsWith(".bin") ? 1
|
||||||
|
: 0;
|
||||||
|
if (score > bestScore) {
|
||||||
|
bestScore = score;
|
||||||
|
best = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
/** Build config for a CD-only game (no executables on the filesystem). */
|
/** Build config for a CD-only game (no executables on the filesystem). */
|
||||||
private String buildCdOnlyDosboxConf(List<String> cdImages) {
|
private String buildCdOnlyDosboxConf(List<String> cdImages) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
@@ -574,27 +614,10 @@ public class UploadResource {
|
|||||||
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:, …
|
// Mount CD images as D:, E:, …
|
||||||
// Prefer descriptor formats (.cue, .ccd) over raw data (.img, .bin)
|
// Resolve one image per directory with format priority (.cue > .iso > .ccd > .img > .bin)
|
||||||
// DOSBox needs descriptors for proper track layout and filesystem access.
|
|
||||||
Set<String> seenDirs = new java.util.HashSet<>();
|
|
||||||
char driveLetter = 'D';
|
char driveLetter = 'D';
|
||||||
for (String img : cdImages) {
|
for (String img : resolveCdImages(cdImages)) {
|
||||||
int slashIdx = img.lastIndexOf('/');
|
|
||||||
String parentDir = slashIdx >= 0 ? img.substring(0, slashIdx) : "";
|
|
||||||
if (seenDirs.contains(parentDir)) continue;
|
|
||||||
String imgLower = img.toLowerCase();
|
String imgLower = img.toLowerCase();
|
||||||
// Skip raw data files when a descriptor exists in the same directory
|
|
||||||
if (imgLower.endsWith(".img") || imgLower.endsWith(".bin")) {
|
|
||||||
boolean hasDescriptor = 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(".cue") || il.endsWith(".ccd"));
|
|
||||||
});
|
|
||||||
if (hasDescriptor) continue;
|
|
||||||
}
|
|
||||||
seenDirs.add(parentDir);
|
|
||||||
String flags = (imgLower.endsWith(".bin") && !imgLower.endsWith(".cue"))
|
String flags = (imgLower.endsWith(".bin") && !imgLower.endsWith(".cue"))
|
||||||
? " -t cdrom -fs iso" : " -t cdrom";
|
? " -t cdrom -fs iso" : " -t cdrom";
|
||||||
sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n");
|
sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n");
|
||||||
@@ -654,28 +677,10 @@ public class UploadResource {
|
|||||||
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.
|
// Mount CD images as D:, E:, … so games can find their CD.
|
||||||
// Deduplicate by parent directory — prefer descriptor formats (.cue, .ccd)
|
// Resolve one image per directory with format priority (.cue > .iso > .ccd > .img > .bin)
|
||||||
// over raw data formats (.img, .bin). DOSBox needs descriptors for proper
|
|
||||||
// track layout (audio tracks, subchannel data, copy protection).
|
|
||||||
Set<String> seenDirs = new java.util.HashSet<>();
|
|
||||||
char driveLetter = 'D';
|
char driveLetter = 'D';
|
||||||
for (String img : cdImages) {
|
for (String img : resolveCdImages(cdImages)) {
|
||||||
int slashIdx = img.lastIndexOf('/');
|
|
||||||
String parentDir = slashIdx >= 0 ? img.substring(0, slashIdx) : "";
|
|
||||||
if (seenDirs.contains(parentDir)) continue;
|
|
||||||
String imgLower = img.toLowerCase();
|
String imgLower = img.toLowerCase();
|
||||||
// Skip raw data files when a descriptor exists in the same directory
|
|
||||||
if (imgLower.endsWith(".img") || imgLower.endsWith(".bin")) {
|
|
||||||
boolean hasDescriptor = 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(".cue") || il.endsWith(".ccd"));
|
|
||||||
});
|
|
||||||
if (hasDescriptor) continue;
|
|
||||||
}
|
|
||||||
seenDirs.add(parentDir);
|
|
||||||
String flags = (imgLower.endsWith(".bin") && !imgLower.endsWith(".cue"))
|
String flags = (imgLower.endsWith(".bin") && !imgLower.endsWith(".cue"))
|
||||||
? " -t cdrom -fs iso" : " -t cdrom";
|
? " -t cdrom -fs iso" : " -t cdrom";
|
||||||
sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n");
|
sb.append("imgmount ").append(driveLetter).append(" \"").append(img).append("\"").append(flags).append("\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user