add in Wine/Proton detection, used to prevent D3D9 from being used if a user ends up using wine/proton (as often it seems D3D9 wine/proton just doesn't work and crashes in weird ways, sometimes *after* checking the renderer so it wouldn't fallback to OpenGL anyways)

Probably can add in some first time message box warning the user that wine/proton isnt supported, although we probably shouldn't block wine/proton (considering it's the only option for some distros with read-only filesystems, like the Steam Deck)
This commit is contained in:
CasualPokePlayer 2023-07-31 23:02:30 -07:00
parent 67e5505899
commit dc34b0b1a9
3 changed files with 47 additions and 27 deletions

View File

@ -214,7 +214,7 @@ namespace BizHawk.Client.Common
public int DispPrescale { get; set; } = 1;
public EDispMethod DispMethod { get; set; } = HostCapabilityDetector.HasDirectX ? EDispMethod.D3D9 : EDispMethod.OpenGL;
public EDispMethod DispMethod { get; set; } = HostCapabilityDetector.HasDirectX && !OSTailoredCode.IsWine ? EDispMethod.D3D9 : EDispMethod.OpenGL;
public int DispChromeFrameWindowed { get; set; } = 2;
public bool DispChromeStatusBarWindowed { get; set; } = true;

View File

@ -210,7 +210,7 @@ namespace BizHawk.Client.EmuHawk
switch (dispMethod)
{
case EDispMethod.D3D9:
if (OSTC.IsUnixHost)
if (OSTC.IsUnixHost || OSTC.IsWine)
{
// possibly sharing config w/ Windows, assume the user wants the not-slow method (but don't change the config)
return TryInitIGL(EDispMethod.OpenGL);

View File

@ -67,6 +67,26 @@ namespace BizHawk.Common
public static bool IsWSL => _isWSL.Value;
private static readonly Lazy<bool> _isWine = new(() =>
{
if (IsUnixHost)
{
return false;
}
var ntdll = LinkedLibManager.LoadOrZero("ntdll.dll");
if (ntdll == IntPtr.Zero)
{
return false;
}
var isWine = LinkedLibManager.GetProcAddrOrZero(ntdll, "wine_get_version") != IntPtr.Zero;
LinkedLibManager.FreeByPtr(ntdll);
return isWine;
});
public static bool IsWine => _isWine.Value;
private static readonly Lazy<ILinkedLibManager> _LinkedLibManager = new Lazy<ILinkedLibManager>(() => CurrentOS switch
{
DistinctOS.Linux => new UnixMonoLLManager(),
@ -131,9 +151,9 @@ namespace BizHawk.Common
}
public string GetErrorMessage()
{
var errCharPtr = dlerror();
return errCharPtr == IntPtr.Zero ? "No error present" : Marshal.PtrToStringAnsi(errCharPtr);
{
var errCharPtr = dlerror();
return errCharPtr == IntPtr.Zero ? "No error present" : Marshal.PtrToStringAnsi(errCharPtr);
}
private const int RTLD_NOW = 2;
@ -147,21 +167,21 @@ namespace BizHawk.Common
private static extern bool FreeLibrary(IntPtr hModule); // return type was annotated MarshalAs(UnmanagedType.Bool)
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
private enum FORMAT_MESSAGE : uint
{
ALLOCATE_BUFFER = 0x00000100,
IGNORE_INSERTS = 0x00000200,
FROM_SYSTEM = 0x00001000,
}
[DllImport("kernel32.dll")]
private static extern uint GetLastError();
private enum FORMAT_MESSAGE : uint
{
ALLOCATE_BUFFER = 0x00000100,
IGNORE_INSERTS = 0x00000200,
FROM_SYSTEM = 0x00001000,
}
[DllImport("kernel32.dll")]
private static extern int FormatMessageA(FORMAT_MESSAGE flags, IntPtr source, uint messageId, uint languageId, out IntPtr outMsg, int size, IntPtr args);
[DllImport("kernel32.dll")]
private static extern IntPtr LocalFree(IntPtr hMem); // use this to free a message from FORMAT_MESSAGE.ALLOCATE_BUFFER
[DllImport("kernel32.dll")]
private static extern IntPtr LocalFree(IntPtr hMem); // use this to free a message from FORMAT_MESSAGE.ALLOCATE_BUFFER
[DllImport("kernel32.dll", SetLastError = true)] // had BestFitMapping = false, ThrowOnUnmappableChar = true
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); // param procName was annotated `[MarshalAs(UnmanagedType.LPStr)]`
@ -184,16 +204,16 @@ namespace BizHawk.Common
{
var ret = LoadOrZero(dllToLoad);
return ret != IntPtr.Zero ? ret : throw new InvalidOperationException($"got null pointer from {nameof(LoadLibrary)}, error code: {GetLastError()}");
}
}
public string GetErrorMessage()
{
var errCode = GetLastError();
var sz = FormatMessageA(FORMAT_MESSAGE.ALLOCATE_BUFFER | FORMAT_MESSAGE.FROM_SYSTEM | FORMAT_MESSAGE.IGNORE_INSERTS,
IntPtr.Zero, errCode, 0, out var buffer, 1024, IntPtr.Zero);
var ret = Marshal.PtrToStringAnsi(buffer, sz);
_ = LocalFree(buffer);
return ret;
{
var errCode = GetLastError();
var sz = FormatMessageA(FORMAT_MESSAGE.ALLOCATE_BUFFER | FORMAT_MESSAGE.FROM_SYSTEM | FORMAT_MESSAGE.IGNORE_INSERTS,
IntPtr.Zero, errCode, 0, out var buffer, 1024, IntPtr.Zero);
var ret = Marshal.PtrToStringAnsi(buffer, sz);
_ = LocalFree(buffer);
return ret;
}
}