From 87fc154490da6a35f70a584024c942dc25210b80 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sun, 23 Jul 2023 20:03:20 -0700 Subject: [PATCH 01/40] Update WineSettings to accept folder & url * WineStartupType (enum) -> IsManagedWine (bool) --- .../Components/MainPage/MainPage.cs | 2 +- .../SettingsPage/Tabs/SettingsTabWine.cs | 8 ++++---- .../Configuration/ILauncherConfig.cs | 2 +- src/XIVLauncher.Core/Program.cs | 15 ++++++++++----- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs index dcd0f9f8..8fc6af32 100644 --- a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs +++ b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs @@ -738,7 +738,7 @@ public async Task StartGameAndAddon(Launcher.LoginResult loginResult, b } else if (Environment.OSVersion.Platform == PlatformID.Unix) { - if (App.Settings.WineStartupType == WineStartupType.Custom) + if (!App.Settings.IsManagedWine ?? true) { if (App.Settings.WineBinaryPath == null) throw new Exception("Custom wine binary path wasn't set."); diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 435006e3..6801a0d5 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -8,20 +8,20 @@ namespace XIVLauncher.Core.Components.SettingsPage.Tabs; public class SettingsTabWine : SettingsTab { - private SettingsEntry startupTypeSetting; + private SettingsEntry isManagedSetting; public SettingsTabWine() { Entries = new SettingsEntry[] { - startupTypeSetting = new SettingsEntry("Wine Version", "Choose how XIVLauncher will start and manage your wine installation.", - () => Program.Config.WineStartupType ?? WineStartupType.Managed, x => Program.Config.WineStartupType = x), + isManagedSetting = new SettingsEntry("Use Managed Wine", "Uncheck to use a custom wine path", + () => Program.Config.IsManagedWine ?? true, b => Program.Config.IsManagedWine = b), new SettingsEntry("Wine Binary Path", "Set the path XIVLauncher will use to run applications via wine.\nIt should be an absolute path to a folder containing wine64 and wineserver binaries.", () => Program.Config.WineBinaryPath, s => Program.Config.WineBinaryPath = s) { - CheckVisibility = () => startupTypeSetting.Value == WineStartupType.Custom + CheckVisibility = () => !isManagedSetting.Value }, new SettingsEntry("Enable Feral's GameMode", "Enable launching with Feral Interactive's GameMode CPU optimizations.", () => Program.Config.GameModeEnabled ?? true, b => Program.Config.GameModeEnabled = b) diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index c7e72e02..0134c108 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -62,7 +62,7 @@ public interface ILauncherConfig #region Linux - public WineStartupType? WineStartupType { get; set; } + public bool? IsManagedWine { get; set; } public string? WineBinaryPath { get; set; } diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 4a689730..3dc3e171 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -120,7 +120,7 @@ private static void LoadConfig(Storage storage) Config.FSyncEnabled ??= false; Config.SetWin7 ??= true; - Config.WineStartupType ??= WineStartupType.Managed; + Config.IsManagedWine ??= true; Config.WineBinaryPath ??= "/usr/bin"; Config.WineDebugVars ??= "-all"; @@ -317,12 +317,17 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { + var managedFolder = ""; + var downloadUrl = ""; + if (Config.IsManagedWine ?? true) + { + managedFolder = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; + downloadUrl = "https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-ubuntu-7.10.r3.g560db77d.tar.xz"; + } var wineLogFile = new FileInfo(Path.Combine(storage.GetFolder("logs").FullName, "wine.log")); var winePrefix = storage.GetFolder("wineprefix"); - var wineSettings = new WineSettings(Config.WineStartupType, Config.WineBinaryPath, Config.WineDebugVars, wineLogFile, winePrefix, Config.ESyncEnabled, Config.FSyncEnabled); + var wineSettings = new WineSettings(Config.IsManagedWine ?? true, Config.WineBinaryPath, managedFolder, downloadUrl, storage.Root.FullName, Config.WineDebugVars, wineLogFile, winePrefix, Config.ESyncEnabled, Config.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); - Directory.CreateDirectory(Path.Combine(toolsFolder.FullName, "dxvk")); - Directory.CreateDirectory(Path.Combine(toolsFolder.FullName, "beta")); CompatibilityTools = new CompatibilityTools(wineSettings, Config.DxvkHudType, Config.GameModeEnabled, Config.DxvkAsyncEnabled, toolsFolder); } @@ -411,7 +416,7 @@ public static void ClearPlugins(bool tsbutton = false) public static void ClearTools(bool tsbutton = false) { storage.GetFolder("compatibilitytool").Delete(true); - storage.GetFolder("compatibilitytool/beta"); + storage.GetFolder("compatibilitytool/wine"); storage.GetFolder("compatibilitytool/dxvk"); if (tsbutton) CreateCompatToolsInstance(); } From 8481dcff9b37504abdea6915a58d30504d70079c Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sun, 23 Jul 2023 20:46:01 -0700 Subject: [PATCH 02/40] Finish work on WineSettings --- lib/FFXIVQuickLauncher | 2 +- .../Components/MainPage/MainPage.cs | 3 +- .../SettingsPage/Tabs/SettingsTabWine.cs | 14 ++- .../Configuration/ILauncherConfig.cs | 5 +- src/XIVLauncher.Core/Program.cs | 15 +-- .../UnixCompatibility/WineManager.cs | 119 ++++++++++++++++++ 6 files changed, 140 insertions(+), 18 deletions(-) create mode 100644 src/XIVLauncher.Core/UnixCompatibility/WineManager.cs diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 2844c3df..c7668691 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 2844c3df359080755bf4475aff30066c2e5cc29a +Subproject commit c7668691cd7b55aa17876339eb7a2414a29c6f54 diff --git a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs index 8fc6af32..79112ee8 100644 --- a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs +++ b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs @@ -19,6 +19,7 @@ using XIVLauncher.Core.Accounts; using XIVLauncher.Common.Game.Exceptions; using XIVLauncher.Core.Support; +using XIVLauncher.Core.UnixCompatibility; namespace XIVLauncher.Core.Components.MainPage; @@ -738,7 +739,7 @@ public async Task StartGameAndAddon(Launcher.LoginResult loginResult, b } else if (Environment.OSVersion.Platform == PlatformID.Unix) { - if (!App.Settings.IsManagedWine ?? true) + if (App.Settings.WineType.Value == WineType.Custom) { if (App.Settings.WineBinaryPath == null) throw new Exception("Custom wine binary path wasn't set."); diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 6801a0d5..afa38d78 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -3,25 +3,31 @@ using ImGuiNET; using XIVLauncher.Common.Unix.Compatibility; using XIVLauncher.Common.Util; +using XIVLauncher.Core.UnixCompatibility; namespace XIVLauncher.Core.Components.SettingsPage.Tabs; public class SettingsTabWine : SettingsTab { - private SettingsEntry isManagedSetting; + private SettingsEntry wineTypeSetting; public SettingsTabWine() { Entries = new SettingsEntry[] { - isManagedSetting = new SettingsEntry("Use Managed Wine", "Uncheck to use a custom wine path", - () => Program.Config.IsManagedWine ?? true, b => Program.Config.IsManagedWine = b), + wineTypeSetting = new SettingsEntry("Installation Type", "Choose how XIVLauncher will start and manage your game installation.", + () => Program.Config.WineType ?? WineType.Managed, x => Program.Config.WineType = x), + new SettingsEntry("Wine Version", "Choose a patched wine version.", () => Program.Config.WineVersion ?? WineVersion.Wine7_10, x => Program.Config.WineVersion = x) + { + CheckVisibility = () => wineTypeSetting.Value == WineType.Managed + }, + new SettingsEntry("Wine Binary Path", "Set the path XIVLauncher will use to run applications via wine.\nIt should be an absolute path to a folder containing wine64 and wineserver binaries.", () => Program.Config.WineBinaryPath, s => Program.Config.WineBinaryPath = s) { - CheckVisibility = () => !isManagedSetting.Value + CheckVisibility = () => wineTypeSetting.Value == WineType.Custom }, new SettingsEntry("Enable Feral's GameMode", "Enable launching with Feral Interactive's GameMode CPU optimizations.", () => Program.Config.GameModeEnabled ?? true, b => Program.Config.GameModeEnabled = b) diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index 0134c108..8dc02d6f 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -3,6 +3,7 @@ using XIVLauncher.Common.Dalamud; using XIVLauncher.Common.Game.Patch.Acquisition; using XIVLauncher.Common.Unix.Compatibility; +using XIVLauncher.Core.UnixCompatibility; namespace XIVLauncher.Core.Configuration; @@ -62,7 +63,9 @@ public interface ILauncherConfig #region Linux - public bool? IsManagedWine { get; set; } + public WineType? WineType { get; set; } + + public WineVersion? WineVersion { get; set; } public string? WineBinaryPath { get; set; } diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 3dc3e171..ddf04dd3 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -22,6 +22,7 @@ using XIVLauncher.Core.Components.LoadingPage; using XIVLauncher.Core.Configuration; using XIVLauncher.Core.Configuration.Parsers; +using XIVLauncher.Core.UnixCompatibility; namespace XIVLauncher.Core; @@ -120,7 +121,8 @@ private static void LoadConfig(Storage storage) Config.FSyncEnabled ??= false; Config.SetWin7 ??= true; - Config.IsManagedWine ??= true; + Config.WineType ??= WineType.Managed; + Config.WineVersion ??= WineVersion.Wine7_10; Config.WineBinaryPath ??= "/usr/bin"; Config.WineDebugVars ??= "-all"; @@ -317,16 +319,7 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { - var managedFolder = ""; - var downloadUrl = ""; - if (Config.IsManagedWine ?? true) - { - managedFolder = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; - downloadUrl = "https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-ubuntu-7.10.r3.g560db77d.tar.xz"; - } - var wineLogFile = new FileInfo(Path.Combine(storage.GetFolder("logs").FullName, "wine.log")); - var winePrefix = storage.GetFolder("wineprefix"); - var wineSettings = new WineSettings(Config.IsManagedWine ?? true, Config.WineBinaryPath, managedFolder, downloadUrl, storage.Root.FullName, Config.WineDebugVars, wineLogFile, winePrefix, Config.ESyncEnabled, Config.FSyncEnabled); + var wineSettings = WineManager.GetSettings(); var toolsFolder = storage.GetFolder("compatibilitytool"); CompatibilityTools = new CompatibilityTools(wineSettings, Config.DxvkHudType, Config.GameModeEnabled, Config.DxvkAsyncEnabled, toolsFolder); } diff --git a/src/XIVLauncher.Core/UnixCompatibility/WineManager.cs b/src/XIVLauncher.Core/UnixCompatibility/WineManager.cs new file mode 100644 index 00000000..157eb1b0 --- /dev/null +++ b/src/XIVLauncher.Core/UnixCompatibility/WineManager.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Serilog; +using XIVLauncher.Common; +using XIVLauncher.Common.Unix.Compatibility; + +namespace XIVLauncher.Core.UnixCompatibility; + +public enum WineType +{ + [SettingsDescription("Managed by XIVLauncher", "Choose a patched version of wine made specifically for XIVLauncher")] + Managed, + + [SettingsDescription("Custom", "Point XIVLauncher to a custom location containing wine binaries to run the game with.")] + Custom, +} + +public enum WineVersion +{ + [SettingsDescription("Wine-xiv 7.10 (Default)", "A patched version of Wine, based on 7.10. The current default.")] + Wine7_10, + + [SettingsDescription("Wine-xiv 8.5", "A newer patched version of Wine-staging 8.5. May be faster, but less stable.")] + Wine8_5, +} + +public static class WineManager +{ + private static string package = "ubuntu"; + + public static WineSettings GetSettings() + { + var isManaged = true; + var winepath = ""; + var folder = ""; + var url = ""; + var version = Program.Config.WineVersion ?? WineVersion.Wine7_10; + var wineLogFile = new FileInfo(Path.Combine(Program.storage.GetFolder("logs").FullName, "wine.log")); + var winePrefix = Program.storage.GetFolder("wineprefix"); + + switch (Program.Config.WineType ?? WineType.Managed) + { + case WineType.Custom: + winepath = Program.Config.WineBinaryPath ?? "/usr/bin"; + isManaged = false; + break; + + case WineType.Managed: + break; + + default: + throw new ArgumentOutOfRangeException("Bad value for WineType"); + } + + switch (version) + { + case WineVersion.Wine8_5: + folder = "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; + url = $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{package}-8.5.r4.g4211bac7.tar.xz"; + break; + + case WineVersion.Wine7_10: + folder = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; + url = $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{package}-7.10.r3.g560db77d.tar.xz"; + break; + + default: + throw new ArgumentOutOfRangeException("Bad value for WineVersion"); + } + + return new WineSettings(isManaged, winepath, folder, url, Program.storage.Root.FullName, Program.Config.WineDebugVars, wineLogFile, winePrefix, Program.Config.ESyncEnabled, Program.Config.FSyncEnabled); + } + + private static void ParseOSRelease() + { + try + { + if (!File.Exists("/etc/os-release")) + { + package = "ubuntu"; + return; + } + var osRelease = File.ReadAllLines("/etc/os-release"); + var osInfo = new Dictionary(); + foreach (var line in osRelease) + { + var keyValue = line.Split('=', 2); + if (keyValue.Length == 1) + osInfo.Add(keyValue[0], ""); + else + osInfo.Add(keyValue[0], keyValue[1]); + } + + foreach (var kvp in osInfo) + { + if (kvp.Value.ToLower().Contains("fedora")) + package = "fedora"; + if (kvp.Value.ToLower().Contains("tumbleweed")) + package = "fedora"; + if (kvp.Value.ToLower().Contains("ubuntu")) + package = "ubuntu"; + if (kvp.Value.ToLower().Contains("debian")) + package = "ubuntu"; + if (kvp.Value.ToLower().Contains("arch")) + package = "arch"; + } + } + catch (Exception ex) + { + // If there's any kind of error opening the file or even finding it, just go with default. + Log.Error(ex, "There was an error while parsing /etc/os-release"); + package = "ubuntu"; + } + } +} \ No newline at end of file From 7ac10597a4b76c0d162557c25fb44ec76888012e Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sun, 23 Jul 2023 21:51:01 -0700 Subject: [PATCH 03/40] Minimal work to allow DxvkSettings class --- lib/FFXIVQuickLauncher | 2 +- src/XIVLauncher.Core/Program.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index c7668691..23a45a9c 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit c7668691cd7b55aa17876339eb7a2414a29c6f54 +Subproject commit 23a45a9ca7dd79b698b69348bfa3660105277fe8 diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index ddf04dd3..9b9bb5f7 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -319,9 +319,10 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { + var dxvkSettings = new DxvkSettings("dxvk-async-1.10.3", "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz", storage.Root.FullName, Config.DxvkAsyncEnabled, 0, true); var wineSettings = WineManager.GetSettings(); var toolsFolder = storage.GetFolder("compatibilitytool"); - CompatibilityTools = new CompatibilityTools(wineSettings, Config.DxvkHudType, Config.GameModeEnabled, Config.DxvkAsyncEnabled, toolsFolder); + CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.DxvkHudType, Config.GameModeEnabled, toolsFolder); } public static void ShowWindow() From 49f1efce908bb1261424eeffb0d823a798b2e6fd Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Mon, 24 Jul 2023 19:03:08 -0700 Subject: [PATCH 04/40] Minimal work to allow Hud settings --- lib/FFXIVQuickLauncher | 2 +- .../SettingsPage/Tabs/SettingsTabWine.cs | 2 +- .../Configuration/ILauncherConfig.cs | 14 +- src/XIVLauncher.Core/Program.cs | 16 ++- .../UnixCompatibility/Dxvk.cs | 123 ++++++++++++++++++ .../{WineManager.cs => Wine.cs} | 69 +++++----- 6 files changed, 182 insertions(+), 44 deletions(-) create mode 100644 src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs rename src/XIVLauncher.Core/UnixCompatibility/{WineManager.cs => Wine.cs} (57%) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 23a45a9c..c8771871 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 23a45a9ca7dd79b698b69348bfa3660105277fe8 +Subproject commit c87718719745aad02897975aec08e32a3d49945e diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index afa38d78..2402cffc 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -58,7 +58,7 @@ public SettingsTabWine() new SettingsEntry("Set Windows version to 7", "Default for Wine 8.1+ is Windows 10, but this causes issues with some Dalamud plugins. Windows 7 is recommended for now.", () => Program.Config.SetWin7 ?? true, b => Program.Config.SetWin7 = b), - new SettingsEntry("DXVK Overlay", "Configure how much of the DXVK overlay is to be shown.", () => Program.Config.DxvkHudType, type => Program.Config.DxvkHudType = type), + new SettingsEntry("DXVK Overlay", "Configure how much of the DXVK overlay is to be shown.", () => Program.Config.DxvkHud ?? DxvkHud.None, type => Program.Config.DxvkHud = type), new SettingsEntry("WINEDEBUG Variables", "Configure debug logging for wine. Useful for troubleshooting.", () => Program.Config.WineDebugVars ?? string.Empty, s => Program.Config.WineDebugVars = s) }; } diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index 8dc02d6f..ee305534 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -77,7 +77,19 @@ public interface ILauncherConfig public bool? FSyncEnabled { get; set; } - public Dxvk.DxvkHudType DxvkHudType { get; set; } + public DxvkVersion? DxvkVersion { get; set; } + + public int? DxvkFrameRateLimit { get; set; } + + public DxvkHud? DxvkHud { get; set; } + + public string? DxvkHudCustom { get; set; } + + public MangoHud? MangoHud { get; set; } + + public string? MangoHudCustomString { get; set; } + + public string? MangoHudCustomFile { get; set; } public string? WineDebugVars { get; set; } diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 9b9bb5f7..58f734a5 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -116,7 +116,6 @@ private static void LoadConfig(Storage storage) Config.GlobalScale ??= 1.0f; Config.GameModeEnabled ??= false; - Config.DxvkAsyncEnabled ??= true; Config.ESyncEnabled ??= true; Config.FSyncEnabled ??= false; Config.SetWin7 ??= true; @@ -126,6 +125,15 @@ private static void LoadConfig(Storage storage) Config.WineBinaryPath ??= "/usr/bin"; Config.WineDebugVars ??= "-all"; + Config.DxvkVersion ??= DxvkVersion.v1_10_3; + Config.DxvkAsyncEnabled ??= true; + Config.DxvkFrameRateLimit ??= 0; + Config.DxvkHud ??= DxvkHud.None; + Config.DxvkHudCustom ??= "fps,frametimes,gpuload,version"; + Config.MangoHud ??= MangoHud.None; + Config.MangoHudCustomString = "ram,vram,resolution,vulkan_driver,engine_version,wine,frame_timing=0"; + Config.MangoHudCustomFile = Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".config", "MangoHud", "MangoHud.conf"); + Config.FixLDP ??= false; Config.FixIM ??= false; } @@ -319,10 +327,10 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { - var dxvkSettings = new DxvkSettings("dxvk-async-1.10.3", "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz", storage.Root.FullName, Config.DxvkAsyncEnabled, 0, true); - var wineSettings = WineManager.GetSettings(); + var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled); + var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root.FullName, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); - CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.DxvkHudType, Config.GameModeEnabled, toolsFolder); + CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder); } public static void ShowWindow() diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs new file mode 100644 index 00000000..54cebb67 --- /dev/null +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -0,0 +1,123 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Serilog; +using XIVLauncher.Common; +using XIVLauncher.Common.Unix.Compatibility; + +namespace XIVLauncher.Core.UnixCompatibility; + +public static class Dxvk +{ + public static bool Enabled => Program.Config.DxvkVersion != DxvkVersion.Disabled; + + public static string FolderName => Program.Config.DxvkVersion switch + { + DxvkVersion.Disabled => "", + DxvkVersion.v1_10_3 => "dxvk-async-1.10.3", + DxvkVersion.v2_0 => "dxvk-async-2.0", + DxvkVersion.v2_1 => "dxvk-2.1", + DxvkVersion.v2_2 => "dxvk-2.2", + _ => throw new ArgumentOutOfRangeException(), + }; + + public static string DownloadUrl => Program.Config.DxvkVersion switch + { + DxvkVersion.Disabled => "", + DxvkVersion.v1_10_3 => "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz", + DxvkVersion.v2_0 => "https://github.com/Sporif/dxvk-async/releases/download/2.0/dxvk-async-2.0.tar.gz", + DxvkVersion.v2_1 => "https://github.com/doitsujin/dxvk/releases/download/v2.1/dxvk-2.1.tar.gz", + DxvkVersion.v2_2 => "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz", + _ => throw new ArgumentOutOfRangeException(), + }; + + public static int FrameRateLimit => Program.Config.DxvkFrameRateLimit ?? 0; + + public static bool AsyncEnabled => Program.Config.DxvkAsyncEnabled ?? false; + + public static bool DxvkHudEnabled => Program.Config.DxvkHud != DxvkHud.None; + + public static string DxvkHudString => Program.Config.DxvkHud switch + { + DxvkHud.None => "", + DxvkHud.Custom => Program.Config.DxvkHudCustom, + DxvkHud.Default => "1", + DxvkHud.Fps => "fps", + DxvkHud.Full => "full", + _ => throw new ArgumentOutOfRangeException(), + }; + + public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; + + public static bool MangoHudCustomIsFile => Program.Config.MangoHud == MangoHud.CustomFile; + + public static string MangoHudString => Program.Config.MangoHud switch + { + MangoHud.None => "", + MangoHud.Default => "", + MangoHud.Full => "full", + MangoHud.CustomString => Program.Config.MangoHudCustomString, + MangoHud.CustomFile => Program.Config.MangoHudCustomFile, + _ => throw new ArgumentOutOfRangeException(), + }; + +} + +public enum DxvkVersion +{ + [SettingsDescription("1.10.3 (default)", "Current version of 1.10 branch of DXVK.")] + v1_10_3, + + [SettingsDescription("2.0", "Newer version of DXVK. Last version with Async patch")] + v2_0, + + [SettingsDescription("2.1 (No Async)", "Newer version of DXVK, using graphics pipeline library. No Async patch.")] + v2_1, + + [SettingsDescription("2.2 (No Async)", "Newest version of DXVK, using graphics pipeline library. No Async patch.")] + v2_2, + + [SettingsDescription("Disabled", "Disable Dxvk, use WineD3D with OpenGL instead.")] + Disabled, +} + +public enum DxvkHud +{ + [SettingsDescription("None", "Disable DXVK Hud")] + None, + + [SettingsDescription("FPS", "Only show FPS")] + Fps, + + [SettingsDescription("Default", "Equivalent to DXVK_HUD=1")] + Default, + + [SettingsDescription("Custom", "Use a custom DXVK_HUD string")] + Custom, + + [SettingsDescription("Full", "Show everything")] + Full, +} + +public enum MangoHud +{ + [SettingsDescription("None", "Disable MangoHud")] + None, + + [SettingsDescription("Default", "Uses no config file.")] + Default, + + [SettingsDescription("Custom File", "Specify a custom config file")] + CustomFile, + + [SettingsDescription("Custom String", "Specify a config via string")] + CustomString, + + [SettingsDescription("Full", "Show (almost) everything")] + Full, +} + diff --git a/src/XIVLauncher.Core/UnixCompatibility/WineManager.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs similarity index 57% rename from src/XIVLauncher.Core/UnixCompatibility/WineManager.cs rename to src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 157eb1b0..55c387d7 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/WineManager.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -28,55 +28,50 @@ public enum WineVersion Wine8_5, } -public static class WineManager +public static class Wine { private static string package = "ubuntu"; - public static WineSettings GetSettings() + public static bool IsManagedWine => Program.Config.WineType == WineType.Managed; + + public static string CustomWinePath => Program.Config.WineBinaryPath ?? "/usr/bin"; + + public static string FolderName => Program.Config.WineVersion switch { - var isManaged = true; - var winepath = ""; - var folder = ""; - var url = ""; - var version = Program.Config.WineVersion ?? WineVersion.Wine7_10; - var wineLogFile = new FileInfo(Path.Combine(Program.storage.GetFolder("logs").FullName, "wine.log")); - var winePrefix = Program.storage.GetFolder("wineprefix"); - - switch (Program.Config.WineType ?? WineType.Managed) - { - case WineType.Custom: - winepath = Program.Config.WineBinaryPath ?? "/usr/bin"; - isManaged = false; - break; + WineVersion.Wine7_10 => "wine-xiv-staging-fsync-git-7.10.r3.g560db77d", + WineVersion.Wine8_5 => "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7", + _ => throw new ArgumentOutOfRangeException(), + }; - case WineType.Managed: - break; + public static string DownloadUrl => GetDownloadUrl(); - default: - throw new ArgumentOutOfRangeException("Bad value for WineType"); - } + public static string DebugVars => Program.Config.WineDebugVars ?? "-all"; - switch (version) - { - case WineVersion.Wine8_5: - folder = "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; - url = $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{package}-8.5.r4.g4211bac7.tar.xz"; - break; - - case WineVersion.Wine7_10: - folder = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; - url = $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{package}-7.10.r3.g560db77d.tar.xz"; - break; - - default: - throw new ArgumentOutOfRangeException("Bad value for WineVersion"); - } + public static FileInfo LogFile => new FileInfo(Path.Combine(Program.storage.GetFolder("logs").FullName, "wine.log")); - return new WineSettings(isManaged, winepath, folder, url, Program.storage.Root.FullName, Program.Config.WineDebugVars, wineLogFile, winePrefix, Program.Config.ESyncEnabled, Program.Config.FSyncEnabled); + public static DirectoryInfo Prefix => Program.storage.GetFolder("wineprefix"); + + public static bool ESyncEnabled => Program.Config.ESyncEnabled ?? true; + + public static bool FSyncEnabled => Program.Config.FSyncEnabled ?? false; + + private static bool OSReleaseIsParsed = false; + + private static string GetDownloadUrl() + { + if (!OSReleaseIsParsed) + ParseOSRelease(); + return Program.Config.WineVersion switch + { + WineVersion.Wine7_10 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{package}-7.10.r3.g560db77d.tar.xz", + WineVersion.Wine8_5 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{package}-8.5.r4.g4211bac7.tar.xz", + _ => throw new ArgumentOutOfRangeException(), + }; } private static void ParseOSRelease() { + OSReleaseIsParsed = true; try { if (!File.Exists("/etc/os-release")) From fc3b9ff29dda9f1cab7d6d61d0f6f0f96b3233c6 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Mon, 24 Jul 2023 20:10:50 -0700 Subject: [PATCH 05/40] Add DXVK tab to Settings page --- .../Components/MainPage/MainPage.cs | 2 - .../Components/SettingsPage/SettingsPage.cs | 1 + .../Components/SettingsPage/SettingsTab.cs | 5 +- .../SettingsPage/Tabs/SettingsTabDxvk.cs | 103 ++++++++++++++++++ .../SettingsPage/Tabs/SettingsTabWine.cs | 33 +++++- .../Configuration/ILauncherConfig.cs | 2 - src/XIVLauncher.Core/Program.cs | 7 +- .../UnixCompatibility/Dxvk.cs | 8 ++ 8 files changed, 147 insertions(+), 14 deletions(-) create mode 100644 src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs diff --git a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs index 79112ee8..037d2469 100644 --- a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs +++ b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs @@ -757,10 +757,8 @@ public async Task StartGameAndAddon(Launcher.LoginResult loginResult, b var _ = Task.Run(async () => { var tempPath = App.Storage.GetFolder("temp"); - var winver = (App.Settings.SetWin7 ?? true) ? "win7" : "win10"; await Program.CompatibilityTools.EnsureTool(tempPath).ConfigureAwait(false); - Program.CompatibilityTools.RunInPrefix($"winecfg /v {winver}"); var gameFixApply = new GameFixApply(App.Settings.GamePath, App.Settings.GameConfigPath, Program.CompatibilityTools.Settings.Prefix, tempPath); gameFixApply.UpdateProgress += (text, hasProgress, progress) => diff --git a/src/XIVLauncher.Core/Components/SettingsPage/SettingsPage.cs b/src/XIVLauncher.Core/Components/SettingsPage/SettingsPage.cs index cbf9a074..3773a743 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/SettingsPage.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/SettingsPage.cs @@ -11,6 +11,7 @@ public class SettingsPage : Page new SettingsTabGame(), new SettingsTabPatching(), new SettingsTabWine(), + new SettingsTabDxvk(), new SettingsTabDalamud(), new SettingsTabAutoStart(), new SettingsTabAbout(), diff --git a/src/XIVLauncher.Core/Components/SettingsPage/SettingsTab.cs b/src/XIVLauncher.Core/Components/SettingsPage/SettingsTab.cs index e50ebeda..5e86faab 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/SettingsTab.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/SettingsTab.cs @@ -16,9 +16,10 @@ public override void Draw() foreach (SettingsEntry settingsEntry in Entries) { if (settingsEntry.IsVisible) + { settingsEntry.Draw(); - - ImGui.Dummy(new Vector2(10) * ImGuiHelpers.GlobalScale); + ImGui.Dummy(new Vector2(10) * ImGuiHelpers.GlobalScale); + } } base.Draw(); diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs new file mode 100644 index 00000000..850b2c44 --- /dev/null +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -0,0 +1,103 @@ +using System.IO; +using System.Numerics; +using System.Runtime.InteropServices; +using ImGuiNET; +using XIVLauncher.Common.Unix.Compatibility; +using XIVLauncher.Common.Util; +using XIVLauncher.Core.UnixCompatibility; + +namespace XIVLauncher.Core.Components.SettingsPage.Tabs; + +public class SettingsTabDxvk : SettingsTab +{ + private SettingsEntry dxvkVersionSetting; + private SettingsEntry dxvkHudSetting; + private SettingsEntry mangoHudSetting; + + public SettingsTabDxvk() + { + Entries = new SettingsEntry[] + { + dxvkVersionSetting = new SettingsEntry("DXVK Version", "Choose which version of DXVK to use.", () => Program.Config.DxvkVersion ?? DxvkVersion.v1_10_3, type => Program.Config.DxvkVersion = type) + { + CheckWarning = type => + { + if (new [] {DxvkVersion.v2_1, DxvkVersion.v2_2}.Contains(type)) + return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; + return null; + }, + }, + new SettingsEntry("Enable DXVK ASYNC", "Enable DXVK ASYNC patch.", () => Program.Config.DxvkAsyncEnabled ?? true, b => Program.Config.DxvkAsyncEnabled = b) + { + CheckVisibility = () => (new [] {DxvkVersion.v1_10_3, DxvkVersion.v2_0}.Contains(dxvkVersionSetting.Value)), + CheckWarning = b => + { + if (!b && dxvkVersionSetting.Value == DxvkVersion.v2_0) + return "AMD users may need to use env variable RADV_PERFTEST=gpl"; + return null; + }, + }, + dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with Dxvk. It doesn't work if Dxvk is disabled.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) + { + CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, + }, + new SettingsEntry("DXVK Hud Custom String", "Set a custom string for the built in DXVK Hud. Warning: If it's invalid, the game may hang.", () => Program.Config.DxvkHudCustom ?? Dxvk.DXVK_HUD, s => Program.Config.DxvkHudCustom = s) + { + CheckVisibility = () => dxvkHudSetting.Value == DxvkHud.Custom && dxvkVersionSetting.Value != DxvkVersion.Disabled, + CheckWarning = s => + { + if(!DxvkSettings.DxvkHudStringIsValid(s)) + return "That's not a valid hud string"; + return null; + }, + }, + mangoHudSetting = new SettingsEntry("MangoHud Overlay", "MangoHud must be installed separately. Flatpak users need the flatpak version of MangoHud.", () => Program.Config.MangoHud ?? MangoHud.None, x => Program.Config.MangoHud = x) + { + CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckWarning = x => + { + if (dxvkHudSetting.Value != DxvkHud.None && x != MangoHud.None) + return "You probably shouldn't run MangoHud and DxvkHud at the same time."; + return null; + } + }, + new SettingsEntry("MangoHud Custom String", "Set a custom string for MangoHud config.", () => Program.Config.MangoHudCustomString ?? Dxvk.MANGOHUD_CONFIG, s => Program.Config.MangoHudCustomString = s) + { + CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomString && dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckWarning = s => + { + if (s.Contains(' ')) + return "No spaces allowed in MangoHud config"; + return null; + } + }, + new SettingsEntry("MangoHud Custom Path", "Set a custom path for MangoHud config file.", () => Program.Config.MangoHudCustomFile ?? Dxvk.MANGOHUD_CONFIGFILE, s => Program.Config.MangoHudCustomFile = s) + { + CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomFile && dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckWarning = s => + { + if(!File.Exists(s)) + return "That's not a valid file."; + return null; + }, + }, + new NumericSettingsEntry("Frame Rate Limit", "Set a frame rate limit, and DXVK will try not exceed it. Use 0 for unlimited.", () => Program.Config.DxvkFrameRateLimit ?? 0, i => Program.Config.DxvkFrameRateLimit = i, 0, 1000) + { + CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, + }, + }; + } + + public override SettingsEntry[] Entries { get; } + + public override bool IsUnixExclusive => true; + + public override string Title => "DXVK"; + + public override void Save() + { + base.Save(); + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + Program.CreateCompatToolsInstance(); + } +} diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 2402cffc..d404fa76 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -55,10 +55,6 @@ public SettingsTabWine() return null; } }, - - new SettingsEntry("Set Windows version to 7", "Default for Wine 8.1+ is Windows 10, but this causes issues with some Dalamud plugins. Windows 7 is recommended for now.", () => Program.Config.SetWin7 ?? true, b => Program.Config.SetWin7 = b), - - new SettingsEntry("DXVK Overlay", "Configure how much of the DXVK overlay is to be shown.", () => Program.Config.DxvkHud ?? DxvkHud.None, type => Program.Config.DxvkHud = type), new SettingsEntry("WINEDEBUG Variables", "Configure debug logging for wine. Useful for troubleshooting.", () => Program.Config.WineDebugVars ?? string.Empty, s => Program.Config.WineDebugVars = s) }; } @@ -73,6 +69,10 @@ public override void Draw() { base.Draw(); + ImGui.Separator(); + + ImGui.Dummy(new Vector2(10) * ImGuiHelpers.GlobalScale); + if (!Program.CompatibilityTools.IsToolDownloaded) { ImGui.BeginDisabled(); @@ -100,6 +100,31 @@ public override void Draw() Program.CompatibilityTools.RunInPrefix("explorer"); } + ImGui.SameLine(); + + if (ImGui.Button("Open Wine explorer (use WineD3D")) + { + Program.CompatibilityTools.RunInPrefix("explorer", wineD3D: true); + + } + + ImGui.Dummy(new Vector2(10) * ImGuiHelpers.GlobalScale); + + + if (ImGui.Button("Set Wine to Windows 7")) + { + Program.CompatibilityTools.RunInPrefix($"winecfg /v win7", redirectOutput: true, writeLog: true); + } + + ImGui.SameLine(); + + if (ImGui.Button("Set Wine to Windows 10")) + { + Program.CompatibilityTools.RunInPrefix($"winecfg /v win10", redirectOutput: true, writeLog: true); + } + + ImGui.Dummy(new Vector2(10) * ImGuiHelpers.GlobalScale); + if (ImGui.Button("Kill all wine processes")) { Program.CompatibilityTools.Kill(); diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index ee305534..c3bb9b79 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -97,8 +97,6 @@ public interface ILauncherConfig public bool? FixIM { get; set; } - public bool? SetWin7 { get; set; } - #endregion #region Dalamud diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 58f734a5..4ea5b262 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -118,7 +118,6 @@ private static void LoadConfig(Storage storage) Config.GameModeEnabled ??= false; Config.ESyncEnabled ??= true; Config.FSyncEnabled ??= false; - Config.SetWin7 ??= true; Config.WineType ??= WineType.Managed; Config.WineVersion ??= WineVersion.Wine7_10; @@ -129,10 +128,10 @@ private static void LoadConfig(Storage storage) Config.DxvkAsyncEnabled ??= true; Config.DxvkFrameRateLimit ??= 0; Config.DxvkHud ??= DxvkHud.None; - Config.DxvkHudCustom ??= "fps,frametimes,gpuload,version"; + Config.DxvkHudCustom ??= Dxvk.DXVK_HUD; Config.MangoHud ??= MangoHud.None; - Config.MangoHudCustomString = "ram,vram,resolution,vulkan_driver,engine_version,wine,frame_timing=0"; - Config.MangoHudCustomFile = Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".config", "MangoHud", "MangoHud.conf"); + Config.MangoHudCustomString ??= Dxvk.MANGOHUD_CONFIG; + Config.MangoHudCustomFile ??= Dxvk.MANGOHUD_CONFIGFILE; Config.FixLDP ??= false; Config.FixIM ??= false; diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 54cebb67..fa3aca6c 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -51,6 +51,8 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; + public static bool MangoHudInstalled => !string.IsNullOrEmpty(DxvkSettings.GetMangoHudPath()); + public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; public static bool MangoHudCustomIsFile => Program.Config.MangoHud == MangoHud.CustomFile; @@ -65,6 +67,12 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; + public static string DXVK_HUD => "fps,frametimes,gpuload,version"; + + public static string MANGOHUD_CONFIG => "ram,vram,resolution,vulkan_driver,engine_version,wine,frame_timing=0"; + + public static string MANGOHUD_CONFIGFILE => Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".config", "MangoHud", "MangoHud.conf"); + } public enum DxvkVersion From f960f07d73e95ff75faaa8f81778d35340e1e0a0 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Mon, 24 Jul 2023 22:38:45 -0700 Subject: [PATCH 06/40] Tweak Dxvk tab, rework for boolean MangoHud check --- lib/FFXIVQuickLauncher | 2 +- .../Components/SettingsPage/SettingsEntry{T}.cs | 2 +- .../Components/SettingsPage/Tabs/SettingsTabDxvk.cs | 6 +++--- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index c8771871..569c31e1 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit c87718719745aad02897975aec08e32a3d49945e +Subproject commit 569c31e15dfd9cd2e8d93f10cd587e355c19db9e diff --git a/src/XIVLauncher.Core/Components/SettingsPage/SettingsEntry{T}.cs b/src/XIVLauncher.Core/Components/SettingsPage/SettingsEntry{T}.cs index f31527bf..040ac8ef 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/SettingsEntry{T}.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/SettingsEntry{T}.cs @@ -94,7 +94,7 @@ public override void Draw() } ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey); - ImGuiHelpers.TextWrapped(this.Description); + if (!string.IsNullOrWhiteSpace(this.Description)) ImGuiHelpers.TextWrapped(this.Description); ImGui.PopStyleColor(); if (this.CheckValidity != null) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 850b2c44..239b6b8f 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -37,7 +37,7 @@ public SettingsTabDxvk() return null; }, }, - dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with Dxvk. It doesn't work if Dxvk is disabled.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) + dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with Dxvk. MangoHud must be installed separately.\nFlatpak users need the flatpak version of MangoHud.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) { CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, }, @@ -51,13 +51,13 @@ public SettingsTabDxvk() return null; }, }, - mangoHudSetting = new SettingsEntry("MangoHud Overlay", "MangoHud must be installed separately. Flatpak users need the flatpak version of MangoHud.", () => Program.Config.MangoHud ?? MangoHud.None, x => Program.Config.MangoHud = x) + mangoHudSetting = new SettingsEntry("MangoHud Overlay", "MangoHud is installed. It is recommended to set Dxvk Overlay to None if using MangoHud.", () => Program.Config.MangoHud ?? MangoHud.None, x => Program.Config.MangoHud = x) { CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, CheckWarning = x => { if (dxvkHudSetting.Value != DxvkHud.None && x != MangoHud.None) - return "You probably shouldn't run MangoHud and DxvkHud at the same time."; + return "Warning! You can run Dxvk Hud and MangoHud at the same time, but you probably shouldn't.\nSet one of them to None."; return null; } }, diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index fa3aca6c..5e87d8f7 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -51,7 +51,7 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; - public static bool MangoHudInstalled => !string.IsNullOrEmpty(DxvkSettings.GetMangoHudPath()); + public static bool MangoHudInstalled => DxvkSettings.MangoHudInstalled(); public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; From 9b237189c9d0a7db64fe5fccede10693339c6b48 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 25 Jul 2023 20:36:56 -0700 Subject: [PATCH 07/40] Added OSInfo * got rid of #if FLATPAK * got rid of #if WINE_XIV_DISTRO for wine packages * added a few UI tweaks --- lib/FFXIVQuickLauncher | 2 +- .../SettingsPage/Tabs/SettingsTabDebug.cs | 11 +- .../SettingsPage/Tabs/SettingsTabDxvk.cs | 2 +- src/XIVLauncher.Core/OSInfo.cs | 132 ++++++++++++++++++ src/XIVLauncher.Core/Program.cs | 8 +- .../UnixCompatibility/Dxvk.cs | 2 +- .../UnixCompatibility/Wine.cs | 49 +------ 7 files changed, 149 insertions(+), 57 deletions(-) create mode 100644 src/XIVLauncher.Core/OSInfo.cs diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 569c31e1..e6b2a3e6 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 569c31e15dfd9cd2e8d93f10cd587e355c19db9e +Subproject commit e6b2a3e6d6c797cafba121d1bd257c01fd2ec571 diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs index 53225022..6028d6fa 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs @@ -1,5 +1,7 @@ using System.Collections; using ImGuiNET; +using XIVLauncher.Core; +using XIVLauncher.Common; namespace XIVLauncher.Core.Components.SettingsPage.Tabs; @@ -12,7 +14,10 @@ public override void Draw() { ImGui.TextUnformatted("Generic Information"); ImGui.Separator(); - ImGui.TextUnformatted($"Operating System: {Environment.OSVersion}"); + if (OSInfo.Platform == Platform.Linux) + ImGui.TextUnformatted($"Operating System: {OSInfo.Name} - {Environment.OSVersion}"); + else + ImGui.TextUnformatted($"Operating System: {Environment.OSVersion}"); ImGui.TextUnformatted($"Runtime Version: {Environment.Version}"); if (Program.IsSteamDeckHardware) @@ -21,9 +26,9 @@ public override void Draw() if (Program.IsSteamDeckGamingMode) ImGui.Text("Steam Deck Gaming Mode Detected"); -#if FLATPAK + if (OSInfo.IsFlatpak) ImGui.Text("Running as a Flatpak"); -#endif + ImGui.Spacing(); diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 239b6b8f..4141f096 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -46,7 +46,7 @@ public SettingsTabDxvk() CheckVisibility = () => dxvkHudSetting.Value == DxvkHud.Custom && dxvkVersionSetting.Value != DxvkVersion.Disabled, CheckWarning = s => { - if(!DxvkSettings.DxvkHudStringIsValid(s)) + if(!UnixHelpers.DxvkHudStringIsValid(s)) return "That's not a valid hud string"; return null; }, diff --git a/src/XIVLauncher.Core/OSInfo.cs b/src/XIVLauncher.Core/OSInfo.cs new file mode 100644 index 00000000..a8e49118 --- /dev/null +++ b/src/XIVLauncher.Core/OSInfo.cs @@ -0,0 +1,132 @@ +using System.Numerics; +using System.IO; +using System.Collections.Generic; +using XIVLauncher.Common; +using System.Runtime.InteropServices; + +namespace XIVLauncher.Core; + +public enum DistroPackage +{ + ubuntu, + + fedora, + + arch, + + none, +} + +public static class OSInfo +{ + public static DistroPackage Package { get; private set; } + + public static string Name { get; private set; } + + public static bool IsFlatpak { get; private set; } + + public static Platform Platform { get; private set; } + + static OSInfo() + { + var os = System.Environment.OSVersion; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Package = DistroPackage.none; + Name = os.VersionString; + IsFlatpak = false; + Platform = Platform.Win32; + return; + } + + // There's no wine releases for MacOS or FreeBSD, and I'm not sure this will even compile on either + // platform, but here's some code just in case. Can modify this as needed if it's useful in the future. + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + Platform = Platform.Mac; + Name = os.VersionString; + IsFlatpak = false; + Package = DistroPackage.none; + return; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) + { + Platform = Platform.Mac; // Don't have an option for this atm. + Name = os.VersionString; + IsFlatpak = false; + Package = DistroPackage.none; + return; + } + + Platform = Platform.Linux; + try + { + if (!File.Exists("/etc/os-release")) + { + Package = DistroPackage.ubuntu; + Name = "Unknown distribution"; + IsFlatpak = false; + return; + } + var osRelease = File.ReadAllLines("/etc/os-release"); + var osInfo = new Dictionary(); + foreach (var line in osRelease) + { + var keyValue = line.Split('=', 2); + if (keyValue.Length == 1) + osInfo.Add(keyValue[0], ""); + else + osInfo.Add(keyValue[0], keyValue[1]); + } + + var name = (osInfo.ContainsKey("NAME") ? osInfo["NAME"] : "").Trim('"'); + var pretty = (osInfo.ContainsKey("PRETTY_NAME") ? osInfo["PRETTY_NAME"] : "").Trim('"'); + Name = pretty == "" ? (name == "" ? "Unknown distribution" : name) : pretty; + + if (CheckFlatpak(osInfo)) + { + IsFlatpak = true; + Package = DistroPackage.ubuntu; + return; + } + + Package = CheckDistro(osInfo); + IsFlatpak = false; + return; + } + catch + { + // If there's any kind of error opening the file or even finding it, just go with default. + Package = DistroPackage.ubuntu; + Name = "Unknown distribution"; + IsFlatpak = false; + } + } + + private static bool CheckFlatpak(Dictionary osInfo) + { + if (osInfo.ContainsKey("ID")) + if (osInfo["ID"] == "org.freedesktop.platform") + return true; + return false; + } + + private static DistroPackage CheckDistro(Dictionary osInfo) + { + foreach (var kvp in osInfo) + { + if (kvp.Value.ToLower().Contains("fedora")) + return DistroPackage.fedora; + if (kvp.Value.ToLower().Contains("tumbleweed")) + return DistroPackage.fedora; + if (kvp.Value.ToLower().Contains("ubuntu")) + return DistroPackage.ubuntu; + if (kvp.Value.ToLower().Contains("debian")) + return DistroPackage.ubuntu; + if (kvp.Value.ToLower().Contains("arch")) + return DistroPackage.arch; + } + return DistroPackage.ubuntu; + } +} \ No newline at end of file diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 4ea5b262..c19a122d 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -223,6 +223,8 @@ private static void Main(string[] args) CreateCompatToolsInstance(); + Log.Information("Running on {OSName}.{wineInfo}", (OSInfo.IsFlatpak) ? "Linux in a flatpak" : OSInfo.Name, (OSInfo.Platform == Platform.Linux) ? $" Using \"{OSInfo.Package}\" package for managed wine downloads." : string.Empty); + Log.Debug("Creating Veldrid devices..."); #if DEBUG @@ -255,15 +257,13 @@ private static void Main(string[] args) var needUpdate = false; -#if FLATPAK - if (Config.DoVersionCheck ?? false) + if (OSInfo.IsFlatpak && (Config.DoVersionCheck ?? false)) { var versionCheckResult = UpdateCheck.CheckForUpdate().GetAwaiter().GetResult(); if (versionCheckResult.Success) needUpdate = versionCheckResult.NeedUpdate; } -#endif needUpdate = CoreEnvironmentSettings.IsUpgrade ? true : needUpdate; @@ -329,7 +329,7 @@ public static void CreateCompatToolsInstance() var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled); var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root.FullName, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); - CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder); + CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder, OSInfo.IsFlatpak); } public static void ShowWindow() diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 5e87d8f7..c31aa9be 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -51,7 +51,7 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; - public static bool MangoHudInstalled => DxvkSettings.MangoHudInstalled(); + public static bool MangoHudInstalled => UnixHelpers.MangoHudIsInstalled(); public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 55c387d7..1f2e7933 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -30,8 +30,6 @@ public enum WineVersion public static class Wine { - private static string package = "ubuntu"; - public static bool IsManagedWine => Program.Config.WineType == WineType.Managed; public static string CustomWinePath => Program.Config.WineBinaryPath ?? "/usr/bin"; @@ -59,8 +57,8 @@ public static class Wine private static string GetDownloadUrl() { - if (!OSReleaseIsParsed) - ParseOSRelease(); + var package = OSInfo.Package; + return Program.Config.WineVersion switch { WineVersion.Wine7_10 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{package}-7.10.r3.g560db77d.tar.xz", @@ -68,47 +66,4 @@ private static string GetDownloadUrl() _ => throw new ArgumentOutOfRangeException(), }; } - - private static void ParseOSRelease() - { - OSReleaseIsParsed = true; - try - { - if (!File.Exists("/etc/os-release")) - { - package = "ubuntu"; - return; - } - var osRelease = File.ReadAllLines("/etc/os-release"); - var osInfo = new Dictionary(); - foreach (var line in osRelease) - { - var keyValue = line.Split('=', 2); - if (keyValue.Length == 1) - osInfo.Add(keyValue[0], ""); - else - osInfo.Add(keyValue[0], keyValue[1]); - } - - foreach (var kvp in osInfo) - { - if (kvp.Value.ToLower().Contains("fedora")) - package = "fedora"; - if (kvp.Value.ToLower().Contains("tumbleweed")) - package = "fedora"; - if (kvp.Value.ToLower().Contains("ubuntu")) - package = "ubuntu"; - if (kvp.Value.ToLower().Contains("debian")) - package = "ubuntu"; - if (kvp.Value.ToLower().Contains("arch")) - package = "arch"; - } - } - catch (Exception ex) - { - // If there's any kind of error opening the file or even finding it, just go with default. - Log.Error(ex, "There was an error while parsing /etc/os-release"); - package = "ubuntu"; - } - } } \ No newline at end of file From 825fb442c350319bcbd7bff79535022224897ccd Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 25 Jul 2023 20:51:20 -0700 Subject: [PATCH 08/40] Removed unnecessary logging line --- src/XIVLauncher.Core/Program.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index c19a122d..1b3d3b14 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -223,8 +223,6 @@ private static void Main(string[] args) CreateCompatToolsInstance(); - Log.Information("Running on {OSName}.{wineInfo}", (OSInfo.IsFlatpak) ? "Linux in a flatpak" : OSInfo.Name, (OSInfo.Platform == Platform.Linux) ? $" Using \"{OSInfo.Package}\" package for managed wine downloads." : string.Empty); - Log.Debug("Creating Veldrid devices..."); #if DEBUG From a43335172405ecd386cb65b71010733659065667 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 26 Jul 2023 07:53:39 -0700 Subject: [PATCH 09/40] Update submodule --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index e6b2a3e6..16c32f31 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit e6b2a3e6d6c797cafba121d1bd257c01fd2ec571 +Subproject commit 16c32f31dbf3c3be2492a72eda41a190b6008afb From 8c9baac74c1d63f247b16ec0d658ac1a87625c06 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 26 Jul 2023 19:38:08 -0700 Subject: [PATCH 10/40] Format Wine.cs to match Dxvk.cs --- lib/FFXIVQuickLauncher | 2 +- .../UnixCompatibility/Wine.cs | 51 ++++++++----------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 16c32f31..f20b884c 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 16c32f31dbf3c3be2492a72eda41a190b6008afb +Subproject commit f20b884c972d27cce2aeaf3de69fde1fed91f853 diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 1f2e7933..2758b9d3 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -10,24 +10,6 @@ namespace XIVLauncher.Core.UnixCompatibility; -public enum WineType -{ - [SettingsDescription("Managed by XIVLauncher", "Choose a patched version of wine made specifically for XIVLauncher")] - Managed, - - [SettingsDescription("Custom", "Point XIVLauncher to a custom location containing wine binaries to run the game with.")] - Custom, -} - -public enum WineVersion -{ - [SettingsDescription("Wine-xiv 7.10 (Default)", "A patched version of Wine, based on 7.10. The current default.")] - Wine7_10, - - [SettingsDescription("Wine-xiv 8.5", "A newer patched version of Wine-staging 8.5. May be faster, but less stable.")] - Wine8_5, -} - public static class Wine { public static bool IsManagedWine => Program.Config.WineType == WineType.Managed; @@ -41,7 +23,12 @@ public static class Wine _ => throw new ArgumentOutOfRangeException(), }; - public static string DownloadUrl => GetDownloadUrl(); + public static string DownloadUrl =>Program.Config.WineVersion switch + { + WineVersion.Wine7_10 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz", + WineVersion.Wine8_5 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz", + _ => throw new ArgumentOutOfRangeException(), + }; public static string DebugVars => Program.Config.WineDebugVars ?? "-all"; @@ -54,16 +41,22 @@ public static class Wine public static bool FSyncEnabled => Program.Config.FSyncEnabled ?? false; private static bool OSReleaseIsParsed = false; +} - private static string GetDownloadUrl() - { - var package = OSInfo.Package; +public enum WineType +{ + [SettingsDescription("Managed by XIVLauncher", "Choose a patched version of wine made specifically for XIVLauncher")] + Managed, + + [SettingsDescription("Custom", "Point XIVLauncher to a custom location containing wine binaries to run the game with.")] + Custom, +} - return Program.Config.WineVersion switch - { - WineVersion.Wine7_10 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{package}-7.10.r3.g560db77d.tar.xz", - WineVersion.Wine8_5 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{package}-8.5.r4.g4211bac7.tar.xz", - _ => throw new ArgumentOutOfRangeException(), - }; - } +public enum WineVersion +{ + [SettingsDescription("Wine-xiv 7.10 (Default)", "A patched version of Wine, based on 7.10. The current default.")] + Wine7_10, + + [SettingsDescription("Wine-xiv 8.5", "A newer patched version of Wine-staging 8.5. May be faster, but less stable.")] + Wine8_5, } \ No newline at end of file From e99c2acf340405e6bcda25d099d3e7c9d4c5a5af Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 26 Jul 2023 20:22:53 -0700 Subject: [PATCH 11/40] Allow for wow64 wine builds with no wine64 binary --- src/XIVLauncher.Core/Components/MainPage/MainPage.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs index 037d2469..43118b40 100644 --- a/src/XIVLauncher.Core/Components/MainPage/MainPage.cs +++ b/src/XIVLauncher.Core/Components/MainPage/MainPage.cs @@ -746,8 +746,8 @@ public async Task StartGameAndAddon(Launcher.LoginResult loginResult, b else if (!Directory.Exists(App.Settings.WineBinaryPath)) throw new Exception("Custom wine binary path is invalid: no such directory.\n" + "Check path carefully for typos: " + App.Settings.WineBinaryPath); - else if (!File.Exists(Path.Combine(App.Settings.WineBinaryPath,"wine64"))) - throw new Exception("Custom wine binary path is invalid: no wine64 found at that location.\n" + + else if (!File.Exists(Path.Combine(App.Settings.WineBinaryPath, "wine64")) && !File.Exists(Path.Combine(App.Settings.WineBinaryPath, "wine"))) + throw new Exception("Custom wine binary path is invalid: no wine or wine64 found at that location.\n" + "Check path carefully for typos: " + App.Settings.WineBinaryPath); } From 62ae5d0e9cd4fbe2f27462d63fe1b21f379c8521 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 29 Jul 2023 11:31:45 -0700 Subject: [PATCH 12/40] Remove redundant async from Wine tab --- .../Components/SettingsPage/Tabs/SettingsTabWine.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index d404fa76..56747434 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -42,8 +42,8 @@ public SettingsTabWine() } }, - new SettingsEntry("Enable DXVK ASYNC", "Enable DXVK ASYNC patch.", () => Program.Config.DxvkAsyncEnabled ?? true, b => Program.Config.DxvkAsyncEnabled = b), new SettingsEntry("Enable ESync", "Enable eventfd-based synchronization.", () => Program.Config.ESyncEnabled ?? true, b => Program.Config.ESyncEnabled = b), + new SettingsEntry("Enable FSync", "Enable fast user mutex (futex2).", () => Program.Config.FSyncEnabled ?? true, b => Program.Config.FSyncEnabled = b) { CheckVisibility = () => RuntimeInformation.IsOSPlatform(OSPlatform.Linux), @@ -55,6 +55,7 @@ public SettingsTabWine() return null; } }, + new SettingsEntry("WINEDEBUG Variables", "Configure debug logging for wine. Useful for troubleshooting.", () => Program.Config.WineDebugVars ?? string.Empty, s => Program.Config.WineDebugVars = s) }; } From f93f53c4d7a12c91b697dd08a6a402a3385c5e7d Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 29 Jul 2023 21:26:21 -0700 Subject: [PATCH 13/40] Add fix for proton-wine 8 --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index f20b884c..7d21042d 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit f20b884c972d27cce2aeaf3de69fde1fed91f853 +Subproject commit 7d21042d9706b887673020f1e2ec7c09b7d76d7d From 0b1e88ec3262b6bf0da026d5304825fd05eb338e Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 1 Aug 2023 20:10:07 -0700 Subject: [PATCH 14/40] Clean up to match changes in XL.Common.Unix --- .../SettingsPage/Tabs/SettingsTabDxvk.cs | 2 +- src/XIVLauncher.Core/OSInfo.cs | 30 +++++++++---------- src/XIVLauncher.Core/Program.cs | 2 +- .../UnixCompatibility/Dxvk.cs | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 4141f096..239b6b8f 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -46,7 +46,7 @@ public SettingsTabDxvk() CheckVisibility = () => dxvkHudSetting.Value == DxvkHud.Custom && dxvkVersionSetting.Value != DxvkVersion.Disabled, CheckWarning = s => { - if(!UnixHelpers.DxvkHudStringIsValid(s)) + if(!DxvkSettings.DxvkHudStringIsValid(s)) return "That's not a valid hud string"; return null; }, diff --git a/src/XIVLauncher.Core/OSInfo.cs b/src/XIVLauncher.Core/OSInfo.cs index a8e49118..da8d0896 100644 --- a/src/XIVLauncher.Core/OSInfo.cs +++ b/src/XIVLauncher.Core/OSInfo.cs @@ -6,7 +6,7 @@ namespace XIVLauncher.Core; -public enum DistroPackage +public enum LinuxDistroPackage { ubuntu, @@ -19,7 +19,7 @@ public enum DistroPackage public static class OSInfo { - public static DistroPackage Package { get; private set; } + public static LinuxDistroPackage Package { get; private set; } public static string Name { get; private set; } @@ -32,7 +32,7 @@ static OSInfo() var os = System.Environment.OSVersion; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - Package = DistroPackage.none; + Package = LinuxDistroPackage.none; Name = os.VersionString; IsFlatpak = false; Platform = Platform.Win32; @@ -46,7 +46,7 @@ static OSInfo() Platform = Platform.Mac; Name = os.VersionString; IsFlatpak = false; - Package = DistroPackage.none; + Package = LinuxDistroPackage.none; return; } @@ -55,7 +55,7 @@ static OSInfo() Platform = Platform.Mac; // Don't have an option for this atm. Name = os.VersionString; IsFlatpak = false; - Package = DistroPackage.none; + Package = LinuxDistroPackage.none; return; } @@ -64,7 +64,7 @@ static OSInfo() { if (!File.Exists("/etc/os-release")) { - Package = DistroPackage.ubuntu; + Package = LinuxDistroPackage.ubuntu; Name = "Unknown distribution"; IsFlatpak = false; return; @@ -87,7 +87,7 @@ static OSInfo() if (CheckFlatpak(osInfo)) { IsFlatpak = true; - Package = DistroPackage.ubuntu; + Package = LinuxDistroPackage.ubuntu; return; } @@ -98,7 +98,7 @@ static OSInfo() catch { // If there's any kind of error opening the file or even finding it, just go with default. - Package = DistroPackage.ubuntu; + Package = LinuxDistroPackage.ubuntu; Name = "Unknown distribution"; IsFlatpak = false; } @@ -112,21 +112,21 @@ private static bool CheckFlatpak(Dictionary osInfo) return false; } - private static DistroPackage CheckDistro(Dictionary osInfo) + private static LinuxDistroPackage CheckDistro(Dictionary osInfo) { foreach (var kvp in osInfo) { if (kvp.Value.ToLower().Contains("fedora")) - return DistroPackage.fedora; + return LinuxDistroPackage.fedora; if (kvp.Value.ToLower().Contains("tumbleweed")) - return DistroPackage.fedora; + return LinuxDistroPackage.fedora; if (kvp.Value.ToLower().Contains("ubuntu")) - return DistroPackage.ubuntu; + return LinuxDistroPackage.ubuntu; if (kvp.Value.ToLower().Contains("debian")) - return DistroPackage.ubuntu; + return LinuxDistroPackage.ubuntu; if (kvp.Value.ToLower().Contains("arch")) - return DistroPackage.arch; + return LinuxDistroPackage.arch; } - return DistroPackage.ubuntu; + return LinuxDistroPackage.ubuntu; } } \ No newline at end of file diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 1b3d3b14..cb653282 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -325,7 +325,7 @@ private static void Main(string[] args) public static void CreateCompatToolsInstance() { var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled); - var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root.FullName, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); + var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder, OSInfo.IsFlatpak); } diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index c31aa9be..5cef7648 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -51,7 +51,7 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; - public static bool MangoHudInstalled => UnixHelpers.MangoHudIsInstalled(); + public static bool MangoHudInstalled => DxvkSettings.MangoHudIsInstalled(); public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; From 48ace04440ff4c4775c252c819e0f199b08796df Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 1 Aug 2023 20:10:42 -0700 Subject: [PATCH 15/40] Update submodule --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 7d21042d..3025d250 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 7d21042d9706b887673020f1e2ec7c09b7d76d7d +Subproject commit 3025d2500b71272bd6cdace718de36ebb20b58c2 From a6ae34fc3faadb53379aa5bd532054b43ae1b452 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 3 Aug 2023 07:55:13 -0700 Subject: [PATCH 16/40] Submodule update --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 3025d250..dd1d2a3e 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 3025d2500b71272bd6cdace718de36ebb20b58c2 +Subproject commit dd1d2a3ebec5faf10605b956a86d01cc0372b0eb From 62508411db6589171eb4246864c244e312e9f5c7 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 8 Aug 2023 16:24:01 -0700 Subject: [PATCH 17/40] Remove unused property --- src/XIVLauncher.Core/UnixCompatibility/Wine.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 2758b9d3..8605b526 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -39,8 +39,6 @@ public static class Wine public static bool ESyncEnabled => Program.Config.ESyncEnabled ?? true; public static bool FSyncEnabled => Program.Config.FSyncEnabled ?? false; - - private static bool OSReleaseIsParsed = false; } public enum WineType From a999a38754ff764cd49066d952ad019a40bb6077 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Tue, 5 Sep 2023 09:56:40 -0700 Subject: [PATCH 18/40] Add Dxvk 2.3 --- .../SettingsPage/Tabs/SettingsTabDxvk.cs | 4 ++-- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 16 ++++++++++------ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 239b6b8f..47daded5 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -22,7 +22,7 @@ public SettingsTabDxvk() { CheckWarning = type => { - if (new [] {DxvkVersion.v2_1, DxvkVersion.v2_2}.Contains(type)) + if (new [] {DxvkVersion.v2_1, DxvkVersion.v2_2, DxvkVersion.v2_3}.Contains(type)) return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; return null; }, @@ -33,7 +33,7 @@ public SettingsTabDxvk() CheckWarning = b => { if (!b && dxvkVersionSetting.Value == DxvkVersion.v2_0) - return "AMD users may need to use env variable RADV_PERFTEST=gpl"; + return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; return null; }, }, diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 5cef7648..bfb978e9 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -22,6 +22,7 @@ public static class Dxvk DxvkVersion.v2_0 => "dxvk-async-2.0", DxvkVersion.v2_1 => "dxvk-2.1", DxvkVersion.v2_2 => "dxvk-2.2", + DxvkVersion.v2_3 => "dxvk-2.3", _ => throw new ArgumentOutOfRangeException(), }; @@ -32,6 +33,7 @@ public static class Dxvk DxvkVersion.v2_0 => "https://github.com/Sporif/dxvk-async/releases/download/2.0/dxvk-async-2.0.tar.gz", DxvkVersion.v2_1 => "https://github.com/doitsujin/dxvk/releases/download/v2.1/dxvk-2.1.tar.gz", DxvkVersion.v2_2 => "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz", + DxvkVersion.v2_3 => "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz", _ => throw new ArgumentOutOfRangeException(), }; @@ -77,22 +79,24 @@ public static class Dxvk public enum DxvkVersion { - [SettingsDescription("1.10.3 (default)", "Current version of 1.10 branch of DXVK.")] + [SettingsDescription("Dxvk 1.10.3 (Legacy)", "Dxvk 1.10.3. High compatibility with most graphics cards.")] v1_10_3, - [SettingsDescription("2.0", "Newer version of DXVK. Last version with Async patch")] + [SettingsDescription("Dxvk 2.0", "Dxvk 2.0. Equivalent to 1.10.3 if used with Async. Uses GPL without Async.")] v2_0, - [SettingsDescription("2.1 (No Async)", "Newer version of DXVK, using graphics pipeline library. No Async patch.")] + [SettingsDescription("Dxvk 2.1", "A previous version of Dxvk, using GPL. Try this if 2.2 & 2.3 cause problems.")] v2_1, - [SettingsDescription("2.2 (No Async)", "Newest version of DXVK, using graphics pipeline library. No Async patch.")] - v2_2, + [SettingsDescription("Dxvk 2.2", "A previous version of Dxvk, using GPL. Try this if 2.3 causes problems.")] + v2_2, + + [SettingsDescription("Dxvk 2.3 (Current)", "Dxvk 2.3, using GPL. May help in CPU-bound situations. No Async patch.")] + v2_3, [SettingsDescription("Disabled", "Disable Dxvk, use WineD3D with OpenGL instead.")] Disabled, } - public enum DxvkHud { [SettingsDescription("None", "Disable DXVK Hud")] From 8f641c842f05baac1f4fb584861e2023efc174c9 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 7 Sep 2023 09:02:54 -0700 Subject: [PATCH 19/40] Add DXVK custom option. Clean up DXVK tab. --- .../SettingsPage/Tabs/SettingsTabDxvk.cs | 8 +++--- .../UnixCompatibility/Dxvk.cs | 25 +++++++++++-------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 47daded5..41f43ab7 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -14,11 +14,13 @@ public class SettingsTabDxvk : SettingsTab private SettingsEntry dxvkHudSetting; private SettingsEntry mangoHudSetting; + private string customDxvk = Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk", "custom"); + public SettingsTabDxvk() { Entries = new SettingsEntry[] { - dxvkVersionSetting = new SettingsEntry("DXVK Version", "Choose which version of DXVK to use.", () => Program.Config.DxvkVersion ?? DxvkVersion.v1_10_3, type => Program.Config.DxvkVersion = type) + dxvkVersionSetting = new SettingsEntry("DXVK Version", "Choose which version of DXVK to use. Put your custom DXVK in " + customDxvk, () => Program.Config.DxvkVersion ?? DxvkVersion.v1_10_3, type => Program.Config.DxvkVersion = type) { CheckWarning = type => { @@ -29,7 +31,7 @@ public SettingsTabDxvk() }, new SettingsEntry("Enable DXVK ASYNC", "Enable DXVK ASYNC patch.", () => Program.Config.DxvkAsyncEnabled ?? true, b => Program.Config.DxvkAsyncEnabled = b) { - CheckVisibility = () => (new [] {DxvkVersion.v1_10_3, DxvkVersion.v2_0}.Contains(dxvkVersionSetting.Value)), + CheckVisibility = () => (new [] {DxvkVersion.v1_10_3, DxvkVersion.v2_0, DxvkVersion.Custom}.Contains(dxvkVersionSetting.Value)), CheckWarning = b => { if (!b && dxvkVersionSetting.Value == DxvkVersion.v2_0) @@ -37,7 +39,7 @@ public SettingsTabDxvk() return null; }, }, - dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with Dxvk. MangoHud must be installed separately.\nFlatpak users need the flatpak version of MangoHud.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) + dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with DXVK. MangoHud must be installed separately.\nFlatpak users need the flatpak version of MangoHud.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) { CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, }, diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index bfb978e9..6a552992 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -23,6 +23,7 @@ public static class Dxvk DxvkVersion.v2_1 => "dxvk-2.1", DxvkVersion.v2_2 => "dxvk-2.2", DxvkVersion.v2_3 => "dxvk-2.3", + DxvkVersion.Custom => "custom", _ => throw new ArgumentOutOfRangeException(), }; @@ -34,6 +35,7 @@ public static class Dxvk DxvkVersion.v2_1 => "https://github.com/doitsujin/dxvk/releases/download/v2.1/dxvk-2.1.tar.gz", DxvkVersion.v2_2 => "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz", DxvkVersion.v2_3 => "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz", + DxvkVersion.Custom => "", _ => throw new ArgumentOutOfRangeException(), }; @@ -79,22 +81,25 @@ public static class Dxvk public enum DxvkVersion { - [SettingsDescription("Dxvk 1.10.3 (Legacy)", "Dxvk 1.10.3. High compatibility with most graphics cards.")] - v1_10_3, + [SettingsDescription("DXVK 2.3 (Current)", "DXVK 2.3, using GPL. May help in CPU-bound situations. No Async patch.")] + v2_3, - [SettingsDescription("Dxvk 2.0", "Dxvk 2.0. Equivalent to 1.10.3 if used with Async. Uses GPL without Async.")] - v2_0, + [SettingsDescription("DXVK 1.10.3 (Legacy)", "DXVK 1.10.3. High compatibility with most graphics cards.")] + v1_10_3, - [SettingsDescription("Dxvk 2.1", "A previous version of Dxvk, using GPL. Try this if 2.2 & 2.3 cause problems.")] - v2_1, + [SettingsDescription("Custom DXVK", "Put a custom DXVK version in ~/.xlcore/compatibilitytool/dxvk/custom")] + Custom, - [SettingsDescription("Dxvk 2.2", "A previous version of Dxvk, using GPL. Try this if 2.3 causes problems.")] + [SettingsDescription("DXVK 2.2", "A previous version of DXVK, using GPL. Try this if 2.3 causes problems.")] v2_2, - [SettingsDescription("Dxvk 2.3 (Current)", "Dxvk 2.3, using GPL. May help in CPU-bound situations. No Async patch.")] - v2_3, + [SettingsDescription("DXVK 2.1", "A previous version of DXVK, using GPL. Try this if 2.2 & 2.3 cause problems.")] + v2_1, + + [SettingsDescription("DXVK 2.0", "DXVK 2.0. Equivalent to 1.10.3 if used with Async. Uses GPL without Async.")] + v2_0, - [SettingsDescription("Disabled", "Disable Dxvk, use WineD3D with OpenGL instead.")] + [SettingsDescription("Disabled", "Disable DXVK, use WineD3D with OpenGL instead.")] Disabled, } public enum DxvkHud From 345bed0f1e39824719bc4be635ade74114f6762f Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sun, 10 Sep 2023 20:18:59 -0700 Subject: [PATCH 20/40] Improved version picker --- .../SettingsPage/DictionarySettingsEntry.cs | 86 ++++++++++++++ .../SettingsPage/Tabs/SettingsTabDxvk.cs | 37 +++--- .../SettingsPage/Tabs/SettingsTabWine.cs | 5 +- .../Configuration/ILauncherConfig.cs | 4 +- src/XIVLauncher.Core/Program.cs | 8 +- .../UnixCompatibility/Dxvk.cs | 109 +++++++++++------- .../UnixCompatibility/Wine.cs | 82 +++++++++---- 7 files changed, 238 insertions(+), 93 deletions(-) create mode 100644 src/XIVLauncher.Core/Components/SettingsPage/DictionarySettingsEntry.cs diff --git a/src/XIVLauncher.Core/Components/SettingsPage/DictionarySettingsEntry.cs b/src/XIVLauncher.Core/Components/SettingsPage/DictionarySettingsEntry.cs new file mode 100644 index 00000000..04da17a2 --- /dev/null +++ b/src/XIVLauncher.Core/Components/SettingsPage/DictionarySettingsEntry.cs @@ -0,0 +1,86 @@ +using ImGuiNET; +using XIVLauncher.Core.UnixCompatibility; + +namespace XIVLauncher.Core.Components.SettingsPage; + +public class DictionarySettingsEntry : SettingsEntry +{ + public Dictionary> Pairs; + + public string DefaultValue; + + public bool ShowDescription; + + public bool ShowItemDescription; + + public DictionarySettingsEntry(string name, string description, Dictionary> pairs, Func load, Action save, string defaultValue, bool showSelectedDesc = false, bool showItemDesc = true) + : base(name, description, load, save) + { + this.Pairs = pairs; + this.DefaultValue = defaultValue; + this.ShowDescription = showSelectedDesc; + this.ShowItemDescription = showItemDesc; + } + + + public override void Draw() + { + var nativeValue = this.Value; + string idx = (string)(this.InternalValue ?? DefaultValue); + + ImGuiHelpers.TextWrapped(this.Name); + + Dictionary>.KeyCollection keys = Pairs.Keys; + var label = Pairs[idx].ContainsKey("label") ? $"[{Pairs[idx]["label"]}] " : ""; + var name = Pairs[idx].ContainsKey("name") ? Pairs[idx]["name"] : idx; + var desc = ShowDescription && Pairs[idx].ContainsKey("desc") ? $" - {Pairs[idx]["desc"]}" : ""; + var mark = Pairs[idx].ContainsKey("mark") ? $" *{Pairs[idx]["mark"]}*" : ""; + + if (ImGui.BeginCombo($"###{Id.ToString()}", $"{label}{name}{desc}{mark}")) + { + foreach ( string key in keys ) + { + var itemlabel = Pairs[key].ContainsKey("label") ? $"[{Pairs[key]["label"]}] " : ""; + var itemname = Pairs[key].ContainsKey("name") ? Pairs[key]["name"] : key; + var itemdesc = ShowItemDescription && Pairs[key].ContainsKey("desc") ? $" - {Pairs[key]["desc"]}" : ""; + var itemmark = Pairs[key].ContainsKey("mark") ? $" *{Pairs[key]["mark"]}*" : ""; + if (ImGui.Selectable($"{itemlabel}{itemname}{itemdesc}{itemmark}", idx == key)) + { + this.InternalValue = key; + } + } + ImGui.EndCombo(); + } + + ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudGrey); + if (!string.IsNullOrEmpty(this.Description)) ImGuiHelpers.TextWrapped(this.Description); + ImGui.PopStyleColor(); + + if (this.CheckValidity != null) + { + var validityMsg = this.CheckValidity.Invoke(this.Value); + this.IsValid = string.IsNullOrEmpty(validityMsg); + + if (!this.IsValid) + { + ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed); + ImGui.Text(validityMsg); + ImGui.PopStyleColor(); + } + } + else + { + this.IsValid = true; + } + + var warningMessage = this.CheckWarning?.Invoke(this.Value); + + if (warningMessage != null) + { + ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed); + ImGui.Text(warningMessage); + ImGui.PopStyleColor(); + } + + } +} \ No newline at end of file diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 41f43ab7..3223a8c1 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -1,51 +1,44 @@ -using System.IO; -using System.Numerics; using System.Runtime.InteropServices; using ImGuiNET; using XIVLauncher.Common.Unix.Compatibility; -using XIVLauncher.Common.Util; using XIVLauncher.Core.UnixCompatibility; namespace XIVLauncher.Core.Components.SettingsPage.Tabs; public class SettingsTabDxvk : SettingsTab { - private SettingsEntry dxvkVersionSetting; + private DictionarySettingsEntry dxvkVersionSetting; private SettingsEntry dxvkHudSetting; private SettingsEntry mangoHudSetting; - private string customDxvk = Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk", "custom"); + private string dxvkPath = Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk"); public SettingsTabDxvk() { Entries = new SettingsEntry[] { - dxvkVersionSetting = new SettingsEntry("DXVK Version", "Choose which version of DXVK to use. Put your custom DXVK in " + customDxvk, () => Program.Config.DxvkVersion ?? DxvkVersion.v1_10_3, type => Program.Config.DxvkVersion = type) + dxvkVersionSetting = new DictionarySettingsEntry("DXVK Version", $"Choose which version of DXVK to use. Put your custom DXVK in {dxvkPath}\nEntries marked with *Download* will be downloaded when you log in.", Dxvk.Versions, () => Program.Config.DxvkVersion ?? "dxvk-async-1.10.3", s => Program.Config.DxvkVersion = s, Dxvk.GetDefaultVersion()) { - CheckWarning = type => + CheckWarning = s => { - if (new [] {DxvkVersion.v2_1, DxvkVersion.v2_2, DxvkVersion.v2_3}.Contains(type)) + if (new [] {"dxvk-2.3", "dxvk-2.2", "dxvk-2.1", "dxvk-async-2.0", "dxvk-2.0"}.Contains(s)) return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; return null; }, }, - new SettingsEntry("Enable DXVK ASYNC", "Enable DXVK ASYNC patch.", () => Program.Config.DxvkAsyncEnabled ?? true, b => Program.Config.DxvkAsyncEnabled = b) + new SettingsEntry("Enable DXVK ASYNC", "Enable DXVK ASYNC patch. May not be available on DXVK >= 2.0", () => Program.Config.DxvkAsyncEnabled ?? true, b => Program.Config.DxvkAsyncEnabled = b) { - CheckVisibility = () => (new [] {DxvkVersion.v1_10_3, DxvkVersion.v2_0, DxvkVersion.Custom}.Contains(dxvkVersionSetting.Value)), - CheckWarning = b => - { - if (!b && dxvkVersionSetting.Value == DxvkVersion.v2_0) - return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; - return null; - }, + CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED", }, + dxvkHudSetting = new SettingsEntry("DXVK Overlay", "DXVK Hud is included with DXVK. MangoHud must be installed separately.\nFlatpak users need the flatpak version of MangoHud.", () => Program.Config.DxvkHud ?? DxvkHud.None, x => Program.Config.DxvkHud = x) { - CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, + CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED", }, + new SettingsEntry("DXVK Hud Custom String", "Set a custom string for the built in DXVK Hud. Warning: If it's invalid, the game may hang.", () => Program.Config.DxvkHudCustom ?? Dxvk.DXVK_HUD, s => Program.Config.DxvkHudCustom = s) { - CheckVisibility = () => dxvkHudSetting.Value == DxvkHud.Custom && dxvkVersionSetting.Value != DxvkVersion.Disabled, + CheckVisibility = () => dxvkHudSetting.Value == DxvkHud.Custom && dxvkVersionSetting.Value != "DISABLED", CheckWarning = s => { if(!DxvkSettings.DxvkHudStringIsValid(s)) @@ -55,7 +48,7 @@ public SettingsTabDxvk() }, mangoHudSetting = new SettingsEntry("MangoHud Overlay", "MangoHud is installed. It is recommended to set Dxvk Overlay to None if using MangoHud.", () => Program.Config.MangoHud ?? MangoHud.None, x => Program.Config.MangoHud = x) { - CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED" && Dxvk.MangoHudInstalled, CheckWarning = x => { if (dxvkHudSetting.Value != DxvkHud.None && x != MangoHud.None) @@ -65,7 +58,7 @@ public SettingsTabDxvk() }, new SettingsEntry("MangoHud Custom String", "Set a custom string for MangoHud config.", () => Program.Config.MangoHudCustomString ?? Dxvk.MANGOHUD_CONFIG, s => Program.Config.MangoHudCustomString = s) { - CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomString && dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomString && dxvkVersionSetting.Value != "DISABLED" && Dxvk.MangoHudInstalled, CheckWarning = s => { if (s.Contains(' ')) @@ -75,7 +68,7 @@ public SettingsTabDxvk() }, new SettingsEntry("MangoHud Custom Path", "Set a custom path for MangoHud config file.", () => Program.Config.MangoHudCustomFile ?? Dxvk.MANGOHUD_CONFIGFILE, s => Program.Config.MangoHudCustomFile = s) { - CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomFile && dxvkVersionSetting.Value != DxvkVersion.Disabled && Dxvk.MangoHudInstalled, + CheckVisibility = () => mangoHudSetting.Value == MangoHud.CustomFile && dxvkVersionSetting.Value != "DISABLED" && Dxvk.MangoHudInstalled, CheckWarning = s => { if(!File.Exists(s)) @@ -85,7 +78,7 @@ public SettingsTabDxvk() }, new NumericSettingsEntry("Frame Rate Limit", "Set a frame rate limit, and DXVK will try not exceed it. Use 0 for unlimited.", () => Program.Config.DxvkFrameRateLimit ?? 0, i => Program.Config.DxvkFrameRateLimit = i, 0, 1000) { - CheckVisibility = () => dxvkVersionSetting.Value != DxvkVersion.Disabled, + CheckVisibility = () => dxvkVersionSetting.Value != "DISABLED", }, }; } diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 56747434..4062ac51 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -1,7 +1,6 @@ using System.Numerics; using System.Runtime.InteropServices; using ImGuiNET; -using XIVLauncher.Common.Unix.Compatibility; using XIVLauncher.Common.Util; using XIVLauncher.Core.UnixCompatibility; @@ -11,6 +10,8 @@ public class SettingsTabWine : SettingsTab { private SettingsEntry wineTypeSetting; + private readonly string toolDirectory = Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "wine"); + public SettingsTabWine() { Entries = new SettingsEntry[] @@ -18,7 +19,7 @@ public SettingsTabWine() wineTypeSetting = new SettingsEntry("Installation Type", "Choose how XIVLauncher will start and manage your game installation.", () => Program.Config.WineType ?? WineType.Managed, x => Program.Config.WineType = x), - new SettingsEntry("Wine Version", "Choose a patched wine version.", () => Program.Config.WineVersion ?? WineVersion.Wine7_10, x => Program.Config.WineVersion = x) + new DictionarySettingsEntry("Wine Version", $"Wine versions in {toolDirectory}\nEntries marked with *Download* will be downloaded when you log in.", Wine.Versions, () => Program.Config.WineVersion, s => Program.Config.WineVersion = s, Wine.GetDefaultVersion()) { CheckVisibility = () => wineTypeSetting.Value == WineType.Managed }, diff --git a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs index c3bb9b79..aaf56993 100644 --- a/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs +++ b/src/XIVLauncher.Core/Configuration/ILauncherConfig.cs @@ -65,7 +65,7 @@ public interface ILauncherConfig public WineType? WineType { get; set; } - public WineVersion? WineVersion { get; set; } + public string? WineVersion { get; set; } public string? WineBinaryPath { get; set; } @@ -77,7 +77,7 @@ public interface ILauncherConfig public bool? FSyncEnabled { get; set; } - public DxvkVersion? DxvkVersion { get; set; } + public string? DxvkVersion { get; set; } public int? DxvkFrameRateLimit { get; set; } diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index cb653282..018e800a 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -120,11 +120,13 @@ private static void LoadConfig(Storage storage) Config.FSyncEnabled ??= false; Config.WineType ??= WineType.Managed; - Config.WineVersion ??= WineVersion.Wine7_10; + if (!Wine.Versions.ContainsKey(Config.WineVersion ?? "")) + Config.WineVersion = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; Config.WineBinaryPath ??= "/usr/bin"; Config.WineDebugVars ??= "-all"; - Config.DxvkVersion ??= DxvkVersion.v1_10_3; + if (!Dxvk.Versions.ContainsKey(Config.DxvkVersion ?? "")) + Config.DxvkVersion = "dxvk-async-1.10.3"; Config.DxvkAsyncEnabled ??= true; Config.DxvkFrameRateLimit ??= 0; Config.DxvkHud ??= DxvkHud.None; @@ -144,6 +146,8 @@ private static void Main(string[] args) { mainargs = args; storage = new Storage(APP_NAME); + Wine.Initialize(); + Dxvk.Initialize(); if (CoreEnvironmentSettings.ClearAll) { diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 6a552992..f2c02c9a 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -13,31 +13,11 @@ namespace XIVLauncher.Core.UnixCompatibility; public static class Dxvk { - public static bool Enabled => Program.Config.DxvkVersion != DxvkVersion.Disabled; + public static bool Enabled => Program.Config.DxvkVersion != "DISABLED"; - public static string FolderName => Program.Config.DxvkVersion switch - { - DxvkVersion.Disabled => "", - DxvkVersion.v1_10_3 => "dxvk-async-1.10.3", - DxvkVersion.v2_0 => "dxvk-async-2.0", - DxvkVersion.v2_1 => "dxvk-2.1", - DxvkVersion.v2_2 => "dxvk-2.2", - DxvkVersion.v2_3 => "dxvk-2.3", - DxvkVersion.Custom => "custom", - _ => throw new ArgumentOutOfRangeException(), - }; + public static string FolderName => Program.Config.DxvkVersion ?? GetDefaultVersion(); - public static string DownloadUrl => Program.Config.DxvkVersion switch - { - DxvkVersion.Disabled => "", - DxvkVersion.v1_10_3 => "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz", - DxvkVersion.v2_0 => "https://github.com/Sporif/dxvk-async/releases/download/2.0/dxvk-async-2.0.tar.gz", - DxvkVersion.v2_1 => "https://github.com/doitsujin/dxvk/releases/download/v2.1/dxvk-2.1.tar.gz", - DxvkVersion.v2_2 => "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz", - DxvkVersion.v2_3 => "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz", - DxvkVersion.Custom => "", - _ => throw new ArgumentOutOfRangeException(), - }; + public static string DownloadUrl => GetDownloadUrl(Program.Config.DxvkVersion); public static int FrameRateLimit => Program.Config.DxvkFrameRateLimit ?? 0; @@ -77,31 +57,72 @@ public static class Dxvk public static string MANGOHUD_CONFIGFILE => Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".config", "MangoHud", "MangoHud.conf"); -} - -public enum DxvkVersion -{ - [SettingsDescription("DXVK 2.3 (Current)", "DXVK 2.3, using GPL. May help in CPU-bound situations. No Async patch.")] - v2_3, - - [SettingsDescription("DXVK 1.10.3 (Legacy)", "DXVK 1.10.3. High compatibility with most graphics cards.")] - v1_10_3, + public static Dictionary> Versions { get; private set; } - [SettingsDescription("Custom DXVK", "Put a custom DXVK version in ~/.xlcore/compatibilitytool/dxvk/custom")] - Custom, - - [SettingsDescription("DXVK 2.2", "A previous version of DXVK, using GPL. Try this if 2.3 causes problems.")] - v2_2, - - [SettingsDescription("DXVK 2.1", "A previous version of DXVK, using GPL. Try this if 2.2 & 2.3 cause problems.")] - v2_1, + static Dxvk() + { + Versions = new Dictionary>() + { + { "dxvk-2.3", new Dictionary() + { {"name", "DXVK 2.3"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, + {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz"}, + {"mark", "Download" } } }, + { "dxvk-async-1.10.3", new Dictionary() + { {"name", "DXVK 1.10.3"}, {"desc", "Legacy version with high compatibility. Includes async patch."}, + {"label", "Legacy"}, {"url", "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz"}, + {"mark", "Download" } } }, + { "DISABLED", new Dictionary() + { {"name", "WineD3D"}, {"desc", "Use WineD3D (OpenGL) instead of DXVK. For old GPUs without Vulkan support."}, + {"label", "Disabled"} } }, + }; + } + + public static void Initialize() + { + var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk")); + + if (!toolDirectory.Exists) + { + Program.storage.GetFolder("compatibilitytool/dxvk"); + return; + } + + foreach (var dxvkDir in toolDirectory.EnumerateDirectories()) + { + if (Directory.Exists(Path.Combine(dxvkDir.FullName, "x64")) && Directory.Exists(Path.Combine(dxvkDir.FullName, "x32"))) + { + if (Versions.ContainsKey(dxvkDir.Name)) + { + if (dxvkDir.Name == "DISABLED") + Log.Error("Cannot use custom DXVK with folder name DISABLED. Skipping."); + else + Versions[dxvkDir.Name].Remove("mark"); + continue; + } + Versions.Add(dxvkDir.Name, new Dictionary() { {"label", "Custom"} }); + } + } + } + + private static string GetDownloadUrl(string? name) + { + name ??= GetDefaultVersion(); + if (Versions.ContainsKey(name)) + return Versions[name].ContainsKey("url") ? Versions[name]["url"] : ""; + return Versions[GetDefaultVersion()]["url"]; + } - [SettingsDescription("DXVK 2.0", "DXVK 2.0. Equivalent to 1.10.3 if used with Async. Uses GPL without Async.")] - v2_0, + public static string GetDefaultVersion() + { + if (Versions.ContainsKey("dxvk-async-1.10.3")) + return "dxvk-async-1.10.3"; + if (Versions.ContainsKey("dxvk-2.3")) + return "dxvk-2.3"; + return Versions.First().Key; + } - [SettingsDescription("Disabled", "Disable DXVK, use WineD3D with OpenGL instead.")] - Disabled, } + public enum DxvkHud { [SettingsDescription("None", "Disable DXVK Hud")] diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 8605b526..97827f59 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -16,19 +16,9 @@ public static class Wine public static string CustomWinePath => Program.Config.WineBinaryPath ?? "/usr/bin"; - public static string FolderName => Program.Config.WineVersion switch - { - WineVersion.Wine7_10 => "wine-xiv-staging-fsync-git-7.10.r3.g560db77d", - WineVersion.Wine8_5 => "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7", - _ => throw new ArgumentOutOfRangeException(), - }; + public static string FolderName => Program.Config.WineVersion ?? GetDefaultVersion(); - public static string DownloadUrl =>Program.Config.WineVersion switch - { - WineVersion.Wine7_10 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz", - WineVersion.Wine8_5 => $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz", - _ => throw new ArgumentOutOfRangeException(), - }; + public static string DownloadUrl => GetDownloadUrl(Program.Config.WineVersion); public static string DebugVars => Program.Config.WineDebugVars ?? "-all"; @@ -39,6 +29,65 @@ public static class Wine public static bool ESyncEnabled => Program.Config.ESyncEnabled ?? true; public static bool FSyncEnabled => Program.Config.FSyncEnabled ?? false; + + public static Dictionary> Versions { get; private set; } + + static Wine() + { + Versions = new Dictionary>() + { + { "wine-xiv-staging-fsync-git-7.10.r3.g560db77d", new Dictionary() + { {"name", "Wine-XIV 7.10"}, {"desc","Patched version of Wine Staging 7.10. Default."}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz"}, + {"mark", "Download"} } }, + { "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7", new Dictionary() + { {"name", "Wine-XIV 8.5"}, {"desc", "Patched version of Wine Staging 8.5. Change Windows version to 7 for best results."}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, + {"mark", "Download"} } }, + }; + } + + public static void Initialize() + { + var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "wine")); + + if (!toolDirectory.Exists) + { + Program.storage.GetFolder("compatibilitytool/wine"); + return; + } + + foreach (var wineDir in toolDirectory.EnumerateDirectories()) + { + if (File.Exists(Path.Combine(wineDir.FullName, "bin", "wine64")) || + File.Exists(Path.Combine(wineDir.FullName, "bin", "wine"))) + { + if (Versions.ContainsKey(wineDir.Name)) + { + Versions[wineDir.Name].Remove("mark"); + continue; + } + Versions.Add(wineDir.Name, new Dictionary() {{"label", "Custom"}}); + } + } + } + + private static string GetDownloadUrl(string? name) + { + name ??= GetDefaultVersion(); + if (Versions.ContainsKey(name)) + return Versions[name].ContainsKey("url") ? Versions[name]["url"] : ""; + return Versions[GetDefaultVersion()]["url"]; + } + + public static string GetDefaultVersion() + { + if (Versions.ContainsKey("wine-xiv-staging-fsync-git-7.10.r3.g560db77d")) + return "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; + if (Versions.ContainsKey("wine-xiv-staging-fsync-git-8.5.r4.g4211bac7")) + return "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; + return Versions.First().Key; + } } public enum WineType @@ -48,13 +97,4 @@ public enum WineType [SettingsDescription("Custom", "Point XIVLauncher to a custom location containing wine binaries to run the game with.")] Custom, -} - -public enum WineVersion -{ - [SettingsDescription("Wine-xiv 7.10 (Default)", "A patched version of Wine, based on 7.10. The current default.")] - Wine7_10, - - [SettingsDescription("Wine-xiv 8.5", "A newer patched version of Wine-staging 8.5. May be faster, but less stable.")] - Wine8_5, } \ No newline at end of file From 7e58294e2a63e71196eaf1fd1a59b22e9783eb04 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 13 Sep 2023 19:37:43 -0700 Subject: [PATCH 21/40] Update dxvk warning for multiple DXVK 2 versions --- .../Components/SettingsPage/Tabs/SettingsTabDxvk.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs index 3223a8c1..a8374345 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDxvk.cs @@ -21,7 +21,8 @@ public SettingsTabDxvk() { CheckWarning = s => { - if (new [] {"dxvk-2.3", "dxvk-2.2", "dxvk-2.1", "dxvk-async-2.0", "dxvk-2.0"}.Contains(s)) + if (s is null) return null; + if (s.StartsWith("dxvk-2") || s.StartsWith("dxvk-async-2") || s.StartsWith("dxvk-gplasync-v2")) return "May not work with older graphics cards. AMD users may need to use env variable RADV_PERFTEST=gpl"; return null; }, From c18ef3b4847dfe3f8b54faba5c312d6281e49cf0 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 14 Sep 2023 19:24:56 -0700 Subject: [PATCH 22/40] Rework troubleshooing option to only delete official wine versions, and leave custom wine --- .../Tabs/SettingsTabTroubleshooting.cs | 8 ++++- src/XIVLauncher.Core/Program.cs | 19 ++++++++-- .../UnixCompatibility/Dxvk.cs | 36 +++++++++++-------- .../UnixCompatibility/Wine.cs | 28 ++++++++------- 4 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs index c3f4f153..820f3b2f 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs @@ -37,7 +37,7 @@ public override void Draw() Program.ClearPrefix(); } - ImGui.Text("\nClear the managed Wine install and DXVK"); + ImGui.Text("\nClear the managed Wine and DXVK installs. Custom versions won't be touched."); if (ImGui.Button("Clear Wine & DXVK")) { Program.ClearTools(true); @@ -61,6 +61,12 @@ public override void Draw() Program.ClearAll(true); } + ImGui.Text("\nOpen the .xlcore folder in your file browser."); + if (ImGui.Button("Open .xlcore")) + { + PlatformHelpers.OpenBrowser(Program.storage.Root.FullName); + } + ImGui.Text("\nGenerate a troubleshooting pack to upload to the official Discord channel"); if (ImGui.Button("Generate tspack")) { diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 018e800a..48802b43 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -418,9 +418,22 @@ public static void ClearPlugins(bool tsbutton = false) public static void ClearTools(bool tsbutton = false) { - storage.GetFolder("compatibilitytool").Delete(true); - storage.GetFolder("compatibilitytool/wine"); - storage.GetFolder("compatibilitytool/dxvk"); + foreach (var winetool in Wine.Versions) + { + if (winetool.Value.ContainsKey("url")) + if (!string.IsNullOrEmpty(winetool.Value["url"])) + storage.GetFolder($"compatibilitytool/wine/{winetool.Key}").Delete(true); + } + foreach (var dxvktool in Dxvk.Versions) + { + if (dxvktool.Value.ContainsKey("url")) + if (!string.IsNullOrEmpty(dxvktool.Value["url"])) + storage.GetFolder($"compatibilitytool/dxvk/{dxvktool.Key}").Delete(true); + } + // Re-initialize Versions so they get *Download* marks back. + Wine.Initialize(); + Dxvk.Initialize(); + if (tsbutton) CreateCompatToolsInstance(); } diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index f2c02c9a..a68d3ac3 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -61,24 +61,30 @@ public static class Dxvk static Dxvk() { - Versions = new Dictionary>() - { - { "dxvk-2.3", new Dictionary() - { {"name", "DXVK 2.3"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, - {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz"}, - {"mark", "Download" } } }, - { "dxvk-async-1.10.3", new Dictionary() - { {"name", "DXVK 1.10.3"}, {"desc", "Legacy version with high compatibility. Includes async patch."}, - {"label", "Legacy"}, {"url", "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz"}, - {"mark", "Download" } } }, - { "DISABLED", new Dictionary() - { {"name", "WineD3D"}, {"desc", "Use WineD3D (OpenGL) instead of DXVK. For old GPUs without Vulkan support."}, - {"label", "Disabled"} } }, - }; + Versions = new Dictionary>(); } public static void Initialize() { + // Add default versions. + Versions["dxvk-2.3"] = new Dictionary() + { + {"name", "DXVK 2.3"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, + {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.3/dxvk-2.3.tar.gz"}, + {"mark", "Download" } + }; + Versions["dxvk-async-1.10.3"] = new Dictionary() + { + {"name", "DXVK 1.10.3"}, {"desc", "Legacy version with high compatibility. Includes async patch."}, + {"label", "Legacy"}, {"url", "https://github.com/Sporif/dxvk-async/releases/download/1.10.3/dxvk-async-1.10.3.tar.gz"}, + {"mark", "Download" } + }; + Versions["DISABLED"] = new Dictionary() + { + {"name", "WineD3D"}, {"desc", "Use WineD3D (OpenGL) instead of DXVK. For old GPUs without Vulkan support."}, + {"label", "Disabled"} + }; + var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "dxvk")); if (!toolDirectory.Exists) @@ -99,7 +105,7 @@ public static void Initialize() Versions[dxvkDir.Name].Remove("mark"); continue; } - Versions.Add(dxvkDir.Name, new Dictionary() { {"label", "Custom"} }); + Versions[dxvkDir.Name] = new Dictionary() { {"label", "Custom"} }; } } } diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 97827f59..1606f133 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -34,21 +34,25 @@ public static class Wine static Wine() { - Versions = new Dictionary>() - { - { "wine-xiv-staging-fsync-git-7.10.r3.g560db77d", new Dictionary() - { {"name", "Wine-XIV 7.10"}, {"desc","Patched version of Wine Staging 7.10. Default."}, - {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz"}, - {"mark", "Download"} } }, - { "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7", new Dictionary() - { {"name", "Wine-XIV 8.5"}, {"desc", "Patched version of Wine Staging 8.5. Change Windows version to 7 for best results."}, - {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, - {"mark", "Download"} } }, - }; + Versions = new Dictionary>(); } public static void Initialize() { + // Add default versions. + Versions["wine-xiv-staging-fsync-git-7.10.r3.g560db77d"] = new Dictionary() + { + {"name", "Wine-XIV 7.10"}, {"desc","Patched version of Wine Staging 7.10. Default."}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz"}, + {"mark", "Download"} + }; + Versions["wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"] = new Dictionary() + { + {"name", "Wine-XIV 8.5"}, {"desc", "Patched version of Wine Staging 8.5. Change Windows version to 7 for best results."}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, + {"mark", "Download"} + }; + var toolDirectory = new DirectoryInfo(Path.Combine(Program.storage.Root.FullName, "compatibilitytool", "wine")); if (!toolDirectory.Exists) @@ -67,7 +71,7 @@ public static void Initialize() Versions[wineDir.Name].Remove("mark"); continue; } - Versions.Add(wineDir.Name, new Dictionary() {{"label", "Custom"}}); + Versions[wineDir.Name] = new Dictionary() { {"label", "Custom"} }; } } } From 124e9b926a63fdccd7201f8f798cd17b8a3079d9 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 21 Sep 2023 20:51:02 -0700 Subject: [PATCH 23/40] Fix console spam "gamemodeauto:" * Move to CoreEnvironmentSettings so it only gets called once per session --- .../SettingsPage/Tabs/SettingsTabWine.cs | 4 +--- src/XIVLauncher.Core/CoreEnvironmentSettings.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index 8d542456..e3402950 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -29,10 +29,8 @@ public SettingsTabWine() CheckVisibility = () => RuntimeInformation.IsOSPlatform(OSPlatform.Linux), CheckValidity = b => { - var handle = IntPtr.Zero; - if (b == true && !NativeLibrary.TryLoad("libgamemodeauto.so.0", out handle)) + if (b == true && !CoreEnvironmentSettings.GameModeInstalled) return "GameMode was not detected on your system."; - NativeLibrary.Free(handle); return null; } }, diff --git a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs index 2a78b2b3..278fbde8 100644 --- a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs +++ b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; namespace XIVLauncher.Core; @@ -37,4 +38,18 @@ public static string GetCleanEnvironmentVariable(string envvar, string badstring if (badstring.Equals("")) return dirty; return string.Join(separator, Array.FindAll(dirty.Split(separator, StringSplitOptions.RemoveEmptyEntries), s => !s.Contains(badstring))); } + + static public bool GameModeInstalled { get; } + + static CoreEnvironmentSettings() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + var handle = IntPtr.Zero; + GameModeInstalled = NativeLibrary.TryLoad("libgamemodeauto.so.0", out handle); + NativeLibrary.Free(handle); + } + else + GameModeInstalled = false; + } } \ No newline at end of file From 48ac1d96c4804fbd13d512285f787168195a02cb Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 21 Sep 2023 21:54:30 -0700 Subject: [PATCH 24/40] Only check for mangohud installation once --- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index a68d3ac3..ac01cf9c 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -35,7 +35,7 @@ public static class Dxvk _ => throw new ArgumentOutOfRangeException(), }; - public static bool MangoHudInstalled => DxvkSettings.MangoHudIsInstalled(); + public static bool MangoHudInstalled { get; } public static bool MangoHudEnabled => Program.Config.MangoHud != MangoHud.None; @@ -62,6 +62,7 @@ public static class Dxvk static Dxvk() { Versions = new Dictionary>(); + MangoHudInstalled = DxvkSettings.MangoHudIsInstalled(); } public static void Initialize() From 930f2f711d818886797a4a2114769e4b1f182a8b Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Fri, 10 Nov 2023 21:15:41 -0800 Subject: [PATCH 25/40] Make Clear Plugins separate from Clear Dalamud --- .../Tabs/SettingsTabTroubleshooting.cs | 22 ++++++++++++------- .../CoreEnvironmentSettings.cs | 1 + src/XIVLauncher.Core/Program.cs | 16 +++++++++----- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs index 820f3b2f..bac44baf 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabTroubleshooting.cs @@ -25,12 +25,6 @@ public override void Draw() ImGui.Separator(); - ImGui.Text("\nReset settings to default."); - if (ImGui.Button("Clear Settings")) - { - Program.ClearSettings(true); - } - ImGui.Text("\nClear the Wine Prefix - delete the ~/.xlcore/wineprefix folder"); if (ImGui.Button("Clear Prefix")) { @@ -43,10 +37,16 @@ public override void Draw() Program.ClearTools(true); } - ImGui.Text("\nClear all the files and folders related to Dalamud. Your settings will not be touched,\nbut all your plugins will be uninstalled, including 3rd-party repos."); + ImGui.Text("\nClear all the files and folders related to Dalamud. This will not uninstall your plugins or their configurations."); if (ImGui.Button("Clear Dalamud")) { - Program.ClearPlugins(true); + Program.ClearDalamud(true); + } + + ImGui.Text("\nClear the installedPlugins folder. This will uninstall your plugins, but will not remove their configurations."); + if (ImGui.Button("Clear Plugins")) + { + Program.ClearPlugins(); } ImGui.Text("\nClear all the log files."); @@ -55,6 +55,12 @@ public override void Draw() Program.ClearLogs(true); } + ImGui.Text("\nReset settings to default."); + if (ImGui.Button("Clear Settings")) + { + Program.ClearSettings(true); + } + ImGui.Text("\nDo all of the above."); if (ImGui.Button("Clear Everything")) { diff --git a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs index 2a78b2b3..b7a3289e 100644 --- a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs +++ b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs @@ -10,6 +10,7 @@ public static class CoreEnvironmentSettings public static bool IsUpgrade => CheckEnvBool("XL_SHOW_UPGRADE"); public static bool ClearSettings => CheckEnvBool("XL_CLEAR_SETTINGS"); public static bool ClearPrefix => CheckEnvBool("XL_CLEAR_PREFIX"); + public static bool ClearDalamud => CheckEnvBool("XL_CLEAR_DALAMUD"); public static bool ClearPlugins => CheckEnvBool("XL_CLEAR_PLUGINS"); public static bool ClearTools => CheckEnvBool("XL_CLEAR_TOOLS"); public static bool ClearLogs => CheckEnvBool("XL_CLEAR_LOGS"); diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 48802b43..dcea1fa0 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -157,6 +157,7 @@ private static void Main(string[] args) { if (CoreEnvironmentSettings.ClearSettings) ClearSettings(); if (CoreEnvironmentSettings.ClearPrefix) ClearPrefix(); + if (CoreEnvironmentSettings.ClearDalamud) ClearDalamud(); if (CoreEnvironmentSettings.ClearPlugins) ClearPlugins(); if (CoreEnvironmentSettings.ClearTools) ClearTools(); if (CoreEnvironmentSettings.ClearLogs) ClearLogs(); @@ -393,17 +394,14 @@ public static void ClearPrefix() storage.GetFolder("wineprefix"); } - public static void ClearPlugins(bool tsbutton = false) + public static void ClearDalamud(bool tsbutton = false) { storage.GetFolder("dalamud").Delete(true); storage.GetFolder("dalamudAssets").Delete(true); - storage.GetFolder("installedPlugins").Delete(true); storage.GetFolder("runtime").Delete(true); if (storage.GetFile("dalamudUI.ini").Exists) storage.GetFile("dalamudUI.ini").Delete(); - if (storage.GetFile("dalamudConfig.json").Exists) storage.GetFile("dalamudConfig.json").Delete(); storage.GetFolder("dalamud"); storage.GetFolder("dalamudAssets"); - storage.GetFolder("installedPlugins"); storage.GetFolder("runtime"); if (tsbutton) { @@ -416,6 +414,13 @@ public static void ClearPlugins(bool tsbutton = false) } } + public static void ClearPlugins() + { + storage.GetFolder("installedPlugins").Delete(true); + storage.GetFolder("installedPlugins"); + if (storage.GetFile("dalamudConfig.json").Exists) storage.GetFile("dalamudConfig.json").Delete(); + } + public static void ClearTools(bool tsbutton = false) { foreach (var winetool in Wine.Versions) @@ -453,7 +458,8 @@ public static void ClearAll(bool tsbutton = false) { ClearSettings(tsbutton); ClearPrefix(); - ClearPlugins(tsbutton); + ClearDalamud(tsbutton); + ClearPlugins(); ClearTools(tsbutton); ClearLogs(true); } From e8fb7cf12d5d4e590e8495f50c32bb4fe50bf9cd Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Fri, 10 Nov 2023 21:26:42 -0800 Subject: [PATCH 26/40] Sort custom wine and dxvk alphabetically --- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 2 +- src/XIVLauncher.Core/UnixCompatibility/Wine.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index ac01cf9c..cbd4a9b3 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -94,7 +94,7 @@ public static void Initialize() return; } - foreach (var dxvkDir in toolDirectory.EnumerateDirectories()) + foreach (var dxvkDir in toolDirectory.EnumerateDirectories().OrderBy(x => x.Name)) { if (Directory.Exists(Path.Combine(dxvkDir.FullName, "x64")) && Directory.Exists(Path.Combine(dxvkDir.FullName, "x32"))) { diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 1606f133..d22ef018 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -61,7 +61,7 @@ public static void Initialize() return; } - foreach (var wineDir in toolDirectory.EnumerateDirectories()) + foreach (var wineDir in toolDirectory.EnumerateDirectories().OrderBy(x => x.Name)) { if (File.Exists(Path.Combine(wineDir.FullName, "bin", "wine64")) || File.Exists(Path.Combine(wineDir.FullName, "bin", "wine"))) From 78376e2162df46c116fa890a0f3e0935c89725bd Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 13 Mar 2024 15:58:46 -0700 Subject: [PATCH 27/40] Make gamemode check a separate function --- .../Components/SettingsPage/Tabs/SettingsTabWine.cs | 2 +- src/XIVLauncher.Core/CoreEnvironmentSettings.cs | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs index e3402950..c1c56ccb 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabWine.cs @@ -29,7 +29,7 @@ public SettingsTabWine() CheckVisibility = () => RuntimeInformation.IsOSPlatform(OSPlatform.Linux), CheckValidity = b => { - if (b == true && !CoreEnvironmentSettings.GameModeInstalled) + if (b == true && !CoreEnvironmentSettings.IsGameModeInstalled()) return "GameMode was not detected on your system."; return null; } diff --git a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs index 278fbde8..6d512393 100644 --- a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs +++ b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs @@ -39,17 +39,20 @@ public static string GetCleanEnvironmentVariable(string envvar, string badstring return string.Join(separator, Array.FindAll(dirty.Split(separator, StringSplitOptions.RemoveEmptyEntries), s => !s.Contains(badstring))); } - static public bool GameModeInstalled { get; } + static private bool? gameModeInstalled = null; - static CoreEnvironmentSettings() - { + static public bool IsGameModeInstalled() + { + if (gameModeInstalled is not null) + return gameModeInstalled ?? false; if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { var handle = IntPtr.Zero; - GameModeInstalled = NativeLibrary.TryLoad("libgamemodeauto.so.0", out handle); + gameModeInstalled = NativeLibrary.TryLoad("libgamemodeauto.so.0", out handle); NativeLibrary.Free(handle); } else - GameModeInstalled = false; + gameModeInstalled = false; + return gameModeInstalled ?? false; } } \ No newline at end of file From 466b8817de8b71a26fa0eeca53cc980b108aed89 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 4 May 2024 11:28:31 -0700 Subject: [PATCH 28/40] Set 8.5 as default wine version --- src/XIVLauncher.Core/Program.cs | 2 +- src/XIVLauncher.Core/UnixCompatibility/Wine.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 635854e8..e5cbd70c 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -127,7 +127,7 @@ private static void LoadConfig(Storage storage) Config.WineType ??= WineType.Managed; if (!Wine.Versions.ContainsKey(Config.WineVersion ?? "")) - Config.WineVersion = "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; + Config.WineVersion = "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; Config.WineBinaryPath ??= "/usr/bin"; Config.WineDebugVars ??= "-all"; diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index d22ef018..3d34dfe7 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -86,10 +86,10 @@ private static string GetDownloadUrl(string? name) public static string GetDefaultVersion() { - if (Versions.ContainsKey("wine-xiv-staging-fsync-git-7.10.r3.g560db77d")) - return "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; if (Versions.ContainsKey("wine-xiv-staging-fsync-git-8.5.r4.g4211bac7")) return "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; + if (Versions.ContainsKey("wine-xiv-staging-fsync-git-7.10.r3.g560db77d")) + return "wine-xiv-staging-fsync-git-7.10.r3.g560db77d"; return Versions.First().Key; } } From 0b6d06749b1de2a88f7532cb78aa269834453c54 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 20 Jun 2024 15:33:49 -0700 Subject: [PATCH 29/40] Suggest dxvk 2.2 only if 2.3.1 has issues with REST --- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 964aca62..3e98735a 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -76,7 +76,7 @@ public static void Initialize() }; Versions["dxvk-2.2"] = new Dictionary() { - {"name", "DXVK 2.2"}, {"desc", "Previous version, using Graphics Pipeline Libs. Use this if you use ReShade Effects Toggler."}, + {"name", "DXVK 2.2"}, {"desc", "Previous version, using Graphics Pipeline Libs. Use this if you have problems with ReShade Effects Toggler."}, {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz"}, {"mark", "Download" } }; From d08dd58ea786b5c23dc217f7255f4a273202e1f7 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 31 Aug 2024 08:14:28 -0700 Subject: [PATCH 30/40] Update to DXVK 2.4 --- lib/FFXIVQuickLauncher | 2 +- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 6b261b07..cdde1fbe 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 6b261b0700ca2f081bfdd6190474034a57735cff +Subproject commit cdde1fbeb31549dea13bd015e76b0b3964543c12 diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index 3e98735a..db389e25 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -68,16 +68,16 @@ static Dxvk() public static void Initialize() { // Add default versions. - Versions["dxvk-2.3.1"] = new Dictionary() + Versions["dxvk-2.4"] = new Dictionary() { - {"name", "DXVK 2.3.1"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, - {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.3.1/dxvk-2.3.1.tar.gz"}, + {"name", "DXVK 2.4"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, + {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.4/dxvk-2.4.tar.gz"}, {"mark", "Download" } }; Versions["dxvk-2.2"] = new Dictionary() { - {"name", "DXVK 2.2"}, {"desc", "Previous version, using Graphics Pipeline Libs. Use this if you have problems with ReShade Effects Toggler."}, - {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz"}, + {"name", "DXVK 2.2"}, {"desc", "Previous version, using Graphics Pipeline Libs. Use this if you have problems with ReShade Effects Toggler (REST)."}, + {"label", "Previous"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.2/dxvk-2.2.tar.gz"}, {"mark", "Download" } }; Versions["dxvk-async-1.10.3"] = new Dictionary() @@ -129,8 +129,8 @@ public static string GetDefaultVersion() { if (Versions.ContainsKey("dxvk-async-1.10.3")) return "dxvk-async-1.10.3"; - if (Versions.ContainsKey("dxvk-2.3")) - return "dxvk-2.3"; + if (Versions.ContainsKey("dxvk-2.4")) + return "dxvk-2.4"; return Versions.First().Key; } From 5daf2e62681b3573bd9cda8948ef6e8b407714a4 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 31 Aug 2024 09:58:47 -0700 Subject: [PATCH 31/40] Update submodule --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index cdde1fbe..04da286c 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit cdde1fbeb31549dea13bd015e76b0b3964543c12 +Subproject commit 04da286ca9442133724a3611172737c24fb97ef4 From add221392b5f65e05015e0092f258eaf428db272 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 5 Oct 2024 20:14:48 -0700 Subject: [PATCH 32/40] Update to DXVK 2.4.1 --- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index db389e25..b28b6f2a 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -70,8 +70,8 @@ public static void Initialize() // Add default versions. Versions["dxvk-2.4"] = new Dictionary() { - {"name", "DXVK 2.4"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, - {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.4/dxvk-2.4.tar.gz"}, + {"name", "DXVK 2.4.1"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, + {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.4.1/dxvk-2.4.1.tar.gz"}, {"mark", "Download" } }; Versions["dxvk-2.2"] = new Dictionary() From 7b873f832435766dc3c2746ed801e9cb12c29e5f Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 5 Oct 2024 20:34:44 -0700 Subject: [PATCH 33/40] Update submodule --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 04da286c..9e21f074 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 04da286ca9442133724a3611172737c24fb97ef4 +Subproject commit 9e21f074303be3ec294b99520057a55379fdaa09 From c0252c21935bedab2fbf8fd89c098289c2f28037 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 6 Nov 2024 16:58:53 -0800 Subject: [PATCH 34/40] Update submodule --- lib/FFXIVQuickLauncher | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/FFXIVQuickLauncher b/lib/FFXIVQuickLauncher index 9e21f074..19c603de 160000 --- a/lib/FFXIVQuickLauncher +++ b/lib/FFXIVQuickLauncher @@ -1 +1 @@ -Subproject commit 9e21f074303be3ec294b99520057a55379fdaa09 +Subproject commit 19c603de1ec038136bdb14d65924bd525131d3fb From 5feaa6208af02734c30202588e36d72059a00abb Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 6 Nov 2024 17:02:43 -0800 Subject: [PATCH 35/40] Copy over compatibility-rework-2 from FFXIVQuickLauncher --- .../Compatibility/CompatibilityTools.cs | 229 ++++++++++++------ .../Compatibility/Dxvk.cs | 55 ----- .../Compatibility/DxvkSettings.cs | 85 +++++++ .../Compatibility/WineSettings.cs | 32 ++- .../UnixDalamudRunner.cs | 32 ++- 5 files changed, 277 insertions(+), 156 deletions(-) delete mode 100644 src/XIVLauncher.Common.Unix/Compatibility/Dxvk.cs create mode 100644 src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs diff --git a/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs b/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs index 8216526f..afe43885 100644 --- a/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs +++ b/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs @@ -1,13 +1,12 @@ using System; using System.Collections.Generic; -using System.Collections.Specialized; using System.Diagnostics; using System.IO; using System.Linq; -using System.Net.Http; using System.Threading.Tasks; -using Serilog; +using System.Net.Http; using XIVLauncher.Common.Util; +using Serilog; #if FLATPAK #warning THIS IS A FLATPAK BUILD!!! @@ -17,56 +16,46 @@ namespace XIVLauncher.Common.Unix.Compatibility; public class CompatibilityTools { - private DirectoryInfo toolDirectory; + private DirectoryInfo wineDirectory; + private DirectoryInfo dxvkDirectory; private StreamWriter logWriter; -#if WINE_XIV_ARCH_LINUX - private const string WINE_XIV_RELEASE_URL = "https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-arch-8.5.r4.g4211bac7.tar.xz"; -#elif WINE_XIV_FEDORA_LINUX - private const string WINE_XIV_RELEASE_URL = "https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-fedora-8.5.r4.g4211bac7.tar.xz"; -#else - private const string WINE_XIV_RELEASE_URL = "https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-ubuntu-8.5.r4.g4211bac7.tar.xz"; -#endif - private const string WINE_XIV_RELEASE_NAME = "wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"; - public bool IsToolReady { get; private set; } public WineSettings Settings { get; private set; } - private string WineBinPath => Settings.StartupType == WineStartupType.Managed ? - Path.Combine(toolDirectory.FullName, WINE_XIV_RELEASE_NAME, "bin") : - Settings.CustomBinPath; - private string Wine64Path => Path.Combine(WineBinPath, "wine64"); - private string WineServerPath => Path.Combine(WineBinPath, "wineserver"); + public DxvkSettings DxvkSettings { get; private set; } - public bool IsToolDownloaded => File.Exists(Wine64Path) && Settings.Prefix.Exists; + public bool IsToolDownloaded => File.Exists(Settings.WinePath) && Settings.Prefix.Exists; - private readonly Dxvk.DxvkHudType hudType; + public bool IsFlatpak { get; } + private readonly bool gamemodeOn; - private readonly string dxvkAsyncOn; - public CompatibilityTools(WineSettings wineSettings, Dxvk.DxvkHudType hudType, bool? gamemodeOn, bool? dxvkAsyncOn, DirectoryInfo toolsFolder) + private Dictionary extraEnvironmentVars; + + public CompatibilityTools(WineSettings wineSettings, DxvkSettings dxvkSettings, bool? gamemodeOn, DirectoryInfo toolsFolder, bool isFlatpak, Dictionary extraEnvVars = null) { this.Settings = wineSettings; - this.hudType = hudType; + this.DxvkSettings = dxvkSettings; this.gamemodeOn = gamemodeOn ?? false; - this.dxvkAsyncOn = (dxvkAsyncOn ?? false) ? "1" : "0"; - this.toolDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "beta")); + // These are currently unused. Here for future use. + this.IsFlatpak = isFlatpak; + this.extraEnvironmentVars = extraEnvVars ?? new Dictionary(); + + this.wineDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "wine")); this.dxvkDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "dxvk")); this.logWriter = new StreamWriter(wineSettings.LogFile.FullName); - if (wineSettings.StartupType == WineStartupType.Managed) - { - if (!this.toolDirectory.Exists) - this.toolDirectory.Create(); + if (!this.wineDirectory.Exists) + this.wineDirectory.Create(); - if (!this.dxvkDirectory.Exists) - this.dxvkDirectory.Create(); - } + if (!this.dxvkDirectory.Exists) + this.dxvkDirectory.Create(); if (!wineSettings.Prefix.Exists) wineSettings.Prefix.Create(); @@ -74,30 +63,60 @@ public CompatibilityTools(WineSettings wineSettings, Dxvk.DxvkHudType hudType, b public async Task EnsureTool(DirectoryInfo tempPath) { - if (!File.Exists(Wine64Path)) + if (!File.Exists(Settings.WinePath)) { - Log.Information("Compatibility tool does not exist, downloading"); - await DownloadTool(tempPath).ConfigureAwait(false); + Log.Information($"Compatibility tool does not exist, downloading {Settings.DownloadUrl}"); + await DownloadTool(wineDirectory, Settings.DownloadUrl).ConfigureAwait(false); } - EnsurePrefix(); - await Dxvk.InstallDxvk(Settings.Prefix, dxvkDirectory).ConfigureAwait(false); + + if (DxvkSettings.Enabled) + await InstallDxvk().ConfigureAwait(false); IsToolReady = true; } - private async Task DownloadTool(DirectoryInfo tempPath) + private async Task InstallDxvk() { - using var client = new HttpClient(); - var tempFilePath = Path.Combine(tempPath.FullName, $"{Guid.NewGuid()}"); + var dxvkPath = Path.Combine(dxvkDirectory.FullName, DxvkSettings.FolderName, "x64"); + if (!Directory.Exists(dxvkPath)) + { + Log.Information($"DXVK does not exist, downloading {DxvkSettings.DownloadUrl}"); + await DownloadTool(dxvkDirectory, DxvkSettings.DownloadUrl).ConfigureAwait(false); + } - await File.WriteAllBytesAsync(tempFilePath, await client.GetByteArrayAsync(WINE_XIV_RELEASE_URL).ConfigureAwait(false)).ConfigureAwait(false); + var system32 = Path.Combine(Settings.Prefix.FullName, "drive_c", "windows", "system32"); + var files = Directory.GetFiles(dxvkPath); - PlatformHelpers.Untar(tempFilePath, this.toolDirectory.FullName); + foreach (string fileName in files) + { + File.Copy(fileName, Path.Combine(system32, Path.GetFileName(fileName)), true); + } - Log.Information("Compatibility tool successfully extracted to {Path}", this.toolDirectory.FullName); + // 32-bit files for Directx9. + var dxvkPath32 = Path.Combine(dxvkDirectory.FullName, DxvkSettings.FolderName, "x32"); + var syswow64 = Path.Combine(Settings.Prefix.FullName, "drive_c", "windows", "syswow64"); - File.Delete(tempFilePath); + if (Directory.Exists(dxvkPath32)) + { + files = Directory.GetFiles(dxvkPath32); + + foreach (string fileName in files) + { + File.Copy(fileName, Path.Combine(syswow64, Path.GetFileName(fileName)), true); + } + } + } + + private async Task DownloadTool(DirectoryInfo installDirectory, string downloadUrl) + { + using var client = new HttpClient(); + var tempPath = Path.GetTempFileName(); + + File.WriteAllBytes(tempPath, await client.GetByteArrayAsync(downloadUrl)); + PlatformHelpers.Untar(tempPath, installDirectory.FullName); + + File.Delete(tempPath); } private void ResetPrefix() @@ -118,7 +137,7 @@ public void EnsurePrefix() public Process RunInPrefix(string command, string workingDirectory = "", IDictionary environment = null, bool redirectOutput = false, bool writeLog = false, bool wineD3D = false) { - var psi = new ProcessStartInfo(Wine64Path); + var psi = new ProcessStartInfo(Settings.WinePath); psi.Arguments = command; Log.Verbose("Running in prefix: {FileName} {Arguments}", psi.FileName, command); @@ -127,7 +146,7 @@ public Process RunInPrefix(string command, string workingDirectory = "", IDictio public Process RunInPrefix(string[] args, string workingDirectory = "", IDictionary environment = null, bool redirectOutput = false, bool writeLog = false, bool wineD3D = false) { - var psi = new ProcessStartInfo(Wine64Path); + var psi = new ProcessStartInfo(Settings.WinePath); foreach (var arg in args) psi.ArgumentList.Add(arg); @@ -135,7 +154,7 @@ public Process RunInPrefix(string[] args, string workingDirectory = "", IDiction return RunInPrefix(psi, workingDirectory, environment, redirectOutput, writeLog, wineD3D); } - private void MergeDictionaries(StringDictionary a, IDictionary b) + private void MergeDictionaries(IDictionary a, IDictionary b) { if (b is null) return; @@ -143,12 +162,34 @@ private void MergeDictionaries(StringDictionary a, IDictionary b foreach (var keyValuePair in b) { if (a.ContainsKey(keyValuePair.Key)) - a[keyValuePair.Key] = keyValuePair.Value; + { + if (keyValuePair.Key == "LD_PRELOAD") + a[keyValuePair.Key] = MergeLDPreload(a[keyValuePair.Key], keyValuePair.Value); + else + a[keyValuePair.Key] = keyValuePair.Value; + } else a.Add(keyValuePair.Key, keyValuePair.Value); } } + private string MergeLDPreload(string a, string b) + { + a ??= ""; + b ??= ""; + return (a.Trim(':') + ":" + b.Trim(':')).Trim(':'); + } + + public void AddEnvironmentVar(string key, string value) + { + extraEnvironmentVars.Add(key, value); + } + + public void AddEnvironmentVars(IDictionary env) + { + MergeDictionaries(extraEnvironmentVars, env); + } + private Process RunInPrefix(ProcessStartInfo psi, string workingDirectory, IDictionary environment, bool redirectOutput, bool writeLog, bool wineD3D) { psi.RedirectStandardOutput = redirectOutput; @@ -156,48 +197,38 @@ private Process RunInPrefix(ProcessStartInfo psi, string workingDirectory, IDict psi.UseShellExecute = false; psi.WorkingDirectory = workingDirectory; - var wineEnviromentVariables = new Dictionary(); - wineEnviromentVariables.Add("WINEPREFIX", Settings.Prefix.FullName); - wineEnviromentVariables.Add("WINEDLLOVERRIDES", $"msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi={(wineD3D ? "b" : "n")}"); + wineD3D = !DxvkSettings.Enabled || wineD3D; + + var wineEnvironmentVariables = new Dictionary(); + wineEnvironmentVariables.Add("WINEPREFIX", Settings.Prefix.FullName); + wineEnvironmentVariables.Add("WINEDLLOVERRIDES", $"msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi={(wineD3D ? "b" : "n,b")}"); if (!string.IsNullOrEmpty(Settings.DebugVars)) { - wineEnviromentVariables.Add("WINEDEBUG", Settings.DebugVars); + wineEnvironmentVariables.Add("WINEDEBUG", Settings.DebugVars); } - wineEnviromentVariables.Add("XL_WINEONLINUX", "true"); - string ldPreload = Environment.GetEnvironmentVariable("LD_PRELOAD") ?? ""; - - string dxvkHud = hudType switch - { - Dxvk.DxvkHudType.None => "0", - Dxvk.DxvkHudType.Fps => "fps", - Dxvk.DxvkHudType.Full => "full", - _ => throw new ArgumentOutOfRangeException() - }; - - if (this.gamemodeOn == true && !ldPreload.Contains("libgamemodeauto.so.0")) - { - ldPreload = ldPreload.Equals("") ? "libgamemodeauto.so.0" : ldPreload + ":libgamemodeauto.so.0"; - } + wineEnvironmentVariables.Add("XL_WINEONLINUX", "true"); - wineEnviromentVariables.Add("DXVK_HUD", dxvkHud); - wineEnviromentVariables.Add("DXVK_ASYNC", dxvkAsyncOn); - wineEnviromentVariables.Add("WINEESYNC", Settings.EsyncOn); - wineEnviromentVariables.Add("WINEFSYNC", Settings.FsyncOn); + if (this.gamemodeOn) + wineEnvironmentVariables.Add("LD_PRELOAD", MergeLDPreload("libgamemodeauto.so.0" , Environment.GetEnvironmentVariable("LD_PRELOAD"))); - wineEnviromentVariables.Add("LD_PRELOAD", ldPreload); + foreach (var dxvkVar in DxvkSettings.Environment) + wineEnvironmentVariables.Add(dxvkVar.Key, dxvkVar.Value); + wineEnvironmentVariables.Add("WINEESYNC", Settings.EsyncOn); + wineEnvironmentVariables.Add("WINEFSYNC", Settings.FsyncOn); - MergeDictionaries(psi.EnvironmentVariables, wineEnviromentVariables); - MergeDictionaries(psi.EnvironmentVariables, environment); + MergeDictionaries(psi.Environment, wineEnvironmentVariables); + MergeDictionaries(psi.Environment, extraEnvironmentVars); // Allow extraEnvironmentVars to override what we set here. + MergeDictionaries(psi.Environment, environment); #if FLATPAK_NOTRIGHTNOW psi.FileName = "flatpak-spawn"; psi.ArgumentList.Insert(0, "--host"); - psi.ArgumentList.Insert(1, Wine64Path); + psi.ArgumentList.Insert(1, Settings.WinePath); - foreach (KeyValuePair envVar in wineEnviromentVariables) + foreach (KeyValuePair envVar in wineEnvironmentVariables) { psi.ArgumentList.Insert(1, $"--env={envVar.Key}={envVar.Value}"); } @@ -257,14 +288,54 @@ public Int32 GetUnixProcessId(Int32 winePid) { var wineDbg = RunInPrefix("winedbg --command \"info procmap\"", redirectOutput: true); var output = wineDbg.StandardOutput.ReadToEnd(); - if (output.Contains("syntax error\n")) - return 0; + if (output.Contains("syntax error\n") || output.Contains("Exception c0000005")) // Proton8 wine changed the error message + { + var processName = GetProcessName(winePid); + return GetUnixProcessIdByName(processName); + } var matchingLines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries).Skip(1).Where( l => int.Parse(l.Substring(1, 8), System.Globalization.NumberStyles.HexNumber) == winePid); var unixPids = matchingLines.Select(l => int.Parse(l.Substring(10, 8), System.Globalization.NumberStyles.HexNumber)).ToArray(); return unixPids.FirstOrDefault(); } + private string GetProcessName(Int32 winePid) + { + var wineDbg = RunInPrefix("winedbg --command \"info proc\"", redirectOutput: true); + var output = wineDbg.StandardOutput.ReadToEnd(); + var matchingLines = output.Split('\n', StringSplitOptions.RemoveEmptyEntries).Skip(1).Where( + l => int.Parse(l.Substring(1, 8), System.Globalization.NumberStyles.HexNumber) == winePid); + var processNames = matchingLines.Select(l => l.Substring(20).Trim('\'')).ToArray(); + return processNames.FirstOrDefault(); + } + + private Int32 GetUnixProcessIdByName(string executableName) + { + int closest = 0; + int early = 0; + var currentProcess = Process.GetCurrentProcess(); // Gets XIVLauncher.Core's process + bool nonunique = false; + foreach (var process in Process.GetProcessesByName(executableName)) + { + if (process.Id < currentProcess.Id) + { + early = process.Id; + continue; // Process was launched before XIVLauncher.Core + } + // Assume that the closest PID to XIVLauncher.Core's is the correct one. But log an error if more than one is found. + if ((closest - currentProcess.Id) > (process.Id - currentProcess.Id) || closest == 0) + { + if (closest != 0) nonunique = true; + closest = process.Id; + } + if (nonunique) Log.Error($"More than one {executableName} found! Selecting the most likely match with process id {closest}."); + } + // Deal with rare edge-case where pid rollover causes the ffxiv pid to be lower than XLCore's. + if (closest == 0 && early != 0) closest = early; + if (closest != 0) Log.Verbose($"Process for {executableName} found using fallback method: {closest}. XLCore pid: {currentProcess.Id}"); + return closest; + } + public string UnixToWinePath(string unixPath) { var launchArguments = new string[] { "winepath", "--windows", unixPath }; @@ -282,7 +353,7 @@ public void AddRegistryKey(string key, string value, string data) public void Kill() { - var psi = new ProcessStartInfo(WineServerPath) + var psi = new ProcessStartInfo(Settings.WineServerPath) { Arguments = "-k" }; diff --git a/src/XIVLauncher.Common.Unix/Compatibility/Dxvk.cs b/src/XIVLauncher.Common.Unix/Compatibility/Dxvk.cs deleted file mode 100644 index 62e3a303..00000000 --- a/src/XIVLauncher.Common.Unix/Compatibility/Dxvk.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.IO; -using System.Net.Http; -using System.Threading.Tasks; -using Serilog; -using XIVLauncher.Common.Util; - -namespace XIVLauncher.Common.Unix.Compatibility; - -public static class Dxvk -{ - private const string DXVK_DOWNLOAD = "https://github.com/Sporif/dxvk-async/releases/download/1.10.1/dxvk-async-1.10.1.tar.gz"; - private const string DXVK_NAME = "dxvk-async-1.10.1"; - - public static async Task InstallDxvk(DirectoryInfo prefix, DirectoryInfo installDirectory) - { - var dxvkPath = Path.Combine(installDirectory.FullName, DXVK_NAME, "x64"); - - if (!Directory.Exists(dxvkPath)) - { - Log.Information("DXVK does not exist, downloading"); - await DownloadDxvk(installDirectory).ConfigureAwait(false); - } - - var system32 = Path.Combine(prefix.FullName, "drive_c", "windows", "system32"); - var files = Directory.GetFiles(dxvkPath); - - foreach (string fileName in files) - { - File.Copy(fileName, Path.Combine(system32, Path.GetFileName(fileName)), true); - } - } - - private static async Task DownloadDxvk(DirectoryInfo installDirectory) - { - using var client = new HttpClient(); - var tempPath = PlatformHelpers.GetTempFileName(); - - File.WriteAllBytes(tempPath, await client.GetByteArrayAsync(DXVK_DOWNLOAD)); - PlatformHelpers.Untar(tempPath, installDirectory.FullName); - - File.Delete(tempPath); - } - - public enum DxvkHudType - { - [SettingsDescription("None", "Show nothing")] - None, - - [SettingsDescription("FPS", "Only show FPS")] - Fps, - - [SettingsDescription("Full", "Show everything")] - Full, - } -} \ No newline at end of file diff --git a/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs new file mode 100644 index 00000000..78530c8a --- /dev/null +++ b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs @@ -0,0 +1,85 @@ +using System.IO; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using System.Linq; +using Serilog; + +namespace XIVLauncher.Common.Unix.Compatibility; + +public class DxvkSettings +{ + public bool Enabled { get; } + + public string FolderName { get; } + + public string DownloadUrl { get; } + + public Dictionary Environment { get; } + + public DxvkSettings(string folder, string url, string storageFolder, bool async, int maxFrameRate, bool dxvkHudEnabled, string dxvkHudString, bool mangoHudEnabled = false, bool mangoHudCustomIsFile = false, string customMangoHud = "", bool enabled = true) + { + FolderName = folder; + DownloadUrl = url; + Enabled = enabled; + + Environment = new Dictionary + { + { "DXVK_LOG_PATH", Path.Combine(storageFolder, "logs") }, + }; + + if (maxFrameRate != 0) + Environment.Add("DXVK_FRAME_RATE", (maxFrameRate).ToString()); + + if (async) + Environment.Add("DXVK_ASYNC", "1"); + + var dxvkCachePath = new DirectoryInfo(Path.Combine(storageFolder, "compatibilitytool", "dxvk", "cache")); + if (!dxvkCachePath.Exists) dxvkCachePath.Create(); + Environment.Add("DXVK_STATE_CACHE_PATH", Path.Combine(dxvkCachePath.FullName, folder)); + + if (dxvkHudEnabled) + Environment.Add("DXVK_HUD", DxvkHudStringIsValid(dxvkHudString) ? dxvkHudString : "1"); + + if (mangoHudEnabled && MangoHudIsInstalled()) + { + Environment.Add("MANGOHUD", "1"); + if (mangoHudCustomIsFile) + { + if (File.Exists(customMangoHud)) + Environment.Add("MANGOHUD_CONFIGFILE", customMangoHud); + else + Environment.Add("MANGOHUD_CONFIG", ""); + } + else + { + Environment.Add("MANGOHUD_CONFIG", customMangoHud); + } + } + } + + public static bool DxvkHudStringIsValid(string customHud) + { + var ALLOWED_CHARS = "^[0-9a-zA-Z,=.]+$"; + var ALLOWED_WORDS = "^(?:devinfo|fps|frametimes|submissions|drawcalls|pipelines|descriptors|memory|gpuload|version|api|cs|compiler|samplers|scale=(?:[0-9])*(?:.(?:[0-9])+)?)$"; + + if (string.IsNullOrWhiteSpace(customHud)) return false; + if (customHud == "full") return true; + if (customHud == "1") return true; + if (!Regex.IsMatch(customHud, ALLOWED_CHARS)) return false; + + string[] hudvars = customHud.Split(","); + + return hudvars.All(hudvar => Regex.IsMatch(hudvar, ALLOWED_WORDS)); + } + + public static bool MangoHudIsInstalled() + { + var usrLib = Path.Combine("/", "usr", "lib", "mangohud", "libMangoHud.so"); // fedora uses this + var usrLib64 = Path.Combine("/", "usr", "lib64", "mangohud", "libMangoHud.so"); // arch and openSUSE use this + var flatpak = Path.Combine("/", "usr", "lib", "extensions", "vulkan", "MangoHud", "lib", "x86_64-linux-gnu", "libMangoHud.so"); + var debuntu = Path.Combine("/", "usr", "lib", "x86_64-linux-gnu", "mangohud", "libMangoHud.so"); + if (File.Exists(usrLib64) || File.Exists(usrLib) || File.Exists(flatpak) || File.Exists(debuntu)) + return true; + return false; + } +} \ No newline at end of file diff --git a/src/XIVLauncher.Common.Unix/Compatibility/WineSettings.cs b/src/XIVLauncher.Common.Unix/Compatibility/WineSettings.cs index 9b122f7a..ed8d16df 100644 --- a/src/XIVLauncher.Common.Unix/Compatibility/WineSettings.cs +++ b/src/XIVLauncher.Common.Unix/Compatibility/WineSettings.cs @@ -2,32 +2,38 @@ namespace XIVLauncher.Common.Unix.Compatibility; -public enum WineStartupType +public class WineSettings { - [SettingsDescription("Managed by XIVLauncher", "The game installation and wine setup is managed by XIVLauncher - you can leave it up to us.")] - Managed, + public bool IsManaged { get; private set; } - [SettingsDescription("Custom", "Point XIVLauncher to a custom location containing wine binaries to run the game with.")] - Custom, -} + public string WineServerPath => Path.Combine(BinPath, "wineserver"); -public class WineSettings -{ - public WineStartupType StartupType { get; private set; } - public string CustomBinPath { get; private set; } + public string WinePath => File.Exists(Path.Combine(BinPath, "wine64")) ? Path.Combine(BinPath, "wine64") : Path.Combine(BinPath, "wine"); + + private string BinPath; + + public string FolderName; + + public string DownloadUrl; public string EsyncOn { get; private set; } + public string FsyncOn { get; private set; } public string DebugVars { get; private set; } + public FileInfo LogFile { get; private set; } public DirectoryInfo Prefix { get; private set; } - public WineSettings(WineStartupType? startupType, string customBinPath, string debugVars, FileInfo logFile, DirectoryInfo prefix, bool? esyncOn, bool? fsyncOn) + public WineSettings(bool isManaged, string customBinPath, string managedFolder, string managedUrl, DirectoryInfo storageFolder, string debugVars, FileInfo logFile, DirectoryInfo prefix, bool? esyncOn, bool? fsyncOn) { - this.StartupType = startupType ?? WineStartupType.Custom; - this.CustomBinPath = customBinPath; + // storageFolder is the path to .xlcore folder. managedFolder is the foldername inside the tarball that will be downloaded from managedUrl. + IsManaged = isManaged; + FolderName = managedFolder; + DownloadUrl = managedUrl; + BinPath = (isManaged) ? Path.Combine(storageFolder.FullName, "compatibilitytool", "wine", managedFolder, "bin") : customBinPath; + this.EsyncOn = (esyncOn ?? false) ? "1" : "0"; this.FsyncOn = (fsyncOn ?? false) ? "1" : "0"; this.DebugVars = debugVars; diff --git a/src/XIVLauncher.Common.Unix/UnixDalamudRunner.cs b/src/XIVLauncher.Common.Unix/UnixDalamudRunner.cs index ef1b8545..b2fde02c 100644 --- a/src/XIVLauncher.Common.Unix/UnixDalamudRunner.cs +++ b/src/XIVLauncher.Common.Unix/UnixDalamudRunner.cs @@ -74,12 +74,28 @@ public UnixDalamudRunner(CompatibilityTools compatibility, DirectoryInfo dotnetR launchArguments.Add(gameArgs); var dalamudProcess = compatibility.RunInPrefix(string.Join(" ", launchArguments), environment: environment, redirectOutput: true, writeLog: true); - var output = dalamudProcess.StandardOutput.ReadLine(); - if (output == null) - throw new DalamudRunnerException("An internal Dalamud error has occured"); + DalamudConsoleOutput dalamudConsoleOutput = null; + int invalidJsonCount = 0; - Console.WriteLine(output); + // Keep checking for valid json output, but only 5 times. If it's still erroring out at that point, give up. + while (dalamudConsoleOutput == null && invalidJsonCount < 5) + { + var output = dalamudProcess.StandardOutput.ReadLine(); + if (output == null) + throw new DalamudRunnerException("An internal Dalamud error has occured"); + Console.WriteLine(output); + + try + { + dalamudConsoleOutput = JsonConvert.DeserializeObject(output); + } + catch (Exception ex) + { + Log.Warning(ex, $"Couldn't parse Dalamud output: {output}"); + } + invalidJsonCount++; + } new Thread(() => { @@ -89,17 +105,15 @@ public UnixDalamudRunner(CompatibilityTools compatibility, DirectoryInfo dotnetR if (output != null) Console.WriteLine(output); } - }).Start(); try { - var dalamudConsoleOutput = JsonConvert.DeserializeObject(output); var unixPid = compatibility.GetUnixProcessId(dalamudConsoleOutput.Pid); if (unixPid == 0) { - Log.Error("Could not retrive Unix process ID, this feature currently requires a patched wine version"); + Log.Error("Could not retrieve Unix process ID"); return null; } @@ -107,9 +121,9 @@ public UnixDalamudRunner(CompatibilityTools compatibility, DirectoryInfo dotnetR Log.Verbose($"Got game process handle {gameProcess.Handle} with Unix pid {gameProcess.Id} and Wine pid {dalamudConsoleOutput.Pid}"); return gameProcess; } - catch (JsonReaderException ex) + catch (Exception ex) { - Log.Error(ex, $"Couldn't parse Dalamud output: {output}"); + Log.Error(ex, $"Could not retrieve game Process information"); return null; } } From f5e1981c28ae19cc32927d670ffbccfda332bd72 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Wed, 6 Nov 2024 17:20:29 -0800 Subject: [PATCH 36/40] Fix broken dxvk version and improve steam deck detection --- src/XIVLauncher.Core/CoreEnvironmentSettings.cs | 6 ++++++ src/XIVLauncher.Core/Program.cs | 5 +++-- src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs | 10 +++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs index 5dc782c4..2fcb70d2 100644 --- a/src/XIVLauncher.Core/CoreEnvironmentSettings.cs +++ b/src/XIVLauncher.Core/CoreEnvironmentSettings.cs @@ -7,7 +7,9 @@ namespace XIVLauncher.Core; public static class CoreEnvironmentSettings { public static bool? IsDeck => CheckEnvBoolOrNull("XL_DECK"); + public static bool IsSteamDeckVar => CheckEnvBool("SteamDeck"); public static bool? IsDeckGameMode => CheckEnvBoolOrNull("XL_GAMEMODE"); + public static bool IsSteamGamepadUIVar => CheckEnvBool("SteamGamepadUI"); public static bool? IsDeckFirstRun => CheckEnvBoolOrNull("XL_FIRSTRUN"); public static bool IsUpgrade => CheckEnvBool("XL_SHOW_UPGRADE"); public static bool ClearSettings => CheckEnvBool("XL_CLEAR_SETTINGS"); @@ -21,6 +23,10 @@ public static class CoreEnvironmentSettings public static bool IsSteamCompatTool => CheckEnvBool("XL_SCT"); public static uint SteamAppId => GetAppId(System.Environment.GetEnvironmentVariable("SteamAppId")); public static uint AltAppID => GetAppId(System.Environment.GetEnvironmentVariable("XL_APPID")); + public static string HOME => System.Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); + public static string XDG_CONFIG_HOME => string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("XDG_CONFIG_HOME")) ? Path.Combine(HOME, ".config") : System.Environment.GetEnvironmentVariable("XDG_CONFIG_HOME") ?? ""; + public static string XDG_DATA_HOME => string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("XDG_DATA_HOME")) ? Path.Combine(HOME, ".local", "share") : System.Environment.GetEnvironmentVariable("XDG_DATA_HOME") ?? ""; + private static bool CheckEnvBool(string key) { diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index b2204ce6..641d238b 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -59,12 +59,13 @@ sealed class Program public static DirectoryInfo DotnetRuntime => storage.GetFolder("runtime"); // TODO: We don't have the steamworks api for this yet. + // SteamDeck=1 on Steam Deck by default. SteamGamepadUI=1 in Big Picture / Gaming Mode. public static bool IsSteamDeckHardware => CoreEnvironmentSettings.IsDeck.HasValue ? CoreEnvironmentSettings.IsDeck.Value : - Directory.Exists("/home/deck") || (CoreEnvironmentSettings.IsDeckGameMode ?? false) || (CoreEnvironmentSettings.IsDeckFirstRun ?? false); + CoreEnvironmentSettings.IsSteamDeckVar || (CoreEnvironmentSettings.IsDeckGameMode ?? false) || (CoreEnvironmentSettings.IsDeckFirstRun ?? false); public static bool IsSteamDeckGamingMode => CoreEnvironmentSettings.IsDeckGameMode.HasValue ? CoreEnvironmentSettings.IsDeckGameMode.Value : - Steam != null && Steam.IsValid && Steam.IsRunningOnSteamDeck(); + Steam != null && Steam.IsValid && Steam.IsRunningOnSteamDeck() && CoreEnvironmentSettings.IsSteamGamepadUIVar; private const string APP_NAME = "xlcore"; diff --git a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs index b28b6f2a..8608b63d 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Dxvk.cs @@ -28,7 +28,7 @@ public static class Dxvk public static string DxvkHudString => Program.Config.DxvkHud switch { DxvkHud.None => "", - DxvkHud.Custom => Program.Config.DxvkHudCustom, + DxvkHud.Custom => Program.Config.DxvkHudCustom ?? "", DxvkHud.Default => "1", DxvkHud.Fps => "fps", DxvkHud.Full => "full", @@ -46,8 +46,8 @@ public static class Dxvk MangoHud.None => "", MangoHud.Default => "", MangoHud.Full => "full", - MangoHud.CustomString => Program.Config.MangoHudCustomString, - MangoHud.CustomFile => Program.Config.MangoHudCustomFile, + MangoHud.CustomString => Program.Config.MangoHudCustomString ?? "", + MangoHud.CustomFile => Program.Config.MangoHudCustomFile ?? "", _ => throw new ArgumentOutOfRangeException(), }; @@ -55,7 +55,7 @@ public static class Dxvk public static string MANGOHUD_CONFIG => "ram,vram,resolution,vulkan_driver,engine_version,wine,frame_timing=0"; - public static string MANGOHUD_CONFIGFILE => Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".config", "MangoHud", "MangoHud.conf"); + public static string MANGOHUD_CONFIGFILE => Path.Combine(CoreEnvironmentSettings.XDG_CONFIG_HOME, "MangoHud", "MangoHud.conf"); public static Dictionary> Versions { get; private set; } @@ -68,7 +68,7 @@ static Dxvk() public static void Initialize() { // Add default versions. - Versions["dxvk-2.4"] = new Dictionary() + Versions["dxvk-2.4.1"] = new Dictionary() { {"name", "DXVK 2.4.1"}, {"desc", "Latest version, using Graphics Pipeline Libs. Async no longer needed."}, {"label", "Current"}, {"url", "https://github.com/doitsujin/dxvk/releases/download/v2.4.1/dxvk-2.4.1.tar.gz"}, From 8fa6c39aceefffde7f6a101181ead326ab87b018 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Thu, 7 Nov 2024 14:42:39 -0800 Subject: [PATCH 37/40] Move OSInfo to XL.Common.Unix * Rename to LinuxInfo * Add file find functions to LinuxInfo * Add library search paths to LinuxInfo * Change Platform object to IsLinux bool * Changed IsFlatpak bool to Container enum (flatpak, snap, none) * Reworked DxvkSettings.IsMangoHudInstalled() --- .../Compatibility/CompatibilityTools.cs | 12 +- .../Compatibility/DxvkSettings.cs | 15 +- src/XIVLauncher.Common.Unix/LinuxContainer.cs | 10 + src/XIVLauncher.Common.Unix/LinuxDistro.cs | 12 + src/XIVLauncher.Common.Unix/LinuxInfo.cs | 210 ++++++++++++++++++ .../SettingsPage/Tabs/SettingsTabDebug.cs | 12 +- src/XIVLauncher.Core/OSInfo.cs | 132 ----------- src/XIVLauncher.Core/Program.cs | 5 +- .../UnixCompatibility/Wine.cs | 5 +- 9 files changed, 256 insertions(+), 157 deletions(-) create mode 100644 src/XIVLauncher.Common.Unix/LinuxContainer.cs create mode 100644 src/XIVLauncher.Common.Unix/LinuxDistro.cs create mode 100644 src/XIVLauncher.Common.Unix/LinuxInfo.cs delete mode 100644 src/XIVLauncher.Core/OSInfo.cs diff --git a/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs b/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs index afe43885..28d92c00 100644 --- a/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs +++ b/src/XIVLauncher.Common.Unix/Compatibility/CompatibilityTools.cs @@ -8,10 +8,6 @@ using XIVLauncher.Common.Util; using Serilog; -#if FLATPAK -#warning THIS IS A FLATPAK BUILD!!! -#endif - namespace XIVLauncher.Common.Unix.Compatibility; public class CompatibilityTools @@ -29,21 +25,17 @@ public class CompatibilityTools public DxvkSettings DxvkSettings { get; private set; } public bool IsToolDownloaded => File.Exists(Settings.WinePath) && Settings.Prefix.Exists; - - public bool IsFlatpak { get; } - + private readonly bool gamemodeOn; private Dictionary extraEnvironmentVars; - public CompatibilityTools(WineSettings wineSettings, DxvkSettings dxvkSettings, bool? gamemodeOn, DirectoryInfo toolsFolder, bool isFlatpak, Dictionary extraEnvVars = null) + public CompatibilityTools(WineSettings wineSettings, DxvkSettings dxvkSettings, bool? gamemodeOn, DirectoryInfo toolsFolder, Dictionary extraEnvVars = null) { this.Settings = wineSettings; this.DxvkSettings = dxvkSettings; this.gamemodeOn = gamemodeOn ?? false; - // These are currently unused. Here for future use. - this.IsFlatpak = isFlatpak; this.extraEnvironmentVars = extraEnvVars ?? new Dictionary(); this.wineDirectory = new DirectoryInfo(Path.Combine(toolsFolder.FullName, "wine")); diff --git a/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs index 78530c8a..4a64016c 100644 --- a/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs +++ b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs @@ -3,6 +3,7 @@ using System.Text.RegularExpressions; using System.Linq; using Serilog; +using XIVLauncher.Common.Unix; namespace XIVLauncher.Common.Unix.Compatibility; @@ -15,6 +16,8 @@ public class DxvkSettings public string DownloadUrl { get; } public Dictionary Environment { get; } + + private static bool? mangoHudFound = null; public DxvkSettings(string folder, string url, string storageFolder, bool async, int maxFrameRate, bool dxvkHudEnabled, string dxvkHudString, bool mangoHudEnabled = false, bool mangoHudCustomIsFile = false, string customMangoHud = "", bool enabled = true) { @@ -74,12 +77,10 @@ public static bool DxvkHudStringIsValid(string customHud) public static bool MangoHudIsInstalled() { - var usrLib = Path.Combine("/", "usr", "lib", "mangohud", "libMangoHud.so"); // fedora uses this - var usrLib64 = Path.Combine("/", "usr", "lib64", "mangohud", "libMangoHud.so"); // arch and openSUSE use this - var flatpak = Path.Combine("/", "usr", "lib", "extensions", "vulkan", "MangoHud", "lib", "x86_64-linux-gnu", "libMangoHud.so"); - var debuntu = Path.Combine("/", "usr", "lib", "x86_64-linux-gnu", "mangohud", "libMangoHud.so"); - if (File.Exists(usrLib64) || File.Exists(usrLib) || File.Exists(flatpak) || File.Exists(debuntu)) - return true; - return false; + if (mangoHudFound is null) + { + mangoHudFound = LinuxInfo.IsFileFound(LinuxInfo.LibraryPaths, "libMangoHud.so"); + } + return mangoHudFound ?? false; } } \ No newline at end of file diff --git a/src/XIVLauncher.Common.Unix/LinuxContainer.cs b/src/XIVLauncher.Common.Unix/LinuxContainer.cs new file mode 100644 index 00000000..917bfb5a --- /dev/null +++ b/src/XIVLauncher.Common.Unix/LinuxContainer.cs @@ -0,0 +1,10 @@ +namespace XIVLauncher.Common.Unix; + +public enum LinuxContainer +{ + none, + + flatpak, + + snap, +} \ No newline at end of file diff --git a/src/XIVLauncher.Common.Unix/LinuxDistro.cs b/src/XIVLauncher.Common.Unix/LinuxDistro.cs new file mode 100644 index 00000000..534fce89 --- /dev/null +++ b/src/XIVLauncher.Common.Unix/LinuxDistro.cs @@ -0,0 +1,12 @@ +namespace XIVLauncher.Common.Unix; + +public enum LinuxDistro +{ + ubuntu, + + fedora, + + arch, + + none, +} diff --git a/src/XIVLauncher.Common.Unix/LinuxInfo.cs b/src/XIVLauncher.Common.Unix/LinuxInfo.cs new file mode 100644 index 00000000..16d3be05 --- /dev/null +++ b/src/XIVLauncher.Common.Unix/LinuxInfo.cs @@ -0,0 +1,210 @@ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.IO; +using System.Diagnostics; + +namespace XIVLauncher.Common.Unix; + +public static class LinuxInfo +{ + public static LinuxDistro Package { get; private set; } + + public static LinuxContainer Container { get; private set; } + + public static List LibraryPaths { get; private set; } + + public static string Name { get; private set; } + + public static bool IsLinux { get; private set; } + + static LinuxInfo() + { + LibraryPaths = new List(); + var os = System.Environment.OSVersion; + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + Package = LinuxDistro.none; + Container = LinuxContainer.none; + Name = os.VersionString; + IsLinux = false; + return; + } + + IsLinux = true; + Package = LinuxDistro.ubuntu; + Container = LinuxContainer.none; + try + { + if (!File.Exists("/etc/os-release")) + { + Package = LinuxDistro.ubuntu; + Container = LinuxContainer.none; + Name = "Unknown distribution"; + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + LibraryPaths.Add(Path.Combine("/", "lib64")); + LibraryPaths.Add(Path.Combine("/", "lib")); + return; + } + var osRelease = File.ReadAllLines("/etc/os-release"); + var osInfo = new Dictionary(); + foreach (var line in osRelease) + { + var keyValue = line.Split('=', 2); + if (keyValue.Length == 1) + osInfo.Add(keyValue[0], ""); + else + osInfo.Add(keyValue[0], keyValue[1]); + } + + var name = (osInfo.ContainsKey("NAME") ? osInfo["NAME"] : "").Trim('"'); + var pretty = (osInfo.ContainsKey("PRETTY_NAME") ? osInfo["PRETTY_NAME"] : "").Trim('"'); + Name = pretty == "" ? (name == "" ? "Unknown distribution" : name) : pretty; + + // Check for flatpak or snap + if (osInfo.ContainsKey("ID")) + { + if (osInfo["ID"] == "org.freedesktop.platform") + { + LibraryPaths.Add(Path.Combine("/", "app", "lib")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x84_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "extensions")); + Container = LinuxContainer.flatpak; + } + else if (osInfo.ContainsKey("HOME_URL")) + { + if (osInfo["ID"] == "ubuntu-core" && osInfo["HOME_URL"] == "https://snapcraft.io") + { + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + // nvidia host path, needed for dlss on steam snap. These paths look on the host distro. + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "x86_64-linux-gnu", "nvidia")); + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib64", "nvidia")); + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "nvidia")); + Container = LinuxContainer.snap; + } + } + } + + // Check distro package if not a container + if (Container == LinuxContainer.none) + { + foreach (var kvp in osInfo) + { + if (kvp.Value.ToLower().Contains("fedora")) + { + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + Package = LinuxDistro.fedora; + break; + } + if (kvp.Value.ToLower().Contains("tumbleweed")) + { + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + Package = LinuxDistro.fedora; + break; + } + if (kvp.Value.ToLower().Contains("arch")) + { + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + Package = LinuxDistro.arch; + break; + } + if (kvp.Value.ToLower().Contains("ubuntu") || kvp.Value.ToLower().Contains("debian")) + { + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + break; + } + // Unknown distro, add extra library search paths + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + LibraryPaths.Add(Path.Combine("/", "lib64")); + LibraryPaths.Add(Path.Combine("/", "lib")); + } + } + } + catch + { + // If there's any kind of error opening the file or even finding it, just go with default. + Package = LinuxDistro.ubuntu; + Name = "Unknown distribution"; + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + LibraryPaths.Add(Path.Combine("/", "lib64")); + LibraryPaths.Add(Path.Combine("/", "lib")); + } + } + + public static List FileFind(string searchPath, string file, bool followSymlinks = false) + { + if (!IsLinux) + return new List(); + + var found = new List(); + var psi = new ProcessStartInfo("find"); + psi.Arguments = $"{(followSymlinks ? "-L " : "")}{searchPath} -name \"{file}\""; + psi.RedirectStandardOutput = true; + psi.RedirectStandardError = true; + var findCmd = new Process(); + findCmd.StartInfo = psi; + try + { + findCmd.Start(); + var output = findCmd.StandardOutput.ReadToEnd(); + if (!string.IsNullOrWhiteSpace(output)) + { + var outputArray = output.Split('\n', StringSplitOptions.RemoveEmptyEntries); + foreach (string foundfile in outputArray) + found.Add(foundfile); + } + } + catch (System.ComponentModel.Win32Exception ex) + { + Console.WriteLine("Error: could not execute \"find\" command. Is it installed?"); + Console.WriteLine(ex.Message); + } + finally + { + findCmd.Dispose(); + } + return found; + } + + public static List FileFind(IEnumerable searchPaths, string file, bool followSymlinks = false) + { + if (!IsLinux) + return new List(); + + var found = new List(); + foreach (string searchPath in searchPaths) + { + found.AddRange(FileFind(searchPath, file, followSymlinks)); + } + return found; + } + + public static bool IsFileFound(string searchPath, string file, bool followSymlinks = false) + { + if (!IsLinux) + return false; + + if (FileFind(searchPath, file, followSymlinks).Count > 0) + return true; + return false; + } + + public static bool IsFileFound(IEnumerable searchPaths, string file, bool followSymlinks = false) + { + if (!IsLinux) + return false; + + foreach (string searchPath in searchPaths) + { + if (IsFileFound(searchPath, file, followSymlinks)) + return true; + } + return false; + } +} \ No newline at end of file diff --git a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs index 86ef5388..5104d355 100644 --- a/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs +++ b/src/XIVLauncher.Core/Components/SettingsPage/Tabs/SettingsTabDebug.cs @@ -3,6 +3,7 @@ using ImGuiNET; using XIVLauncher.Core; using XIVLauncher.Common; +using XIVLauncher.Common.Unix; namespace XIVLauncher.Core.Components.SettingsPage.Tabs; @@ -15,8 +16,8 @@ public override void Draw() { ImGui.TextUnformatted("Generic Information"); ImGui.Separator(); - if (OSInfo.Platform == Platform.Linux) - ImGui.TextUnformatted($"Operating System: {OSInfo.Name} - {Environment.OSVersion}"); + if (LinuxInfo.IsLinux) + ImGui.TextUnformatted($"Operating System: {LinuxInfo.Name} - {Environment.OSVersion}"); else ImGui.TextUnformatted($"Operating System: {Environment.OSVersion}"); ImGui.TextUnformatted($"Runtime Version: {Environment.Version}"); @@ -27,8 +28,11 @@ public override void Draw() if (Program.IsSteamDeckGamingMode) ImGui.Text("Steam Deck Gaming Mode Detected"); - if (OSInfo.IsFlatpak) - ImGui.Text("Running as a Flatpak"); + if (LinuxInfo.Container == LinuxContainer.flatpak) + ImGui.Text("Running in a Flatpak container"); + + if (LinuxInfo.Container == LinuxContainer.snap) + ImGui.Text("Running in a Snap container"); ImGui.Spacing(); diff --git a/src/XIVLauncher.Core/OSInfo.cs b/src/XIVLauncher.Core/OSInfo.cs deleted file mode 100644 index da8d0896..00000000 --- a/src/XIVLauncher.Core/OSInfo.cs +++ /dev/null @@ -1,132 +0,0 @@ -using System.Numerics; -using System.IO; -using System.Collections.Generic; -using XIVLauncher.Common; -using System.Runtime.InteropServices; - -namespace XIVLauncher.Core; - -public enum LinuxDistroPackage -{ - ubuntu, - - fedora, - - arch, - - none, -} - -public static class OSInfo -{ - public static LinuxDistroPackage Package { get; private set; } - - public static string Name { get; private set; } - - public static bool IsFlatpak { get; private set; } - - public static Platform Platform { get; private set; } - - static OSInfo() - { - var os = System.Environment.OSVersion; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - Package = LinuxDistroPackage.none; - Name = os.VersionString; - IsFlatpak = false; - Platform = Platform.Win32; - return; - } - - // There's no wine releases for MacOS or FreeBSD, and I'm not sure this will even compile on either - // platform, but here's some code just in case. Can modify this as needed if it's useful in the future. - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - Platform = Platform.Mac; - Name = os.VersionString; - IsFlatpak = false; - Package = LinuxDistroPackage.none; - return; - } - - if (RuntimeInformation.IsOSPlatform(OSPlatform.FreeBSD)) - { - Platform = Platform.Mac; // Don't have an option for this atm. - Name = os.VersionString; - IsFlatpak = false; - Package = LinuxDistroPackage.none; - return; - } - - Platform = Platform.Linux; - try - { - if (!File.Exists("/etc/os-release")) - { - Package = LinuxDistroPackage.ubuntu; - Name = "Unknown distribution"; - IsFlatpak = false; - return; - } - var osRelease = File.ReadAllLines("/etc/os-release"); - var osInfo = new Dictionary(); - foreach (var line in osRelease) - { - var keyValue = line.Split('=', 2); - if (keyValue.Length == 1) - osInfo.Add(keyValue[0], ""); - else - osInfo.Add(keyValue[0], keyValue[1]); - } - - var name = (osInfo.ContainsKey("NAME") ? osInfo["NAME"] : "").Trim('"'); - var pretty = (osInfo.ContainsKey("PRETTY_NAME") ? osInfo["PRETTY_NAME"] : "").Trim('"'); - Name = pretty == "" ? (name == "" ? "Unknown distribution" : name) : pretty; - - if (CheckFlatpak(osInfo)) - { - IsFlatpak = true; - Package = LinuxDistroPackage.ubuntu; - return; - } - - Package = CheckDistro(osInfo); - IsFlatpak = false; - return; - } - catch - { - // If there's any kind of error opening the file or even finding it, just go with default. - Package = LinuxDistroPackage.ubuntu; - Name = "Unknown distribution"; - IsFlatpak = false; - } - } - - private static bool CheckFlatpak(Dictionary osInfo) - { - if (osInfo.ContainsKey("ID")) - if (osInfo["ID"] == "org.freedesktop.platform") - return true; - return false; - } - - private static LinuxDistroPackage CheckDistro(Dictionary osInfo) - { - foreach (var kvp in osInfo) - { - if (kvp.Value.ToLower().Contains("fedora")) - return LinuxDistroPackage.fedora; - if (kvp.Value.ToLower().Contains("tumbleweed")) - return LinuxDistroPackage.fedora; - if (kvp.Value.ToLower().Contains("ubuntu")) - return LinuxDistroPackage.ubuntu; - if (kvp.Value.ToLower().Contains("debian")) - return LinuxDistroPackage.ubuntu; - if (kvp.Value.ToLower().Contains("arch")) - return LinuxDistroPackage.arch; - } - return LinuxDistroPackage.ubuntu; - } -} \ No newline at end of file diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 641d238b..3d2b02dc 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -21,6 +21,7 @@ using XIVLauncher.Common.Unix.Compatibility; using XIVLauncher.Common.Util; using XIVLauncher.Common.Windows; +using XIVLauncher.Common.Unix; using XIVLauncher.Core.Accounts.Secrets; using XIVLauncher.Core.Accounts.Secrets.Providers; using XIVLauncher.Core.Components.LoadingPage; @@ -309,7 +310,7 @@ private static void Main(string[] args) var needUpdate = false; - if (OSInfo.IsFlatpak && (Config.DoVersionCheck ?? false)) + if (LinuxInfo.Container == LinuxContainer.flatpak && (Config.DoVersionCheck ?? false)) { var versionCheckResult = UpdateCheck.CheckForUpdate().GetAwaiter().GetResult(); @@ -383,7 +384,7 @@ public static void CreateCompatToolsInstance() var dxvkSettings = new DxvkSettings(Dxvk.FolderName, Dxvk.DownloadUrl, storage.Root.FullName, Dxvk.AsyncEnabled, Dxvk.FrameRateLimit, Dxvk.DxvkHudEnabled, Dxvk.DxvkHudString, Dxvk.MangoHudEnabled, Dxvk.MangoHudCustomIsFile, Dxvk.MangoHudString, Dxvk.Enabled); var wineSettings = new WineSettings(Wine.IsManagedWine, Wine.CustomWinePath, Wine.FolderName, Wine.DownloadUrl, storage.Root, Wine.DebugVars, Wine.LogFile, Wine.Prefix, Wine.ESyncEnabled, Wine.FSyncEnabled); var toolsFolder = storage.GetFolder("compatibilitytool"); - CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder, OSInfo.IsFlatpak); + CompatibilityTools = new CompatibilityTools(wineSettings, dxvkSettings, Config.GameModeEnabled, toolsFolder); } public static void ShowWindow() diff --git a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs index 3d34dfe7..0e03ecf7 100644 --- a/src/XIVLauncher.Core/UnixCompatibility/Wine.cs +++ b/src/XIVLauncher.Core/UnixCompatibility/Wine.cs @@ -6,6 +6,7 @@ using System.Linq; using Serilog; using XIVLauncher.Common; +using XIVLauncher.Common.Unix; using XIVLauncher.Common.Unix.Compatibility; namespace XIVLauncher.Core.UnixCompatibility; @@ -43,13 +44,13 @@ public static void Initialize() Versions["wine-xiv-staging-fsync-git-7.10.r3.g560db77d"] = new Dictionary() { {"name", "Wine-XIV 7.10"}, {"desc","Patched version of Wine Staging 7.10. Default."}, - {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz"}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/7.10.r3.g560db77d/wine-xiv-staging-fsync-git-{LinuxInfo.Package.ToString()}-7.10.r3.g560db77d.tar.xz"}, {"mark", "Download"} }; Versions["wine-xiv-staging-fsync-git-8.5.r4.g4211bac7"] = new Dictionary() { {"name", "Wine-XIV 8.5"}, {"desc", "Patched version of Wine Staging 8.5. Change Windows version to 7 for best results."}, - {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{OSInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, + {"label", "Official"}, {"url", $"https://github.com/goatcorp/wine-xiv-git/releases/download/8.5.r4.g4211bac7/wine-xiv-staging-fsync-git-{LinuxInfo.Package.ToString()}-8.5.r4.g4211bac7.tar.xz"}, {"mark", "Download"} }; From 8a2e8541e72253476be4c001d54087a3fd7d4085 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 9 Nov 2024 12:22:33 -0800 Subject: [PATCH 38/40] Get rid of file find functions I didn't realize there was a way to limit recursion in GetFiles(), so I was using linux find. EnumerationOptions was the solution: * set RecurseSubdirectories = true * set MaxRecursionDepth --- .../Compatibility/DxvkSettings.cs | 16 +++- src/XIVLauncher.Common.Unix/LinuxInfo.cs | 83 ++----------------- 2 files changed, 24 insertions(+), 75 deletions(-) diff --git a/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs index 4a64016c..57a4b23e 100644 --- a/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs +++ b/src/XIVLauncher.Common.Unix/Compatibility/DxvkSettings.cs @@ -79,7 +79,21 @@ public static bool MangoHudIsInstalled() { if (mangoHudFound is null) { - mangoHudFound = LinuxInfo.IsFileFound(LinuxInfo.LibraryPaths, "libMangoHud.so"); + mangoHudFound = false; + var options = new EnumerationOptions(); + options.RecurseSubdirectories = true; + options.MaxRecursionDepth = 5; + foreach (var path in LinuxInfo.LibraryPaths) + { + if (!Directory.Exists(path)) + continue; + + if (Directory.GetFiles(path, "libMangoHud.so", options).Length > 0) + { + mangoHudFound = true; + break; + } + } } return mangoHudFound ?? false; } diff --git a/src/XIVLauncher.Common.Unix/LinuxInfo.cs b/src/XIVLauncher.Common.Unix/LinuxInfo.cs index 16d3be05..2d819b0b 100644 --- a/src/XIVLauncher.Common.Unix/LinuxInfo.cs +++ b/src/XIVLauncher.Common.Unix/LinuxInfo.cs @@ -46,6 +46,7 @@ static LinuxInfo() LibraryPaths.Add(Path.Combine("/", "usr", "lib")); LibraryPaths.Add(Path.Combine("/", "lib64")); LibraryPaths.Add(Path.Combine("/", "lib")); + Console.WriteLine($"Distro = {Package}, Container = {Container}"); return; } var osRelease = File.ReadAllLines("/etc/os-release"); @@ -77,6 +78,7 @@ static LinuxInfo() { if (osInfo["ID"] == "ubuntu-core" && osInfo["HOME_URL"] == "https://snapcraft.io") { + Console.WriteLine("Running snap container check"); LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); LibraryPaths.Add(Path.Combine("/", "usr", "lib")); // nvidia host path, needed for dlss on steam snap. These paths look on the host distro. @@ -99,24 +101,28 @@ static LinuxInfo() Package = LinuxDistro.fedora; break; } - if (kvp.Value.ToLower().Contains("tumbleweed")) + else if (kvp.Value.ToLower().Contains("tumbleweed")) { LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); Package = LinuxDistro.fedora; break; } - if (kvp.Value.ToLower().Contains("arch")) + else if (kvp.Value.ToLower().Contains("arch")) { LibraryPaths.Add(Path.Combine("/", "usr", "lib")); Package = LinuxDistro.arch; break; } - if (kvp.Value.ToLower().Contains("ubuntu") || kvp.Value.ToLower().Contains("debian")) + else if (kvp.Value.ToLower().Contains("ubuntu") || kvp.Value.ToLower().Contains("debian")) { LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); break; } + } + if (LibraryPaths.Count == 0) + { // Unknown distro, add extra library search paths + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); LibraryPaths.Add(Path.Combine("/", "usr", "lib")); LibraryPaths.Add(Path.Combine("/", "lib64")); @@ -136,75 +142,4 @@ static LinuxInfo() LibraryPaths.Add(Path.Combine("/", "lib")); } } - - public static List FileFind(string searchPath, string file, bool followSymlinks = false) - { - if (!IsLinux) - return new List(); - - var found = new List(); - var psi = new ProcessStartInfo("find"); - psi.Arguments = $"{(followSymlinks ? "-L " : "")}{searchPath} -name \"{file}\""; - psi.RedirectStandardOutput = true; - psi.RedirectStandardError = true; - var findCmd = new Process(); - findCmd.StartInfo = psi; - try - { - findCmd.Start(); - var output = findCmd.StandardOutput.ReadToEnd(); - if (!string.IsNullOrWhiteSpace(output)) - { - var outputArray = output.Split('\n', StringSplitOptions.RemoveEmptyEntries); - foreach (string foundfile in outputArray) - found.Add(foundfile); - } - } - catch (System.ComponentModel.Win32Exception ex) - { - Console.WriteLine("Error: could not execute \"find\" command. Is it installed?"); - Console.WriteLine(ex.Message); - } - finally - { - findCmd.Dispose(); - } - return found; - } - - public static List FileFind(IEnumerable searchPaths, string file, bool followSymlinks = false) - { - if (!IsLinux) - return new List(); - - var found = new List(); - foreach (string searchPath in searchPaths) - { - found.AddRange(FileFind(searchPath, file, followSymlinks)); - } - return found; - } - - public static bool IsFileFound(string searchPath, string file, bool followSymlinks = false) - { - if (!IsLinux) - return false; - - if (FileFind(searchPath, file, followSymlinks).Count > 0) - return true; - return false; - } - - public static bool IsFileFound(IEnumerable searchPaths, string file, bool followSymlinks = false) - { - if (!IsLinux) - return false; - - foreach (string searchPath in searchPaths) - { - if (IsFileFound(searchPath, file, followSymlinks)) - return true; - } - return false; - } } \ No newline at end of file From 6b1b3e9e8221bfe980213bd02af56c9d1b0bb2f1 Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 9 Nov 2024 13:32:56 -0800 Subject: [PATCH 39/40] More code cleanup: * Move library path handling to a helper function * Move HttpClient.Dispose() below Veldrid resource cleanup This seems to fix the occasional memory errors on close These errors were only visible on the terminal, and harmless. --- src/XIVLauncher.Common.Unix/LinuxInfo.cs | 92 +++++++++++++++--------- src/XIVLauncher.Core/Program.cs | 3 +- 2 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/XIVLauncher.Common.Unix/LinuxInfo.cs b/src/XIVLauncher.Common.Unix/LinuxInfo.cs index 2d819b0b..bdf42289 100644 --- a/src/XIVLauncher.Common.Unix/LinuxInfo.cs +++ b/src/XIVLauncher.Common.Unix/LinuxInfo.cs @@ -32,7 +32,7 @@ static LinuxInfo() } IsLinux = true; - Package = LinuxDistro.ubuntu; + Package = LinuxDistro.none; Container = LinuxContainer.none; try { @@ -41,12 +41,7 @@ static LinuxInfo() Package = LinuxDistro.ubuntu; Container = LinuxContainer.none; Name = "Unknown distribution"; - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib")); - LibraryPaths.Add(Path.Combine("/", "lib64")); - LibraryPaths.Add(Path.Combine("/", "lib")); - Console.WriteLine($"Distro = {Package}, Container = {Container}"); + addLibraryPaths(); return; } var osRelease = File.ReadAllLines("/etc/os-release"); @@ -69,23 +64,15 @@ static LinuxInfo() { if (osInfo["ID"] == "org.freedesktop.platform") { - LibraryPaths.Add(Path.Combine("/", "app", "lib")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x84_64-linux-gnu")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "extensions")); Container = LinuxContainer.flatpak; + Package = LinuxDistro.ubuntu; } else if (osInfo.ContainsKey("HOME_URL")) { if (osInfo["ID"] == "ubuntu-core" && osInfo["HOME_URL"] == "https://snapcraft.io") { - Console.WriteLine("Running snap container check"); - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib")); - // nvidia host path, needed for dlss on steam snap. These paths look on the host distro. - LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "x86_64-linux-gnu", "nvidia")); - LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib64", "nvidia")); - LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "nvidia")); Container = LinuxContainer.snap; + Package = LinuxDistro.ubuntu; } } } @@ -97,49 +84,88 @@ static LinuxInfo() { if (kvp.Value.ToLower().Contains("fedora")) { - LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); Package = LinuxDistro.fedora; break; } else if (kvp.Value.ToLower().Contains("tumbleweed")) { - LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); Package = LinuxDistro.fedora; break; } else if (kvp.Value.ToLower().Contains("arch")) { - LibraryPaths.Add(Path.Combine("/", "usr", "lib")); Package = LinuxDistro.arch; break; } else if (kvp.Value.ToLower().Contains("ubuntu") || kvp.Value.ToLower().Contains("debian")) { - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + Package = LinuxDistro.ubuntu; break; } } - if (LibraryPaths.Count == 0) + if (Package == LinuxDistro.none) { - // Unknown distro, add extra library search paths - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib")); - LibraryPaths.Add(Path.Combine("/", "lib64")); - LibraryPaths.Add(Path.Combine("/", "lib")); + Package = LinuxDistro.ubuntu; } } + addLibraryPaths(); + foreach (var path in LibraryPaths) + Console.Write(path + ":"); } catch { // If there's any kind of error opening the file or even finding it, just go with default. Package = LinuxDistro.ubuntu; Name = "Unknown distribution"; - LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); - LibraryPaths.Add(Path.Combine("/", "usr", "lib")); - LibraryPaths.Add(Path.Combine("/", "lib64")); - LibraryPaths.Add(Path.Combine("/", "lib")); + addLibraryPaths(); + } + } + + private static void addLibraryPaths() + { + switch (Container) + { + case LinuxContainer.flatpak: + LibraryPaths.Add(Path.Combine("/", "app", "lib")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x84_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "extensions")); + break; + + case LinuxContainer.snap: + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + // nvidia host path, needed for dlss on steam snap. These paths look on the host distro. + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "x86_64-linux-gnu", "nvidia")); + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib64", "nvidia")); + LibraryPaths.Add(Path.Combine("/", "var", "lib", "snapd", "hostfs", "usr", "lib", "nvidia")); + break; + + case LinuxContainer.none: + if (Package == LinuxDistro.none && IsLinux) + Package = LinuxDistro.ubuntu; + switch (Package) + { + case LinuxDistro.arch: + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + break; + + case LinuxDistro.fedora: + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + break; + + case LinuxDistro.ubuntu: + LibraryPaths.Add(Path.Combine("/", "usr", "lib", "x86_64-linux-gnu")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib64")); + LibraryPaths.Add(Path.Combine("/", "usr", "lib")); + LibraryPaths.Add(Path.Combine("/", "lib64")); + LibraryPaths.Add(Path.Combine("/", "lib")); + break; + + case LinuxDistro.none: + break; + } + break; } + } } \ No newline at end of file diff --git a/src/XIVLauncher.Core/Program.cs b/src/XIVLauncher.Core/Program.cs index 3d2b02dc..03a9515f 100644 --- a/src/XIVLauncher.Core/Program.cs +++ b/src/XIVLauncher.Core/Program.cs @@ -371,12 +371,13 @@ private static void Main(string[] args) gd.SwapBuffers(gd.MainSwapchain); } - HttpClient.Dispose(); // Clean up Veldrid resources gd.WaitForIdle(); bindings.Dispose(); cl.Dispose(); gd.Dispose(); + + HttpClient.Dispose(); } public static void CreateCompatToolsInstance() From 2f23d0dd84dc73f1aedbfec36f3a7c81092bff4c Mon Sep 17 00:00:00 2001 From: Rankyn Bass Date: Sat, 9 Nov 2024 14:59:22 -0800 Subject: [PATCH 40/40] Remove debug console writes --- src/XIVLauncher.Common.Unix/LinuxInfo.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/XIVLauncher.Common.Unix/LinuxInfo.cs b/src/XIVLauncher.Common.Unix/LinuxInfo.cs index bdf42289..181efdf5 100644 --- a/src/XIVLauncher.Common.Unix/LinuxInfo.cs +++ b/src/XIVLauncher.Common.Unix/LinuxInfo.cs @@ -109,8 +109,6 @@ static LinuxInfo() } } addLibraryPaths(); - foreach (var path in LibraryPaths) - Console.Write(path + ":"); } catch {