diff --git a/src/main/java/com/dostalgia/UploadResource.java b/src/main/java/com/dostalgia/UploadResource.java index 340396e..8b202b1 100644 --- a/src/main/java/com/dostalgia/UploadResource.java +++ b/src/main/java/com/dostalgia/UploadResource.java @@ -80,6 +80,13 @@ public class UploadResource { + " — continuing (cd in autoexec handles subdirs)"); } + // Fix .cue files that reference non-existent data files (e.g. CloneCD) + try { + fixCueReferences(extractDir); + } catch (Exception e) { + LOG.warning("Failed to fix cue references: " + e.getMessage()); + } + // Find main executable String mainExe = findMainExe(extractDir); @@ -404,6 +411,66 @@ public class UploadResource { ".iso", ".cue", ".img", ".ccd", ".bin" ); + /** + * Fix .cue files that reference non-existent data files. + * CloneCD rips often generate a .cue that says FILE "DOTT.bin" BINARY + * but the actual data file is DOTT.img. DOSBox can't load the .cue + * when the referenced file doesn't exist. + */ + private static void fixCueReferences(Path extractDir) throws IOException { + try (var walk = Files.walk(extractDir)) { + walk.filter(Files::isRegularFile) + .filter(f -> f.getFileName().toString().toLowerCase().endsWith(".cue")) + .forEach(f -> { + try { + fixOneCue(f); + } catch (IOException e) { + LOG.warning("Failed to fix cue file " + f + ": " + e.getMessage()); + } + }); + } + } + + private static void fixOneCue(Path cueFile) throws IOException { + String content = Files.readString(cueFile); + Path dir = cueFile.getParent(); + + // Find the FILE line: FILE "somefile.bin" BINARY + // The pattern: FILE "..." (anything between quotes) + java.util.regex.Matcher m = java.util.regex.Pattern + .compile("FILE\\s+\"([^\"]+)\"", java.util.regex.Pattern.CASE_INSENSITIVE) + .matcher(content); + if (!m.find()) return; // no FILE line, nothing to fix + + String referenced = m.group(1); + Path refPath = dir.resolve(referenced); + if (Files.exists(refPath)) return; // referenced file exists, cue is fine + + // Referenced file doesn't exist — look for .img or .bin in same directory + Path replacement = findDataFile(dir); + if (replacement == null) return; // nothing to replace with + + // Rewrite the FILE line with the actual file + String actualName = replacement.getFileName().toString(); + content = content.substring(0, m.start(1)) + actualName + content.substring(m.end(1)); + Files.writeString(cueFile, content); + LOG.info("Fixed cue " + cueFile.getFileName() + ": referenced '" + referenced + + "' → '" + actualName + "'"); + } + + /** Find a .img or .bin file in the directory that could be the data file. */ + private static Path findDataFile(Path dir) throws IOException { + try (var files = Files.list(dir)) { + return files.filter(Files::isRegularFile) + .filter(f -> { + String n = f.getFileName().toString().toLowerCase(); + return n.endsWith(".img") || n.endsWith(".bin"); + }) + .findFirst() + .orElse(null); + } + } + /** Find mountable CD image files in the extracted game directory. * Returns relative paths (with forward slashes) sorted alphabetically. */ private List findCdImages(Path dir) throws IOException {