clean: remove all Doom-specific logic, fix path separator in jsdos.json
Build & Deploy / build-and-deploy (push) Successful in 1m5s
Build & Deploy / build-and-deploy (push) Successful in 1m5s
Removed:
- injectDoomConfig() — WAD-detection and WASD config injection
- buildDoomDefaultCfg() — Doom config file generator
- All calls to injectDoomConfig in both bundle paths
Fixed:
- buildJsdosJson() now also uses splitPath() helper to handle
backslash separators (was using lastIndexOf('/') only)
- Extracted shared splitPath() method used by both
buildJsdosJson and buildDosboxConf
No more game-specific hacks. Just clean config generation.
This commit is contained in:
@@ -83,14 +83,11 @@ public class UploadResource {
|
|||||||
if ("sockdrive".equals(bundleType)) {
|
if ("sockdrive".equals(bundleType)) {
|
||||||
// Copy files loose
|
// Copy files loose
|
||||||
copyDir(extractDir, gameDir);
|
copyDir(extractDir, gameDir);
|
||||||
// Auto-inject WASD config for Doom-engine games
|
// Write js-dos config
|
||||||
injectDoomConfig(extractDir, gameDir);
|
|
||||||
// Write dosbox.conf (full config, not just autoexec)
|
|
||||||
Path jsdos = gameDir.resolve(".jsdos");
|
Path jsdos = gameDir.resolve(".jsdos");
|
||||||
Files.createDirectories(jsdos);
|
Files.createDirectories(jsdos);
|
||||||
String relExe = extractDir.relativize(Path.of(mainExe)).toString().replace('/', '\\');
|
String relExe = extractDir.relativize(Path.of(mainExe)).toString().replace('/', '\\');
|
||||||
String conf = buildDosboxConf(relExe);
|
Files.writeString(jsdos.resolve("dosbox.conf"), buildDosboxConf(relExe));
|
||||||
Files.writeString(jsdos.resolve("dosbox.conf"), conf);
|
|
||||||
Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe));
|
Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe));
|
||||||
bundleFile = ".jsdos/dosbox.conf";
|
bundleFile = ".jsdos/dosbox.conf";
|
||||||
} else {
|
} else {
|
||||||
@@ -210,15 +207,12 @@ public class UploadResource {
|
|||||||
Path tmpBundle = Files.createTempDirectory("dostalgia-bundle-");
|
Path tmpBundle = Files.createTempDirectory("dostalgia-bundle-");
|
||||||
try {
|
try {
|
||||||
copyDir(extractDir, tmpBundle);
|
copyDir(extractDir, tmpBundle);
|
||||||
// Auto-inject WASD config for Doom-engine games
|
|
||||||
injectDoomConfig(extractDir, tmpBundle);
|
|
||||||
|
|
||||||
// Create .jsdos config (full config, not just autoexec)
|
// Create .jsdos config
|
||||||
Path jsdos = tmpBundle.resolve(".jsdos");
|
Path jsdos = tmpBundle.resolve(".jsdos");
|
||||||
Files.createDirectories(jsdos);
|
Files.createDirectories(jsdos);
|
||||||
String relExe = extractDir.relativize(Path.of(mainExe)).toString().replace('/', '\\');
|
String relExe = extractDir.relativize(Path.of(mainExe)).toString().replace('/', '\\');
|
||||||
String conf = buildDosboxConf(relExe);
|
Files.writeString(jsdos.resolve("dosbox.conf"), buildDosboxConf(relExe));
|
||||||
Files.writeString(jsdos.resolve("dosbox.conf"), conf);
|
|
||||||
Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe));
|
Files.write(jsdos.resolve("jsdos.json"), buildJsdosJson(relExe));
|
||||||
|
|
||||||
// ZIP it up
|
// ZIP it up
|
||||||
@@ -239,23 +233,11 @@ public class UploadResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── File Utilities ──────────────────────────────────────────
|
// ─── Configuration Helpers ───────────────────────────────────
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a minimal dosbox.conf with the critical settings for js-dos v8.
|
|
||||||
* The key setting is usescancodes=true — without it DOSBox doesn't
|
|
||||||
* translate physical key presses into game input.
|
|
||||||
*/
|
|
||||||
private byte[] buildJsdosJson(String relExe) {
|
private byte[] buildJsdosJson(String relExe) {
|
||||||
// Split into directory and executable components for subdirectory support
|
String parts[] = splitPath(relExe);
|
||||||
String dir = "";
|
String script = (parts[0].isEmpty() ? "" : "cd " + parts[0] + " && ") + parts[1];
|
||||||
String exe = relExe;
|
|
||||||
int idx = relExe.lastIndexOf('/');
|
|
||||||
if (idx >= 0) {
|
|
||||||
dir = relExe.substring(0, idx);
|
|
||||||
exe = relExe.substring(idx + 1);
|
|
||||||
}
|
|
||||||
String script = (dir.isEmpty() ? "" : "cd " + dir + " && ") + exe;
|
|
||||||
String json = "{"
|
String json = "{"
|
||||||
+ "\"autoexec\":{"
|
+ "\"autoexec\":{"
|
||||||
+ "\"options\":{\"script\":{\"value\":\"" + escapeJson(script) + "\"}}"
|
+ "\"options\":{\"script\":{\"value\":\"" + escapeJson(script) + "\"}}"
|
||||||
@@ -266,19 +248,10 @@ public class UploadResource {
|
|||||||
return json.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
return json.getBytes(java.nio.charset.StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String escapeJson(String s) {
|
|
||||||
return s.replace("\\", "\\\\").replace("\"", "\\\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildDosboxConf(String relExe) {
|
private String buildDosboxConf(String relExe) {
|
||||||
// Split into directory and executable components for subdirectory support
|
String parts[] = splitPath(relExe);
|
||||||
String dir = "";
|
String dir = parts[0];
|
||||||
String exe = relExe;
|
String exe = parts[1];
|
||||||
int idx = Math.max(relExe.lastIndexOf('/'), relExe.lastIndexOf('\\'));
|
|
||||||
if (idx >= 0) {
|
|
||||||
dir = relExe.substring(0, idx);
|
|
||||||
exe = relExe.substring(idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return "[sdl]\n"
|
return "[sdl]\n"
|
||||||
+ "autolock=true\n"
|
+ "autolock=true\n"
|
||||||
@@ -314,80 +287,24 @@ public class UploadResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detect Doom-engine games and inject a DEFAULT.CFG with WASD controls.
|
* Split a DOS path into directory and filename parts.
|
||||||
* Searches recursively for DOOM.WAD / DOOM2.WAD in source, then writes
|
* Handles both backslash and forward-slash separators.
|
||||||
* config files to the destination root (where the game will look for them).
|
* Returns [dir, exe] where dir is empty for root-level files.
|
||||||
*/
|
*/
|
||||||
private void injectDoomConfig(Path srcDir, Path dstDir) throws IOException {
|
private String[] splitPath(String path) {
|
||||||
boolean hasDoom = false;
|
int idx = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
|
||||||
try (var walk = Files.walk(srcDir)) {
|
if (idx >= 0) {
|
||||||
hasDoom = walk.anyMatch(p -> {
|
return new String[]{path.substring(0, idx), path.substring(idx + 1)};
|
||||||
String name = p.getFileName().toString().toUpperCase();
|
|
||||||
return name.equals("DOOM.WAD") || name.equals("DOOM2.WAD");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if (!hasDoom) {
|
return new String[]{"", path};
|
||||||
LOG.info("No Doom WAD found in upload");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
LOG.info("Doom detected — injecting WASD config");
|
|
||||||
byte[] cfg = buildDoomDefaultCfg();
|
|
||||||
Files.write(dstDir.resolve("DEFAULT.CFG"), cfg);
|
|
||||||
// Doom II also reads DOOM2.CFG (game-specific, takes priority over DEFAULT)
|
|
||||||
Files.write(dstDir.resolve("DOOM2.CFG"), cfg);
|
|
||||||
LOG.info("Injected DEFAULT.CFG + DOOM2.CFG with WASD controls");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private String escapeJson(String s) {
|
||||||
* Build a DEFAULT.CFG (Doom engine config) with WASD controls.
|
return s.replace("\\", "\\\\").replace("\"", "\\\"");
|
||||||
* Only called when a DOOM.WAD or DOOM2.WAD is detected in the upload.
|
|
||||||
*
|
|
||||||
* Key bindings:
|
|
||||||
* W=forward, S=backward, A=strafe left, D=strafe right
|
|
||||||
* Arrows=turn, Ctrl=fire, Space=use, Alt=strafe, Shift=run
|
|
||||||
* Mouse enabled for looking
|
|
||||||
*/
|
|
||||||
private byte[] buildDoomDefaultCfg() {
|
|
||||||
// Use CRLF (\r\n) line endings — Doom's config parser uses fgets()
|
|
||||||
// which includes \r in the buffer on DOS. Missing \r can cause parsing issues.
|
|
||||||
String CRLF = "\r\n";
|
|
||||||
String cfg = ""
|
|
||||||
+ "mouse_sensitivity\t\t5" + CRLF
|
|
||||||
+ "sfx_volume\t\t8" + CRLF
|
|
||||||
+ "music_volume\t\t8" + CRLF
|
|
||||||
+ "show_messages\t\t1" + CRLF
|
|
||||||
+ "key_right\t\t77" + CRLF // Right arrow — turn right
|
|
||||||
+ "key_left\t\t75" + CRLF // Left arrow — turn left
|
|
||||||
+ "key_up\t\t17" + CRLF // W — forward
|
|
||||||
+ "key_down\t\t31" + CRLF // S — backward
|
|
||||||
+ "key_strafeleft\t\t30" + CRLF // A — strafe left
|
|
||||||
+ "key_straferight\t\t32" + CRLF // D — strafe right
|
|
||||||
+ "key_fire\t\t29" + CRLF // Ctrl — fire
|
|
||||||
+ "key_use\t\t57" + CRLF // Space — use/open
|
|
||||||
+ "key_strafe\t\t56" + CRLF // Alt — strafe (hold)
|
|
||||||
+ "key_speed\t\t54" + CRLF // Shift — run
|
|
||||||
+ "use_mouse\t\t1" + CRLF
|
|
||||||
+ "mouseb_fire\t\t0" + CRLF
|
|
||||||
+ "mouseb_strafe\t\t1" + CRLF
|
|
||||||
+ "mouseb_forward\t\t2" + CRLF
|
|
||||||
+ "use_joystick\t\t0" + CRLF
|
|
||||||
+ "joyb_fire\t\t0" + CRLF
|
|
||||||
+ "joyb_strafe\t\t1" + CRLF
|
|
||||||
+ "joyb_use\t\t3" + CRLF
|
|
||||||
+ "joyb_speed\t\t2" + CRLF
|
|
||||||
+ "screenblocks\t\t10" + CRLF
|
|
||||||
+ "detaillevel\t\t0" + CRLF
|
|
||||||
+ "showmessages\t\t1" + CRLF
|
|
||||||
+ "comport\t\t1" + CRLF
|
|
||||||
+ "snd_channels\t\t3" + CRLF
|
|
||||||
+ "snd_musicdevice\t\t3" + CRLF
|
|
||||||
+ "snd_sfxdevice\t\t3" + CRLF
|
|
||||||
+ "snd_sbport\t\t544" + CRLF
|
|
||||||
+ "snd_sbirq\t\t7" + CRLF
|
|
||||||
+ "snd_sbdma\t\t1" + CRLF;
|
|
||||||
return cfg.getBytes(java.nio.charset.StandardCharsets.US_ASCII);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── File Utilities ──────────────────────────────────────────
|
||||||
|
|
||||||
private double dirSizeMB(Path dir) throws IOException {
|
private double dirSizeMB(Path dir) throws IOException {
|
||||||
long[] total = {0};
|
long[] total = {0};
|
||||||
Files.walkFileTree(dir, new SimpleFileVisitor<>() {
|
Files.walkFileTree(dir, new SimpleFileVisitor<>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user