mirror of
https://github.com/ayufan/steam-deck-tools.git
synced 2026-01-20 15:30:28 +01:00
PowerControl: Support RTSS in custom folder
This commit is contained in:
parent
e1a4073a7c
commit
bc9c3199b7
|
|
@ -22,7 +22,7 @@ namespace CommonHelpers
|
|||
|
||||
private static string[] RTSS = new string[]
|
||||
{
|
||||
"C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll"
|
||||
"RTSSHooks64.dll"
|
||||
};
|
||||
|
||||
private static string VCRuntimeURL = "https://aka.ms/vs/17/release/vc_redist.x64.exe";
|
||||
|
|
@ -40,87 +40,163 @@ namespace CommonHelpers
|
|||
ValidateDependency(title, "RTSSSharedMemoryNET", RTSSShared, false);
|
||||
}
|
||||
|
||||
public static void ValidateRTSS(string title)
|
||||
public static bool EnsureRTSS(string? title = null)
|
||||
{
|
||||
InstallDependency(title, "Rivatuner Statistics Server", RTSS, RTSSURL, false, false);
|
||||
string? libraryPath = null;
|
||||
|
||||
try
|
||||
{
|
||||
libraryPath = Microsoft.Win32.Registry.GetValue(
|
||||
@"HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Unwinder\RTSS",
|
||||
"InstallDir",
|
||||
null
|
||||
) as string;
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
return EnsureDependency(title, "Rivatuner Statistics Server", RTSS, libraryPath, RTSSURL, false);
|
||||
}
|
||||
|
||||
private static void ValidateVCRuntime(string title)
|
||||
{
|
||||
InstallDependency(title, "Microsoft Visual C++ Runtime", VCRuntime, VCRuntimeURL, true, false);
|
||||
InstallDependency(title, "Microsoft Visual C++ Runtime", VCRuntime, null, VCRuntimeURL, true, false);
|
||||
}
|
||||
|
||||
private static void ValidateDependency(string title, string name, string[] dllNames, bool unload = true)
|
||||
{
|
||||
if (TryToLoad(dllNames, unload))
|
||||
if (TryToLoad(dllNames, null, unload))
|
||||
return;
|
||||
|
||||
Log.TraceError("Cannot load: {0}", dllNames);
|
||||
|
||||
MessageBox.Show(
|
||||
"Cannot load: " + string.Join(", ", dllNames) + ".\n\n" +
|
||||
"Application will exit.\n",
|
||||
var result = ShowDialog(
|
||||
title,
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error
|
||||
name,
|
||||
"Failure in loading the " + string.Join(", ", dllNames) + ".\n\n" +
|
||||
"This is required dependency. Application will exit.\n",
|
||||
null,
|
||||
TaskDialogButton.Close
|
||||
);
|
||||
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
private static void InstallDependency(string title, string name, string[] dllNames, string url, bool required = true, bool unload = true)
|
||||
private static bool EnsureDependency(string? title, string name, string[] dllNames, string? libraryPath, string url, bool required = true)
|
||||
{
|
||||
if (TryToLoad(dllNames, unload))
|
||||
if (TryToLoad(dllNames, libraryPath, false))
|
||||
return true;
|
||||
|
||||
Log.TraceError("Cannot load: {0}", dllNames);
|
||||
|
||||
if (title == null)
|
||||
return false;
|
||||
|
||||
var downloadButton = new TaskDialogButton("Download");
|
||||
|
||||
var result = ShowDialog(
|
||||
title,
|
||||
name,
|
||||
"Failure in loading the " + string.Join(", ", dllNames) + ".\n\n" +
|
||||
"The '" + name + "' is likely not installed.\n" +
|
||||
"Click Download to download it.\n",
|
||||
url,
|
||||
downloadButton,
|
||||
TaskDialogButton.Ignore
|
||||
);
|
||||
|
||||
if (result == downloadButton)
|
||||
ExecuteLink(url);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void InstallDependency(string title, string name, string[] dllNames, string? libraryPath, string url, bool required = true, bool unload = true)
|
||||
{
|
||||
if (TryToLoad(dllNames, libraryPath, unload))
|
||||
return;
|
||||
|
||||
Log.TraceError("Cannot load: {0}", dllNames);
|
||||
|
||||
var result = MessageBox.Show(
|
||||
"Missing '" + name + "' (" + string.Join(", ", dllNames) + ").\n\n" +
|
||||
"Click Yes to download and install?\n",
|
||||
var downloadButton = new TaskDialogButton("Download");
|
||||
var exitButton = new TaskDialogButton("Exit");
|
||||
|
||||
var result = ShowDialog(
|
||||
title,
|
||||
MessageBoxButtons.YesNo,
|
||||
MessageBoxIcon.Error
|
||||
name,
|
||||
"Failure in loading the " + string.Join(", ", dllNames) + ".\n\n" +
|
||||
"The '" + name + "' is likely not installed.\n" +
|
||||
"Click Download to download it.\n" +
|
||||
(required ? "Once installed start application again.\n" : ""),
|
||||
url,
|
||||
downloadButton,
|
||||
required ? exitButton : TaskDialogButton.Ignore
|
||||
);
|
||||
|
||||
if (result == DialogResult.Yes)
|
||||
if (result == downloadButton)
|
||||
{
|
||||
ExecuteLink(url);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
|
||||
if (required)
|
||||
else if (result == exitButton)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"The '" + name + "' is required. " +
|
||||
"Application will exit now. " +
|
||||
"Once installed start application again.",
|
||||
title,
|
||||
MessageBoxButtons.OK,
|
||||
MessageBoxIcon.Error
|
||||
);
|
||||
Environment.Exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool TryToLoad(string[] dllNames, bool unload = true)
|
||||
private static bool TryToLoad(string[] dllNames, string? libraryPath, bool unload = true)
|
||||
{
|
||||
foreach (var dllName in dllNames)
|
||||
{
|
||||
if (!TryToLoad(dllName, unload))
|
||||
if (!TryToLoad(dllName, libraryPath, unload))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static bool TryToLoad(string dllName, bool unload = true)
|
||||
private static bool IsLoaded(string dllName)
|
||||
{
|
||||
return GetModuleHandle(dllName) != IntPtr.Zero;
|
||||
}
|
||||
|
||||
private static bool TryToLoad(string dllName, String? libraryPath = null, bool unload = true)
|
||||
{
|
||||
if (IsLoaded(dllName))
|
||||
return true;
|
||||
|
||||
var handle = LoadLibrary(dllName);
|
||||
if (handle == IntPtr.Zero && libraryPath is not null)
|
||||
handle = LoadLibrary(Path.Join(libraryPath, dllName));
|
||||
if (unload)
|
||||
FreeLibrary(handle);
|
||||
return handle != IntPtr.Zero;
|
||||
}
|
||||
|
||||
private static TaskDialogButton ShowDialog(string caption, string heading, string text, string? url, params TaskDialogButton[] buttons)
|
||||
{
|
||||
var page = new TaskDialogPage();
|
||||
page.Caption = caption;
|
||||
foreach (var button in buttons)
|
||||
page.Buttons.Add(button);
|
||||
page.Icon = TaskDialogIcon.ShieldWarningYellowBar;
|
||||
page.Heading = heading;
|
||||
page.Text = text;
|
||||
if (page.Buttons.Contains(TaskDialogButton.Help) && url is not null)
|
||||
{
|
||||
page.Footnote = new TaskDialogFootnote("Click help to download it.");
|
||||
page.Footnote.Icon = TaskDialogIcon.Information;
|
||||
|
||||
page.HelpRequest += delegate
|
||||
{
|
||||
try { ExecuteLink(url); }
|
||||
catch { }
|
||||
};
|
||||
}
|
||||
|
||||
return TaskDialog.ShowDialog(new Form { TopMost = true }, page, TaskDialogStartupLocation.CenterScreen);
|
||||
}
|
||||
|
||||
private static void ExecuteLink(string link)
|
||||
{
|
||||
try { Process.Start("explorer.exe", link); }
|
||||
|
|
@ -133,5 +209,8 @@ namespace CommonHelpers
|
|||
[DllImport("kernel32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool FreeLibrary(IntPtr module);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern IntPtr GetModuleHandle(string moduleName);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@ namespace CommonHelpers
|
|||
{
|
||||
public static class RTSS
|
||||
{
|
||||
private const uint WM_APP = 0x8000;
|
||||
private const uint WM_RTSS_UPDATESETTINGS = WM_APP + 100;
|
||||
private const uint WM_RTSS_SHOW_PROPERTIES = WM_APP + 102;
|
||||
|
||||
private const uint RTSSHOOKSFLAG_OSD_VISIBLE = 1;
|
||||
private const uint RTSSHOOKSFLAG_LIMITER_DISABLED = 4;
|
||||
private const string GLOBAL_PROFILE = "";
|
||||
|
||||
public static bool GetProfileProperty<T>(string propertyName, out T value)
|
||||
{
|
||||
var bytes = new byte[Marshal.SizeOf<T>()];
|
||||
|
|
@ -58,38 +66,6 @@ namespace CommonHelpers
|
|||
PostMessage(WM_RTSS_UPDATESETTINGS, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll")]
|
||||
public static extern uint SetFlags(uint dwAND, uint dwXOR);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void LoadProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void SaveProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void DeleteProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern bool GetProfileProperty(string propertyName, IntPtr value, uint size);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern bool SetProfileProperty(string propertyName, IntPtr value, uint size);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void ResetProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("C:\\Program Files (x86)\\RivaTuner Statistics Server\\RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void UpdateProfiles();
|
||||
|
||||
|
||||
private static void PostMessage(uint Msg, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
var hWnd = FindWindow(null, "RTSS");
|
||||
|
|
@ -100,12 +76,35 @@ namespace CommonHelpers
|
|||
PostMessage(hWnd, Msg, wParam, lParam);
|
||||
}
|
||||
|
||||
public const uint WM_APP = 0x8000;
|
||||
public const uint WM_RTSS_UPDATESETTINGS = WM_APP + 100;
|
||||
public const uint WM_RTSS_SHOW_PROPERTIES = WM_APP + 102;
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||
static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
public const uint RTSSHOOKSFLAG_OSD_VISIBLE = 1;
|
||||
public const uint RTSSHOOKSFLAG_LIMITER_DISABLED = 4;
|
||||
public const string GLOBAL_PROFILE = "";
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||
|
||||
[DllImport("RTSSHooks64.dll")]
|
||||
public static extern uint SetFlags(uint dwAND, uint dwXOR);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void LoadProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void SaveProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void DeleteProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern bool GetProfileProperty(string propertyName, IntPtr value, uint size);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern bool SetProfileProperty(string propertyName, IntPtr value, uint size);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void ResetProfile(string profile = GLOBAL_PROFILE);
|
||||
|
||||
[DllImport("RTSSHooks64.dll", CharSet = CharSet.Ansi)]
|
||||
public static extern void UpdateProfiles();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,22 +26,29 @@ namespace PowerControl.Options
|
|||
{
|
||||
try
|
||||
{
|
||||
if (!Dependencies.EnsureRTSS(null))
|
||||
return "?";
|
||||
|
||||
RTSS.LoadProfile();
|
||||
if (RTSS.GetProfileProperty("FramerateLimit", out int framerate))
|
||||
return (framerate == 0) ? "Off" : framerate.ToString();
|
||||
return null;
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
#if DEBUG
|
||||
CommonHelpers.Log.TraceException("RTSS", e);
|
||||
#endif
|
||||
return "?";
|
||||
}
|
||||
return null;
|
||||
},
|
||||
ApplyValue = (selected) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Dependencies.EnsureRTSS(Controller.TitleWithVersion))
|
||||
return null;
|
||||
|
||||
int framerate = 0;
|
||||
if (selected != "Off")
|
||||
framerate = int.Parse(selected);
|
||||
|
|
@ -55,7 +62,7 @@ namespace PowerControl.Options
|
|||
RTSS.UpdateProfiles();
|
||||
return (framerate == 0) ? "Off" : framerate.ToString();
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
CommonHelpers.Log.TraceException("RTSS", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
## 0.6.x
|
||||
|
||||
- PowerControl: Support RTSS in custom folder
|
||||
- SteamController: Fix Steam Big Picture detection for non-english
|
||||
- PowerControl: Allow user to configure selectable TDP, CPU and GPU from `PowerControl.dll.ini`
|
||||
- SteamController: Promote RTSS detection to Release - enable by default
|
||||
|
|
|
|||
Loading…
Reference in a new issue