SHA256
Add CommonWarningDialogUI and RegistryUtil to Support NVIDIA Driver Warning
This commit is contained in:
7 files changed
+539
-10
No files matched your search
+59
-1
@@ -34,7 +34,7 @@ namespace ADOFAIRenderer.Util
|
||||
};
|
||||
|
||||
private static GPUVendor _cachedVendor = GPUVendor.Unknown;
|
||||
private static bool _hasCachedVendor = false;
|
||||
private static bool _hasCachedVendor;
|
||||
|
||||
private static GPUVendor GetActiveGPUVendor()
|
||||
{
|
||||
@@ -72,6 +72,64 @@ namespace ADOFAIRenderer.Util
|
||||
return _cachedVendor;
|
||||
}
|
||||
|
||||
private static double? _cachedNvidiaVersion;
|
||||
private static bool _hasCachedNvidiaVersion;
|
||||
|
||||
public static double? GetNvidiaDriverVersion()
|
||||
{
|
||||
if (_hasCachedNvidiaVersion) return _cachedNvidiaVersion;
|
||||
|
||||
_hasCachedNvidiaVersion = true;
|
||||
_cachedNvidiaVersion = null;
|
||||
|
||||
if (GetActiveGPUVendor() != GPUVendor.NVIDIA) return null;
|
||||
|
||||
// 1. Try parsing from UnityEngine.SystemInfo.graphicsDeviceVersion
|
||||
var deviceVersion = UnityEngine.SystemInfo.graphicsDeviceVersion;
|
||||
if (!string.IsNullOrEmpty(deviceVersion))
|
||||
{
|
||||
var match = Regex.Match(deviceVersion, @"\b(\d+)\.(\d+)\.(\d+)\.(\d+)\b");
|
||||
if (match.Success)
|
||||
{
|
||||
if (int.TryParse(match.Groups[3].Value, out int sub) && int.TryParse(match.Groups[4].Value, out int build))
|
||||
{
|
||||
var nvidiaVerInt = sub % 10 * 10000 + build;
|
||||
_cachedNvidiaVersion = nvidiaVerInt / 100.0;
|
||||
Melon<RenderMod>.Logger.Msg($"Parsed NVIDIA Driver Version from SystemInfo: {_cachedNvidiaVersion:F2}");
|
||||
return _cachedNvidiaVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Fallback to Windows Registry (only on Windows NT platforms via RegistryUtil)
|
||||
if (System.Environment.OSVersion.Platform != System.PlatformID.Win32NT) return null;
|
||||
const string classKey = @"SYSTEM\CurrentControlSet\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}";
|
||||
var subkeys = RegistryUtil.GetHKLMSubKeyNames(classKey);
|
||||
if (subkeys == null) return null;
|
||||
|
||||
foreach (var subkey in subkeys)
|
||||
{
|
||||
var subkeyPath = classKey + "\\" + subkey;
|
||||
var provider = RegistryUtil.GetHKLMValue(subkeyPath, "ProviderName");
|
||||
if (provider == null || !provider.Contains("NVIDIA")) continue;
|
||||
|
||||
var driverVersionStr = RegistryUtil.GetHKLMValue(subkeyPath, "DriverVersion");
|
||||
if (string.IsNullOrEmpty(driverVersionStr)) continue;
|
||||
|
||||
var regMatch = Regex.Match(driverVersionStr, @"\b(\d+)\.(\d+)\.(\d+)\.(\d+)\b");
|
||||
if (!regMatch.Success) continue;
|
||||
if (!int.TryParse(regMatch.Groups[3].Value, out var sub) ||
|
||||
!int.TryParse(regMatch.Groups[4].Value, out var build)) continue;
|
||||
|
||||
var nvidiaVerInt = sub % 10 * 10000 + build;
|
||||
_cachedNvidiaVersion = nvidiaVerInt / 100f;
|
||||
Melon<RenderMod>.Logger.Msg($"Parsed NVIDIA Driver Version from Registry (RegistryUtil): {_cachedNvidiaVersion:F2}");
|
||||
return _cachedNvidiaVersion;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<string> GetPrioritizedEncoderCandidates(Codec codec)
|
||||
{
|
||||
if (!CodecMap.TryGetValue(codec, out var list)) return new List<string>();
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
using System;
|
||||
|
||||
namespace ADOFAIRenderer.Util
|
||||
{
|
||||
public static class RegistryUtil
|
||||
{
|
||||
private static readonly Type? RegistryKeyType;
|
||||
private static readonly Type? RegistryHiveType;
|
||||
private static readonly Type? RegistryViewType;
|
||||
private static readonly System.Reflection.MethodInfo? OpenBaseKeyMethod;
|
||||
private static readonly System.Reflection.MethodInfo? OpenSubKeyMethod;
|
||||
private static readonly System.Reflection.MethodInfo? GetSubKeyNamesMethod;
|
||||
private static readonly System.Reflection.MethodInfo? GetValueMethod;
|
||||
|
||||
static RegistryUtil()
|
||||
{
|
||||
try
|
||||
{
|
||||
RegistryKeyType = Type.GetType("Microsoft.Win32.RegistryKey");
|
||||
RegistryHiveType = Type.GetType("Microsoft.Win32.RegistryHive");
|
||||
RegistryViewType = Type.GetType("Microsoft.Win32.RegistryView");
|
||||
|
||||
if (RegistryKeyType == null || RegistryHiveType == null || RegistryViewType == null)
|
||||
{
|
||||
var mscorlib = typeof(object).Assembly;
|
||||
RegistryKeyType = mscorlib.GetType("Microsoft.Win32.RegistryKey");
|
||||
RegistryHiveType = mscorlib.GetType("Microsoft.Win32.RegistryHive");
|
||||
RegistryViewType = mscorlib.GetType("Microsoft.Win32.RegistryView");
|
||||
}
|
||||
|
||||
if (RegistryKeyType != null)
|
||||
{
|
||||
OpenBaseKeyMethod = RegistryKeyType.GetMethod("OpenBaseKey", new[] { RegistryHiveType!, RegistryViewType! });
|
||||
OpenSubKeyMethod = RegistryKeyType.GetMethod("OpenSubKey", new[] { typeof(string) });
|
||||
GetSubKeyNamesMethod = RegistryKeyType.GetMethod("GetSubKeyNames");
|
||||
GetValueMethod = RegistryKeyType.GetMethod("GetValue", new[] { typeof(string) });
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
private static void CloseKey(object? key)
|
||||
{
|
||||
if (key == null || RegistryKeyType == null) return;
|
||||
try
|
||||
{
|
||||
if (key is IDisposable disposable)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
var closeMethod = RegistryKeyType.GetMethod("Close");
|
||||
closeMethod?.Invoke(key, null);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static string[]? GetHKLMSubKeyNames(string parentKeyPath)
|
||||
{
|
||||
if (RegistryKeyType == null || OpenBaseKeyMethod == null || OpenSubKeyMethod == null || GetSubKeyNamesMethod == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
object hiveLocalMachine = Enum.ToObject(RegistryHiveType!, 0x80000002);
|
||||
object viewRegistry64 = Enum.ToObject(RegistryViewType!, 256);
|
||||
|
||||
object? baseKey = OpenBaseKeyMethod.Invoke(null, new[] { hiveLocalMachine, viewRegistry64 });
|
||||
if (baseKey == null) return null;
|
||||
|
||||
object? key = OpenSubKeyMethod.Invoke(baseKey, new object[] { parentKeyPath });
|
||||
if (key == null)
|
||||
{
|
||||
CloseKey(baseKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
string[]? subkeyNames = GetSubKeyNamesMethod.Invoke(key, null) as string[];
|
||||
CloseKey(key);
|
||||
CloseKey(baseKey);
|
||||
return subkeyNames;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static string? GetHKLMValue(string keyPath, string valueName)
|
||||
{
|
||||
if (RegistryKeyType == null || OpenBaseKeyMethod == null || OpenSubKeyMethod == null || GetValueMethod == null)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
object hiveLocalMachine = Enum.ToObject(RegistryHiveType!, 0x80000002);
|
||||
object viewRegistry64 = Enum.ToObject(RegistryViewType!, 256);
|
||||
|
||||
object? baseKey = OpenBaseKeyMethod.Invoke(null, new[] { hiveLocalMachine, viewRegistry64 });
|
||||
if (baseKey == null) return null;
|
||||
|
||||
object? key = OpenSubKeyMethod.Invoke(baseKey, new object[] { keyPath });
|
||||
if (key == null)
|
||||
{
|
||||
CloseKey(baseKey);
|
||||
return null;
|
||||
}
|
||||
|
||||
string? value = GetValueMethod.Invoke(key, new object[] { valueName }) as string;
|
||||
CloseKey(key);
|
||||
CloseKey(baseKey);
|
||||
return value;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user