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());
|
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
|
// Find main executable
|
||||||
String mainExe = findMainExe(extractDir);
|
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.
|
/** Find mountable CD image files in the extracted game directory.
|
||||||
* Returns relative paths (with forward slashes) sorted alphabetically. */
|
* Returns relative paths (with forward slashes) sorted alphabetically. */
|
||||||
private List<String> findCdImages(Path dir) throws IOException {
|
private List<String> findCdImages(Path dir) throws IOException {
|
||||||
|
|||||||
Reference in New Issue
Block a user