diff --git a/src/main/java/com/dostalgia/GameResource.java b/src/main/java/com/dostalgia/GameResource.java index abbc9d5..136819d 100644 --- a/src/main/java/com/dostalgia/GameResource.java +++ b/src/main/java/com/dostalgia/GameResource.java @@ -131,23 +131,6 @@ public class GameResource { } } - /** - * Patch a Sierra game bundle to fix common file layout issues - * (INTERP.ERR paths, RESOURCE.CFG directories). - */ - @POST - @Path("/{id}/patch-sierra") - public Response patchSierra(@PathParam("id") String id) { - try { - var patched = svc.patchSierraGame(id); - return Response.ok(Map.of("patched", patched)).build(); - } catch (NoSuchFileException e) { - return Response.status(404).entity(Map.of("error", "Game not found")).build(); - } catch (Exception e) { - return Response.serverError().entity(Map.of("error", e.getMessage())).build(); - } - } - @GET @Path("/{id}/download") @Produces("application/zip") diff --git a/src/main/java/com/dostalgia/GameService.java b/src/main/java/com/dostalgia/GameService.java index dbcc54e..0c34d1b 100644 --- a/src/main/java/com/dostalgia/GameService.java +++ b/src/main/java/com/dostalgia/GameService.java @@ -322,154 +322,5 @@ public class GameService { } } - /** - * Patch a .jsdos bundle for Sierra games that have file layout issues: - * - INTERP.ERR(C) in a subdirectory instead of root (causes "Can't find" errors) - * - RESOURCE.CFG directory paths pointing to wrong locations - * Returns the list of files that were modified. - */ - public List patchSierraGame(String id) throws IOException { - Game game = load(id); - Path bundlePath = gamesDir.resolve(game.getBundleFile()); - if (!Files.exists(bundlePath)) { - throw new NoSuchFileException("Bundle not found: " + game.getBundleFile()); - } - - Path tmpPath = bundlePath.resolveSibling(bundlePath.getFileName() + ".patchtmp"); - List patched = new ArrayList<>(); - - try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath)); - var zos = new java.util.zip.ZipOutputStream(Files.newOutputStream(tmpPath))) { - - // First pass: read all entries to find INTERP files in subdirs - // We can't buffer the whole zip, so we do the copy in one pass - // and apply known fixes on the fly. - - // Read the RESOURCE.CFG for Sierra directory detection - // We do this by pre-scanning the zip (streaming approach) - - java.util.zip.ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - String name = entry.getName(); - zos.putNextEntry(new java.util.zip.ZipEntry(name)); - - if (name.equals("RESOURCE.CFG")) { - // Read, patch, write - byte[] content = zis.readAllBytes(); - String text = new String(content, java.nio.charset.StandardCharsets.ISO_8859_1); - String original = text; - - // Fix directory paths pointing to a subdir when resources are at root - text = text.replaceAll("(?m)^directory\\s*=\\\\?.+", "directory = ."); - text = text.replaceAll("(?m)^audio\\s*=\\s*[A-Za-z]:\\\\?.+", "audio = ."); - text = text.replaceAll("(?m)^sync\\s*=\\s*[A-Za-z]:\\\\?.+", "sync = ."); - text = text.replaceAll("(?m)^movieDir\\s*=\\s*[A-Za-z]:\\\\?.+", "movieDir = .\\\\SEQ"); - text = text.replaceAll("(?m)^patchDir\\s*=\\s*[A-Za-z]:\\\\?.+", "patchDir = ."); - - if (!text.equals(original)) { - patched.add("RESOURCE.CFG (fixed paths)"); - zos.write(text.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1)); - } else { - zos.write(content); - } - } else { - // For all other files, check if we need to add INTERP.ERR(C) copies - zis.transferTo(zos); - } - zos.closeEntry(); - zis.closeEntry(); - } - - // Second pass: scan for INTERP files in subdirectories - // We need to re-read the zip for this. Use a clean approach. - } - - // If RESOURCE.CFG was not patched, check for INTERP.ERR and add it - boolean needsInterpFix = false; - String interpSource = null; - - // Re-scan the original bundle for INTERP files in subdirs - try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath))) { - java.util.zip.ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - String name = entry.getName(); - if (!name.startsWith(".jsdos/") && name.contains("/") && - (name.endsWith("/INTERP.ERR") || name.endsWith("/INTERP.ERRC"))) { - // Found an INTERP file in a subdirectory - String rootName = name.substring(name.lastIndexOf('/') + 1); - interpSource = name; - break; - } - zis.closeEntry(); - } - } - - if (interpSource != null) { - // Check if INTERP file already exists at root in the patched bundle - boolean hasRootInterp = false; - try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(tmpPath))) { - java.util.zip.ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - String name = entry.getName(); - if (name.equals("INTERP.ERR") || name.equals("INTERP.ERRC")) { - hasRootInterp = true; - break; - } - zis.closeEntry(); - } - } - - if (!hasRootInterp) { - // Read the INTERP file from original bundle and append it - byte[] interpData = null; - try (var zis = new java.util.zip.ZipInputStream(Files.newInputStream(bundlePath))) { - java.util.zip.ZipEntry entry; - while ((entry = zis.getNextEntry()) != null) { - if (entry.getName().equals(interpSource)) { - interpData = zis.readAllBytes(); - break; - } - zis.closeEntry(); - } - } - - if (interpData != null) { - // Append to the patched bundle - String rootName = interpSource.substring(interpSource.lastIndexOf('/') + 1); - try (var zis2 = new java.util.zip.ZipInputStream(Files.newInputStream(tmpPath)); - var tmp2 = new java.util.zip.ZipOutputStream(Files.newOutputStream( - tmpPath.resolveSibling(bundlePath.getFileName() + ".patchtmp2")))) { - java.util.zip.ZipEntry e; - while ((e = zis2.getNextEntry()) != null) { - tmp2.putNextEntry(new java.util.zip.ZipEntry(e.getName())); - zis2.transferTo(tmp2); - tmp2.closeEntry(); - zis2.closeEntry(); - } - // Add INTERP file at root - tmp2.putNextEntry(new java.util.zip.ZipEntry(rootName)); - tmp2.write(interpData); - tmp2.closeEntry(); - zis2.close(); - tmp2.close(); - } - Files.delete(tmpPath); - Path tmp2 = tmpPath.resolveSibling(bundlePath.getFileName() + ".patchtmp2"); - Files.move(tmp2, tmpPath); - patched.add(rootName + " (copied from " + interpSource + ")"); - } - } - } - - // If nothing was patched, clean up and return empty - if (patched.isEmpty()) { - Files.deleteIfExists(tmpPath); - return patched; - } - - Files.move(tmpPath, bundlePath, StandardCopyOption.REPLACE_EXISTING); - return patched; - } - public Path getGamesDir() { return gamesDir; } }