From 633b873fbbd2ab790b764199b9cfa2af3eedc468 Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Tue, 5 May 2026 23:31:16 -0400 Subject: [PATCH 1/2] Fix GetSystemCMD concatenating flags without spaces Every flag appended in GetSystemCMD() was missing a leading space, producing malformed output like "-enable_shadows-shadow_quality 2-aa" instead of "-enable_shadows -shadow_quality 2 -aa". FSO would receive all system flags merged into one unparseable token. The PlayMod call path happened to work by accident because it splits the result on '-' before passing it to CmdLineBuilder, but the output was wrong by contract and would break any caller that used it directly. --- Knossos.NET/Models/GlobalSettings.cs | 50 ++++++++++++++-------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Knossos.NET/Models/GlobalSettings.cs b/Knossos.NET/Models/GlobalSettings.cs index b060e058..7981b818 100644 --- a/Knossos.NET/Models/GlobalSettings.cs +++ b/Knossos.NET/Models/GlobalSettings.cs @@ -954,8 +954,8 @@ public string GetSystemCMD(FsoBuild? build = null) var cmd = string.Empty; if(shadowQuality > 0) { - cmd += "-enable_shadows"; - cmd += "-shadow_quality " + shadowQuality; + cmd += " -enable_shadows"; + cmd += " -shadow_quality " + shadowQuality; } if(aaPreset > 0) { @@ -964,8 +964,8 @@ public string GetSystemCMD(FsoBuild? build = null) var flag_aaPreset = aaPreset - 1; if (build == null || SemanticVersion.Compare(build.version, "21.0.0") >= 0) { - cmd += "-aa"; - cmd += "-aa_preset " + flag_aaPreset; + cmd += " -aa"; + cmd += " -aa_preset " + flag_aaPreset; } else { @@ -973,23 +973,23 @@ public string GetSystemCMD(FsoBuild? build = null) { if (flag_aaPreset <= 2) { - cmd += "-fxaa"; + cmd += " -fxaa"; switch (flag_aaPreset) { - case 0: cmd += "-fxaa_preset 1"; break; - case 1: cmd += "-fxaa_preset 5"; break; - case 2: cmd += "-fxaa_preset 7"; break; + case 0: cmd += " -fxaa_preset 1"; break; + case 1: cmd += " -fxaa_preset 5"; break; + case 2: cmd += " -fxaa_preset 7"; break; } } else { - cmd += "-smaa"; + cmd += " -smaa"; switch (flag_aaPreset) { - case 3: cmd += "-smaa_preset 0"; break; - case 4: cmd += "-smaa_preset 1"; break; - case 5: cmd += "-smaa_preset 2"; break; - case 6: cmd += "-smaa_preset 3"; break; + case 3: cmd += " -smaa_preset 0"; break; + case 4: cmd += " -smaa_preset 1"; break; + case 5: cmd += " -smaa_preset 2"; break; + case 6: cmd += " -smaa_preset 3"; break; } } } @@ -999,47 +999,47 @@ public string GetSystemCMD(FsoBuild? build = null) { switch (msaaPreset) { - case 1: cmd += "-msaa 4"; break; - case 2: cmd += "-msaa 8"; break; + case 1: cmd += " -msaa 4"; break; + case 2: cmd += " -msaa 8"; break; } } if (enableSoftParticles) { - cmd += "-soft_particles"; + cmd += " -soft_particles"; } if (!enableDeferredLighting) { - cmd += "-no_deferred"; + cmd += " -no_deferred"; } switch (windowMode) { - case 0: cmd += "-window"; break; - case 1: cmd += "-fullscreen_window"; break; + case 0: cmd += " -window"; break; + case 1: cmd += " -fullscreen_window"; break; case 2: break; //fullscreen } if (!vsync) { - cmd += "-no_vsync"; + cmd += " -no_vsync"; } if(!postProcess) { - cmd += "-no_post_process"; + cmd += " -no_post_process"; } if (noFpsCapping) { - cmd += "-no_fps_capping"; + cmd += " -no_fps_capping"; } if(showFps) { - cmd += "-fps"; + cmd += " -fps"; } if(disableAudio) { - cmd += "-nosound"; + cmd += " -nosound"; } if(disableMusic) { - cmd += "-nomusic"; + cmd += " -nomusic"; } return cmd; } From ac397ad7eff529bdd4e3eb58e322a7e14ce62cac Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Thu, 7 May 2026 21:46:25 -0400 Subject: [PATCH 2/2] more robust splitting of command-line flags --- Knossos.NET/Classes/KnUtils.cs | 15 ++++++++++++++- Knossos.NET/Classes/Knossos.cs | 6 +++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Knossos.NET/Classes/KnUtils.cs b/Knossos.NET/Classes/KnUtils.cs index 175c047e..5840773c 100644 --- a/Knossos.NET/Classes/KnUtils.cs +++ b/Knossos.NET/Classes/KnUtils.cs @@ -592,6 +592,19 @@ public static void ForEach(this IEnumerable enumerable, Action action) } } + /// + /// Splits a cmdline string into individual flag arguments. Splits on a '-' that is + /// preceded by start-of-string or whitespace, so hyphens inside flag values (e.g. paths) + /// are preserved. + /// + /// + /// array of flag arguments (without the leading '-'), or null if input is null + public static string[]? SplitCmdLineFlags(string? cmdline) + { + if (cmdline == null) return null; + return Regex.Split(cmdline, @"(?<=^|\s)-"); + } + /// /// Adds arguments to a cmdline string, only if they arent already present /// @@ -605,7 +618,7 @@ public static string CmdLineBuilder(string cmdline, string[]? args) if (args != null && args.Any()) { var addedArgs = new List(); - foreach (var arg in cmdline.ToLower().Split('-')) + foreach (var arg in SplitCmdLineFlags(cmdline.ToLower()) ?? Array.Empty()) { addedArgs.Add(arg.Split(' ')[0].Trim()); } diff --git a/Knossos.NET/Classes/Knossos.cs b/Knossos.NET/Classes/Knossos.cs index 1559187a..9ec78188 100644 --- a/Knossos.NET/Classes/Knossos.cs +++ b/Knossos.NET/Classes/Knossos.cs @@ -1358,9 +1358,9 @@ public static async void PlayMod(Mod mod, FsoExecType fsoExecType, bool standalo } /* Build the cmdline, take in consideration systemcmd, globalcmd, modcmd(with user changes if any) */ - var modCmd = mod.GetModCmdLine()?.Split('-').ToList(); - var systemCmd = Knossos.globalSettings.GetSystemCMD(fsoBuild)?.Split('-'); - var globalCmd = Knossos.globalSettings.globalCmdLine?.Split('-'); + var modCmd = KnUtils.SplitCmdLineFlags(mod.GetModCmdLine())?.ToList(); + var systemCmd = KnUtils.SplitCmdLineFlags(Knossos.globalSettings.GetSystemCMD(fsoBuild)); + var globalCmd = KnUtils.SplitCmdLineFlags(Knossos.globalSettings.globalCmdLine); if(!standaloneServer) {