From 72fbadb24ea97be989e8c187e782da94819f0095 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Thu, 11 Jun 2026 12:51:45 +0200 Subject: [PATCH] fix: Blood setup crash caused by Windows NE executable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs: 1. PlatformDetector buffer was 512 bytes — too small to read the NE header at offset 0x0E00 in Blood's SETUP.EXE. Increased to 4096 bytes (0x1000), covering headers up to ~4KB. 2. findSetup() had no platform awareness — it picked SETUP.EXE (Windows 3.x NE executable) over SETMAIN.EXE (actual DOS4GW setup). Added platform detection to the sort, preferring DOS executables over Windows ones. Also added "setmain" to pattern list so Build engine games' DOS setup utilities are detected. --- src/main/java/org/dostalgia/ExecutableDetector.java | 12 ++++++++---- src/main/java/org/dostalgia/PlatformDetector.java | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/dostalgia/ExecutableDetector.java b/src/main/java/org/dostalgia/ExecutableDetector.java index f8f2fee..b6cf0b5 100644 --- a/src/main/java/org/dostalgia/ExecutableDetector.java +++ b/src/main/java/org/dostalgia/ExecutableDetector.java @@ -82,9 +82,9 @@ public class ExecutableDetector { } public String findSetup(Path dir) throws IOException { - record Candidate(int depth, long size, String path) {} + record Candidate(int depth, boolean isWindows, long size, String path) {} List candidates = new ArrayList<>(); - List patterns = List.of("setup", "install", "config", "custom"); + List patterns = List.of("setup", "setmain", "install", "config", "custom"); Files.walkFileTree(dir, new SimpleFileVisitor<>() { @Override @@ -95,8 +95,9 @@ public class ExecutableDetector { return FileVisitResult.CONTINUE; for (String pat : patterns) { if (stem.equals(pat) || stem.startsWith(pat + ".") || stem.startsWith(pat + "-")) { + boolean isWin = "windows".equals(platform.detect(f)); candidates.add(new Candidate( - f.getNameCount() - dir.getNameCount(), a.size(), f.toString())); + f.getNameCount() - dir.getNameCount(), isWin, a.size(), f.toString())); break; } } @@ -105,7 +106,10 @@ public class ExecutableDetector { }); if (candidates.isEmpty()) return null; - candidates.sort(Comparator.comparingInt(Candidate::depth).thenComparingLong(Candidate::size)); + candidates.sort(Comparator + .comparingInt(c -> c.isWindows() ? 1 : 0) // prefer DOS over Windows + .thenComparingInt(Candidate::depth) + .thenComparingLong(Candidate::size)); return candidates.getFirst().path(); } diff --git a/src/main/java/org/dostalgia/PlatformDetector.java b/src/main/java/org/dostalgia/PlatformDetector.java index 9bf69be..4366dc6 100644 --- a/src/main/java/org/dostalgia/PlatformDetector.java +++ b/src/main/java/org/dostalgia/PlatformDetector.java @@ -30,7 +30,7 @@ public class PlatformDetector { /** Read enough PE header bytes from any InputStream (shared by Path and ZIP callers). */ static byte[] readHeaderBytes(InputStream is) throws IOException { - byte[] buf = new byte[0x200]; + byte[] buf = new byte[0x1000]; int read = is.readNBytes(buf, 0, buf.length); return read < buf.length ? java.util.Arrays.copyOf(buf, read) : buf; }