feat: patch hardcoded absolute DOS paths in game configs during upload
Build & Deploy / build-and-deploy (push) Successful in 1m41s
Build & Deploy / build-and-deploy (push) Successful in 1m41s
Adds fixAbsoluteConfigPaths() which runs after flattening and cue fixing during game upload. Detects known config files (FALLOUT.CFG, etc.) with hardcoded C:\dir\ paths and rewrites them to .\ relative paths, so games like Fallout can find their DAT files after flattening moves everything to the bundle root. Uses byte-level replacement to preserve original CRLF line endings and encoding. Extensible via CONFIG_PATH_FIXES map — add new entries for other games with the same problem.
This commit is contained in:
@@ -87,6 +87,15 @@ public class UploadResource {
|
||||
LOG.warning("Failed to fix cue references: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Patch game config files with hardcoded absolute paths
|
||||
// Some games (Fallout, etc.) have FALLOUT.CFG with C:\dir\ paths
|
||||
// that break after flattening moves files to root.
|
||||
try {
|
||||
fixAbsoluteConfigPaths(extractDir);
|
||||
} catch (Exception e) {
|
||||
LOG.warning("Failed to patch config paths: " + e.getMessage());
|
||||
}
|
||||
|
||||
// Find main executable
|
||||
String mainExe = findMainExe(extractDir);
|
||||
|
||||
@@ -471,6 +480,74 @@ public class UploadResource {
|
||||
}
|
||||
}
|
||||
|
||||
/** Known game config files that may have hardcoded absolute DOS paths.
|
||||
* Key = filename pattern (lowercase), Value = list of path prefixes to
|
||||
* replace with ".\\" (relative to the game root). */
|
||||
private static final java.util.Map<String, java.util.List<String>> CONFIG_PATH_FIXES =
|
||||
java.util.Map.of(
|
||||
"fallout.cfg", java.util.List.of("c:\\fallout1\\", "c:\\fallout2\\", "c:\\fallout\\")
|
||||
);
|
||||
|
||||
/**
|
||||
* Patch known game config files that contain hardcoded absolute DOS paths
|
||||
* like {@code master_dat=C:\fallout1\master.dat}. After flattening moves
|
||||
* everything to the bundle root, these paths break. Rewrites them to
|
||||
* relative {@code .\master.dat} instead.
|
||||
*/
|
||||
private static void fixAbsoluteConfigPaths(Path extractDir) throws IOException {
|
||||
try (var walk = Files.walk(extractDir)) {
|
||||
walk.filter(Files::isRegularFile).forEach(f -> {
|
||||
String name = f.getFileName().toString().toLowerCase();
|
||||
var prefixes = CONFIG_PATH_FIXES.get(name);
|
||||
if (prefixes == null) return;
|
||||
try {
|
||||
byte[] data = Files.readAllBytes(f);
|
||||
byte[] original = data.clone();
|
||||
for (String prefix : prefixes) {
|
||||
// Replace both "C:\dir\" and "c:\dir\" patterns
|
||||
byte[] pBytes = prefix.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
byte[] pSlash = prefix.replace('\\', '/')
|
||||
.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
byte[] rel = ".\\".getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
byte[] relSlash = "./"
|
||||
.getBytes(java.nio.charset.StandardCharsets.ISO_8859_1);
|
||||
data = replaceBytes(data, pBytes, rel);
|
||||
data = replaceBytes(data, pSlash, relSlash);
|
||||
}
|
||||
if (!java.util.Arrays.equals(data, original)) {
|
||||
Files.write(f, data);
|
||||
LOG.info("Patched absolute paths in " + f.getFileName());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LOG.warning("Failed to patch " + f.getFileName() + ": " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/** Simple byte-level search-and-replace (preserves CRLF, encoding, etc.). */
|
||||
private static byte[] replaceBytes(byte[] src, byte[] search, byte[] replacement) {
|
||||
if (search.length == 0) return src;
|
||||
java.util.ArrayList<Byte> result = new java.util.ArrayList<>(src.length);
|
||||
int i = 0;
|
||||
while (i <= src.length - search.length) {
|
||||
boolean match = true;
|
||||
for (int j = 0; j < search.length; j++) {
|
||||
if (src[i + j] != search[j]) { match = false; break; }
|
||||
}
|
||||
if (match) {
|
||||
for (byte b : replacement) result.add(b);
|
||||
i += search.length;
|
||||
} else {
|
||||
result.add(src[i++]);
|
||||
}
|
||||
}
|
||||
while (i < src.length) result.add(src[i++]);
|
||||
byte[] out = new byte[result.size()];
|
||||
for (int k = 0; k < out.length; k++) out[k] = result.get(k);
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Find mountable CD image files in the extracted game directory.
|
||||
* Returns relative paths (with forward slashes) sorted alphabetically. */
|
||||
private List<String> findCdImages(Path dir) throws IOException {
|
||||
|
||||
Reference in New Issue
Block a user