-
Notifications
You must be signed in to change notification settings - Fork 334
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compatibility rework #1348
Compatibility rework #1348
Conversation
This reverts commit c37927c. It's better to keep all this on the XL side.
public bool IsToolReady { get; private set; } | ||
|
||
public WineSettings Settings { get; private set; } | ||
public WineRunner WineSettings { get; private set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why rename WineSettings to WineRunner, when it still only holds settings and everything is actually run here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. Can certainly change this back to WineSettings.
It made more sense when I started the whole thing, honestly. The names just kind of stuck around. I can certainly change it back. When I started this whole thing, Dxvk and Wine were both in the same object, but it became too complicated and janky, so I split them. I think Runner was chosen simply because that's the folder lutris stuffs wine installs into.
Settings.CustomBinPath; | ||
private string Wine64Path => Path.Combine(WineBinPath, "wine64"); | ||
private string WineServerPath => Path.Combine(WineBinPath, "wineserver"); | ||
public DxvkRunner DxvkSettings { get; private set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DxvkRunner is also a Misnomer IMHO
private readonly Dxvk.DxvkHudType hudType; | ||
private readonly bool gamemodeOn; | ||
private readonly string dxvkAsyncOn; | ||
public string WineDLLOverrides; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does this need to be a public field?
DxvkSettings = dxvkSettings; | ||
EnvVars = environment; | ||
Prefix = prefix; | ||
WineDLLOverrides = (string.IsNullOrEmpty(wineoverrides)) ? "msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi=n,b" : wineoverrides; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are we setting wineoverrides externally and then have this internal fallback here, and the fallback doesn't even take into account dxvkSettings...
IMO they should only be set in 1 place and ideally here
if (!this.dxvkDirectory.Exists) | ||
this.dxvkDirectory.Create(); | ||
} | ||
public CompatibilityTools(WineRunner wineSettings, DxvkRunner dxvkSettings, Dictionary<string, string> environment, string wineoverrides, DirectoryInfo prefix, DirectoryInfo toolsFolder, FileInfo logfile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
environment should only contain extra user specified env vars that override the standard behaviour
|
||
namespace XIVLauncher.Common.Unix.Compatibility; | ||
|
||
public class WineRunner |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if this needs to be called runner, when all it does is hold wine settings/configuration
|
||
public Dictionary<string, string> Environment { get; } | ||
|
||
public WineRunner(string runCmd, string runArgs, string folder, string url, string rootFolder, Dictionary<string, string> env = null, bool is64only = false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is64only
is a misnomer here, in general all wine builds with 64 bit support will have a dedicated wine64
executable which is the one that should be invoked for xiv and Dalamud, as when you use the wrong 32 bit one, wine will notice and call wine64 for you (except for some IL-only executables).
is64only
should always be true, if anything, but is not even needed to be specified at all... The only exception to not calling wine64 is using the new experimental wine8 wow64 backend, which will create a single 64 bit only wine
executable, that internally thunks all system calls when passing it a 32 bit PE executable (which ironically means when you have a true 64 bit only wine 8 is64only
should be false here).
This is easy enough to handle transparently handle though, always pick wine64
unless it doesn't exist, then pick wine
.
Console.WriteLine("[DALAMUD] " + output); | ||
|
||
// Skip "ERROR: Could Not Get Primary Adapter Handle" and proceed to next line | ||
if (output.Equals("ERROR: Could Not Get Primary Adapter Handle")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary?
Wine should always output its internal logging to stderr, but this doesn't even look like wine.
@@ -74,43 +74,57 @@ 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(); | |||
var output = dalamudProcess.StandardOutput.ReadLine() ?? ""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
output
is checked against null later, no need to null-coalesce it twice.
Also output
being null is meaningful information, since it indicates that the process exited without writing a single line to stdout
try | ||
{ | ||
var dalamudConsoleOutput = JsonConvert.DeserializeObject<DalamudConsoleOutput>(output); | ||
var unixPid = compatibility.GetUnixProcessId(dalamudConsoleOutput.Pid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of UnixDalamudRunner
can be left as is with the adjustments to GetUnixProcessId
from before
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If GetUnixProcessId
is properly implemented all of this can be really left as as (save the JSON reading adjustment and spelling mistakes) to keep it simple
I'll certainly check into all of this when I get a chance later today. Thanks for taking a good look at this. |
* Changed names of classes to WineSettings and DxvkSettings * Moved the install functions back to compatibilitytools * Removed a bunch of unused variables * Restored UnixDalamudRunner to be much closer to original * Moved WINEDLLOVERRIDES completely to compatibilitytools * Renamed some vars for better clarity.
First, marzent, thank you for your thorough review of this PR. It was very helpful.
For reasons unknown, after doing all these changes the Wine 7.11 that I tested for you the other day started working. It still fails in the current flatpak and rpm builds (and on the previous test builds I posted), but with these changes it now properly loads Dalamud, as if there were no problems at all. Previously, the game would load, but the process would hang trying to read the output. With these changes it doesn’t, and I have no idea why. I’ll look at the XL.Core side tomorrow. Thanks! |
I made a mistake in detecting wine or wine64 binary. This was actually the cause of the Wine 7.11 build working: it actually wasn't. Instead, I was accidentally trying to find wine (not wine64), failing, and then falling back to whichever Managed wine option was last selected. So the 7.11 wine still doesn't work, and I've fixed the logic. |
} | ||
WineDLLOverrides = wineoverrides; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a very complicated way of writing WineDLLOverrides = $"msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi={dxvkSettings.IsDxvk ? "n,b" : "b"}";
await Dxvk.InstallDxvk(Settings.Prefix, dxvkDirectory).ConfigureAwait(false); | ||
|
||
// Check to make sure dxvk is valid | ||
if (DxvkSettings.IsDxvk) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
DxvkSettings.IsDxvk
sounds a bit weird (what are DxvkSettings that are not DXVK?) maybe renaming it to DxvkSettings.Enabled
would be nicer
await DownloadTool(wineDirectory.FullName, WineSettings.Folder, WineSettings.DownloadUrl); | ||
|
||
// Use wine if wine64 isn't found. This is mostly for WoW64 wine builds. | ||
WineSettings.RunCommand = WineSettings.SetWineOrWine64(Path.Combine(wineDirectory.FullName, WineSettings.Folder, "bin")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are not setting anything there... SetWineOrWine64
is a a pure function (and not really needed anyways)
#endif | ||
var wineEnvironmentVariables = new Dictionary<string, string>(); | ||
if (wineD3D) | ||
wineEnvironmentVariables.Add("WINEDLLOVERRIDES", "msquic=,mscoree=n,b;d3d9,d3d11,d3d10core,dxgi=b"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic here is completely different from WineDLLOverrides
above and should be consolidated (ideally here)
MergeDictionaries(psi.Environment, wineEnvironmentVariables); | ||
MergeDictionaries(psi.Environment, environment); | ||
|
||
// #if FLATPAK_NOTRIGHTNOW |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about commenting out the code here, but don't have strong opinions on that... Maybe @goaaats has some ideas about it
@@ -253,16 +283,46 @@ public Int32 GetProcessId(string executableName) | |||
return GetProcessIds(executableName).FirstOrDefault(); | |||
} | |||
|
|||
public Int32 GetUnixProcessId(Int32 winePid) | |||
public Int32 GetUnixProcessId(Int32 winePid, string executableName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was not my original suggestion (and makes this function harder to understand)
GetUnixProcessId
maps a Wine PID to its Unix one... If winedbg
doesn't have the necessary patch for this then the process name can be inferred from the wine PID by winedbg
(and not passed as extra parameter) and be fed into GetUnixProcessIdByName
throw new DalamudRunnerException("An internal Dalamud error has occured"); | ||
Console.WriteLine("[DALAMUD] " + output); | ||
dalamudErrorCount++; | ||
} while (!output.StartsWith('{') && dalamudErrorCount <= 2); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a very crude check for valid JSON we should try to parse lines until they can be deserialized to a DalamudConsoleOutput
, something like marzent@f50acf4 would be better IMO...
Although I generally dislike both of these solutions that issue should really not be happening in the first place, but I guess some configurations are special
|
||
new Thread(() => | ||
{ | ||
while (!dalamudProcess.StandardOutput.EndOfStream) | ||
{ | ||
var output = dalamudProcess.StandardOutput.ReadLine(); | ||
if (output != null) | ||
Console.WriteLine(output); | ||
Console.WriteLine("[DALAMUD] " + output); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is confusing since it really is Injector and not Dalamud proper here (in any case best to leave it be)
try | ||
{ | ||
var dalamudConsoleOutput = JsonConvert.DeserializeObject<DalamudConsoleOutput>(output); | ||
var unixPid = compatibility.GetUnixProcessId(dalamudConsoleOutput.Pid); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If GetUnixProcessId
is properly implemented all of this can be really left as as (save the JSON reading adjustment and spelling mistakes) to keep it simple
* fixed WineDLLOverrides * Renamed IsDxvk to Enabled * Improved logic for RunCommand for readability. * Uncommented #FLATPAK_NOTRIGHTNOW block * Removed second arg from GetUnixProcessId() * Added private function to find gameExe from winedbg info proc
Closing and replacing with #1366. There were too many changes needed to rework this branch directly, and it was better to just start over from current master. |
This replaces the Dxvk Settings Rework - #1205
Here's the compatibilitytools rework I mentioned a few weeks ago. This moves most of the bits that will change over to the XL.Core side, such as specific versions of wine or dxvk, where they will be stored, and what environment variables need to be set for each one.
I also moved the MacVideoFix over to XL.Core. I figure individual implementations of fixes can be done on the XL.Core side, and then passed to GameFixApply object.
Depends on
And here's a link to a flatpak build if you want to test:
https://github.com/rankynbass/XIVLauncher.Core/releases/edit/compatrework-v1
Install with
flatpak install xivlauncher-rework.flatpak
, run withflatpak run dev.goats.testing.xivlauncher
.