diff --git a/public/bin/RyzenAdjServiceTask.xml.template b/public/bin/RyzenAdjServiceTask.xml.template
new file mode 100644
index 0000000..296dcd5
--- /dev/null
+++ b/public/bin/RyzenAdjServiceTask.xml.template
@@ -0,0 +1,43 @@
+
+
+
+
+ true
+
+
+
+
+ InteractiveToken
+ HighestAvailable
+
+
+
+ IgnoreNew
+ false
+ false
+ true
+ false
+ false
+
+ false
+ false
+
+ true
+ true
+ false
+ false
+ false
+ PT0S
+ 7
+
+ PT60M
+ 10
+
+
+
+
+ powershell
+ -WindowStyle hidden -ExecutionPolicy Bypass -file "###SCRIPTPATH###"
+
+
+
diff --git a/public/bin/auto-start-ryzen-controller.bat b/public/bin/auto-start-ryzen-controller.bat
deleted file mode 100644
index 80fccf5..0000000
--- a/public/bin/auto-start-ryzen-controller.bat
+++ /dev/null
@@ -1 +0,0 @@
-"%~dp0..\..\..\elevate.exe" "%~dp0..\..\..\..\Ryzen Controller.exe"
diff --git a/public/bin/demo.bat b/public/bin/demo.bat
index 12a3ecc..5bcf94c 100644
--- a/public/bin/demo.bat
+++ b/public/bin/demo.bat
@@ -1,2 +1,2 @@
-%~dp0\ryzenadj.exe --stapm-limit=40000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90
-pause
\ No newline at end of file
+%~dp0\ryzenadj.exe --stapm-limit=40000 --fast-limit=45000 --slow-limit=45000 --tctl-temp=90
+pause
diff --git a/public/bin/inpoutx64.dll b/public/bin/inpoutx64.dll
new file mode 100644
index 0000000..82c343f
Binary files /dev/null and b/public/bin/inpoutx64.dll differ
diff --git a/public/bin/installServiceTask.bat b/public/bin/installServiceTask.bat
new file mode 100644
index 0000000..02df30e
--- /dev/null
+++ b/public/bin/installServiceTask.bat
@@ -0,0 +1,39 @@
+@echo off
+NET FILE 1>NUL 2>NUL
+if %errorlevel% NEQ 0 (
+ echo Installation need be run as Administrator to install a Task
+ pause
+ exit /B 0
+)
+
+cd /D "%~dp0"
+choice /C YN /M "Do you want to install Service based on directory %~dp0? It can not be changed after installation."
+if %ERRORLEVEL% NEQ 1 exit /B 1
+
+for %%f in (RyzenAdjServiceTask.xml.template readjustService.ps1 libryzenadj.dll WinRing0x64.dll WinRing0x64.sys inpoutx64.dll) do (
+ if not exist %%f echo %%f is missing && goto failed
+)
+
+echo Please configure RyzenAdjService by adding your prefered values in the top section of the powershell script.
+timeout /t 2 > NUL
+notepad "%~dp0\readjustService.ps1"
+
+powershell -Command "(gc '%~dp0RyzenAdjServiceTask.xml.template') -replace '###SCRIPTPATH###', '%~dp0readjustService.ps1' | Out-File -encoding ASCII '%~dp0RyzenAdjServiceTask.xml'"
+
+SCHTASKS /Create /TN "AMD\RyzenAdj" /XML "%~dp0RyzenAdjServiceTask.xml" /F || goto failed
+
+SCHTASKS /run /TN "AMD\RyzenAdj" || goto failed
+
+timeout /t 2 > NUL
+
+SCHTASKS /query /TN "AMD\RyzenAdj" || goto failed
+
+echo.
+echo Installation successfull
+pause
+exit /B 0
+
+:FAILED
+echo Installation failed
+pause
+exit /B 1
diff --git a/public/bin/libryzenadj.dll b/public/bin/libryzenadj.dll
index f8fa949..e2d76b2 100644
Binary files a/public/bin/libryzenadj.dll and b/public/bin/libryzenadj.dll differ
diff --git a/public/bin/libryzenadj.exp b/public/bin/libryzenadj.exp
deleted file mode 100644
index 788cb0f..0000000
Binary files a/public/bin/libryzenadj.exp and /dev/null differ
diff --git a/public/bin/libryzenadj.lib b/public/bin/libryzenadj.lib
deleted file mode 100644
index 3aa28f7..0000000
Binary files a/public/bin/libryzenadj.lib and /dev/null differ
diff --git a/public/bin/pmtable-example.py b/public/bin/pmtable-example.py
new file mode 100644
index 0000000..ec269a6
--- /dev/null
+++ b/public/bin/pmtable-example.py
@@ -0,0 +1,59 @@
+import os, sys, time
+from ctypes import *
+from shutil import copyfile
+
+lib_path = os.path.dirname(os.path.abspath(__file__))
+os.chdir(lib_path)
+
+if sys.platform == 'win32' or sys.platform == 'cygwin':
+ try:
+ os.add_dll_directory(lib_path)
+ except AttributeError:
+ pass #not needed for old python version
+
+ winring0_driver_file_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'WinRing0x64.sys')
+ if not os.path.isfile(winring0_driver_file_path):
+ copyfile(os.path.join(lib_path, 'WinRing0x64.sys'), winring0_driver_file_path)
+
+ lib = cdll.LoadLibrary('libryzenadj')
+else:
+ lib = cdll.LoadLibrary('libryzenadj.so')
+
+# define ctype mappings for types which can not be mapped automatically
+lib.init_ryzenadj.restype = c_void_p
+lib.get_table_ver.argtypes = [c_void_p]
+lib.get_table_size.argtypes = [c_void_p]
+lib.get_table_values.restype = POINTER(c_float)
+lib.get_table_values.argtypes = [c_void_p]
+lib.refresh_table.argtypes = [c_void_p]
+
+ry = lib.init_ryzenadj()
+
+if not ry:
+ sys.exit("RyzenAdj could not get initialized")
+
+print("pmtable version: {:x}".format(lib.get_table_ver(ry)))
+
+input("Press any key to show all pmtable values...")
+
+pmtable_size = lib.get_table_size(ry) // 4
+pmtable = lib.get_table_values(ry)
+
+while True:
+ lib.refresh_table(ry)
+ columns, lines = os.get_terminal_size()
+ table_columns = columns // 16 # 16 chars per table entry
+ os.system('cls' if sys.platform == 'win32' else 'clear')
+ table_rows = 0
+ for index in (range(pmtable_size)):
+ sys.stdout.write("{:3d}:{:8.2f}\t".format(index, pmtable[index]))
+ if index % table_columns == table_columns - 1:
+ sys.stdout.write('\n')
+ table_rows += 1
+ if table_rows >= lines - 1:
+ sys.stdout.write('{:d} More entries ...'.format(pmtable_size - 1 - index))
+ break
+
+ if index % table_columns != table_columns - 1: sys.stdout.write('\n')
+ sys.stdout.flush()
+ time.sleep(1)
diff --git a/public/bin/readjust.py b/public/bin/readjust.py
new file mode 100644
index 0000000..856dcc6
--- /dev/null
+++ b/public/bin/readjust.py
@@ -0,0 +1,70 @@
+import os, sys, time
+from ctypes import *
+from shutil import copyfile
+
+lib_path = os.path.dirname(os.path.abspath(__file__))
+os.chdir(lib_path)
+
+if sys.platform == 'win32' or sys.platform == 'cygwin':
+ try:
+ os.add_dll_directory(lib_path)
+ except AttributeError:
+ pass #not needed for old python version
+
+ winring0_driver_file_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'WinRing0x64.sys')
+ if not os.path.isfile(winring0_driver_file_path):
+ copyfile(os.path.join(lib_path, 'WinRing0x64.sys'), winring0_driver_file_path)
+
+ lib = cdll.LoadLibrary('libryzenadj')
+else:
+ lib = cdll.LoadLibrary('libryzenadj.so')
+
+# define ctype mappings for types which can not be mapped automatically
+lib.init_ryzenadj.restype = c_void_p
+lib.refresh_table.argtypes = [c_void_p]
+lib.get_fast_limit.restype = c_float
+lib.get_fast_limit.argtypes = [c_void_p]
+
+ry = lib.init_ryzenadj()
+
+if not ry:
+ sys.exit("RyzenAdj could not get initialized")
+
+error_messages = {
+ -1: "{:s} is not supported on this family\n",
+ -3: "{:s} is not supported on this SMU\n",
+ -4: "{:s} is rejected by SMU\n"
+}
+
+def adjust(field, value):
+ function_name = "set_" + field
+ adjust_func = lib.__getattr__(function_name)
+ adjust_func.argtypes = [c_void_p, c_ulong]
+ res = adjust_func(ry, value)
+ if res:
+ error = error_messages.get(res, "{:s} did fail with {:d}\n")
+ sys.stderr.write(error.format(function_name, res));
+
+def enable(field):
+ function_name = "set_" + field
+ adjust_func = lib.__getattr__(function_name)
+ adjust_func.argtypes = [c_void_p]
+ res = adjust_func(ry)
+ if res:
+ error = error_messages.get(res, "{:s} did fail with {:d}\n")
+ sys.stderr.write(error.format(function_name, res));
+
+print("Monitor if fast limit is not 35W")
+while True:
+ lib.refresh_table(ry)
+ limit = round(lib.get_fast_limit(ry))
+ if limit != 35:
+ print("reapply limits, because old limit was {:d}".format(limit))
+ adjust("fast_limit", 35000)
+ adjust("slow_limit", 22000)
+ adjust("slow_time", 30)
+ adjust("tctl_temp", 97)
+ adjust("apu_skin_temp_limit", 50)
+ adjust("vrmmax_current", 100000)
+ enable("max_performance")
+ time.sleep(3)
diff --git a/public/bin/readjustService.ps1 b/public/bin/readjustService.ps1
new file mode 100644
index 0000000..812cf47
--- /dev/null
+++ b/public/bin/readjustService.ps1
@@ -0,0 +1,450 @@
+<#
+.SYNOPSIS
+ Automates ryzenAdj calls based on custom conditions
+.DESCRIPTION
+ This script is designed to provide maximum flexibility to the user. For that reason it does not use parameters.
+ Instead of parameters, you need to populate the functions in the configuration section with your custom adjustments and additional custom code.
+.NOTES
+ SPDX-License-Identifier: LGPL
+ Falco Schaffrath
+#>
+
+Param([Parameter(Mandatory=$false)][switch]$noGUI)
+$Error.Clear()
+################################################################################
+#### Configuration Start
+################################################################################
+# WARNING: Use at your own risk!
+
+$pathToRyzenAdjDlls = Split-Path -Parent $PSCommandPath #script path is DLL path, needs to be absolut path if you define something else
+
+$showErrorPopupsDuringInit = $true
+# debug mode prints adjust success messages too instead of errorss only
+$debugMode = $false
+# if monitorField is set, this script does only adjust values if something did revert your monitored value. Clear monitorField String to disable monitoring
+# This needs to be an value which actually gets overwritten by your device firmware/software if no changes get detected, your settings will not reapplied
+$monitorField = "fast_limit"
+# Does reapply adjustments if power slider did change position, check $Script:acSlider or $Script:dcSlider to apply slider specific values
+$monitorPowerSlider = $true
+# HWiNFO needs to be restartet after this script did run the first time with this option
+$updateHWINFOSensors = $false
+# some Zen3 devices have a locked STAPM limit, this workarround resets the stapm timer to have unlimited stapm. Use max stapm_limit and stapm_time (usually 500) to triger as less resets as possible
+$resetSTAPMUsage = $false
+
+function doAdjust_ACmode {
+ $Script:repeatWaitTimeSeconds = 1 #only use values below 5s if you are using $monitorField
+ adjust "fast_limit" 46000
+ adjust "slow_limit" 25000
+ #adjust "slow_time" 30
+ #adjust "tctl_temp" 93
+ #adjust "apu_skin_temp_limit" 50
+ #adjust "vrmmax_current" 100000
+ #replace any_other_field with additional adjustments. Name is equal to RyzenAdj options but it uses _ instead of -
+ #adjust "any_other_field" 1234
+
+ #custom code, for example set fan controll back to auto
+ #values (WriteRegister: 47, FanSpeedResetValue:128) extracted from similar devices at https://github.com/hirschmann/nbfc/blob/master/Configs/
+ #Start-Process -NoNewWindow -Wait -filePath "C:\Program Files (x86)\NoteBook FanControl\ec-probe.exe" -ArgumentList("write", "47", "128")
+
+ if($Script:acSlider -eq $Script:betterBattery){
+ #put adjustments for energie saving slider position here:
+ enable "power_saving" #add 10s boost delay for usage on cable to reduce idle power consumtion
+ }
+}
+
+function doAdjust_BatteryMode {
+ $Script:repeatWaitTimeSeconds = 10 #do less reapplies and less HWiNFO updates to save power
+ adjust "fast_limit" 26000
+ adjust "slow_limit" 10000
+ #adjust "any_other_field" 1234
+
+ if($Script:dcSlider -eq $Script:betterBattery){
+ #put adjustments for energie saving slider position here: for example disable fan to save power
+ #Start-Process -NoNewWindow -Wait -filePath "C:\Program Files (x86)\NoteBook FanControl\ec-probe.exe" -ArgumentList("write", "47", "0")
+ }
+
+ if($Script:dcSlider -eq $Script:bestPerformance){
+ #put adjustments for highest performance slider position here:
+ enable "max_performance" #removes 10s boost delay on battery
+ doAdjust_ACmode #set limits from cable mode on battery
+ }
+}
+################################################################################
+#### Configuration End
+################################################################################
+
+$env:PATH += ";$pathToRyzenAdjDlls"
+$NL = $([System.Environment]::NewLine);
+
+if($noGUI){ $showErrorPopupsDuringInit = $false }
+
+$apiHeader = @'
+[DllImport("libryzenadj.dll")] public static extern IntPtr init_ryzenadj();
+[DllImport("libryzenadj.dll")] public static extern int set_stapm_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_fast_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_slow_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_slow_time(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_stapm_time(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_tctl_temp(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_vrm_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_vrmsoc_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_vrmmax_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_vrmsocmax_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_psi0_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_psi0soc_current(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_max_gfxclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_min_gfxclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_max_socclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_min_socclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_max_fclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_min_fclk_freq(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_max_vcn(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_min_vcn(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_max_lclk(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_min_lclk(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_prochot_deassertion_ramp(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_apu_skin_temp_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_dgpu_skin_temp_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_apu_slow_limit(IntPtr ry, [In]uint value);
+[DllImport("libryzenadj.dll")] public static extern int set_power_saving(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern int set_max_performance(IntPtr ry);
+
+[DllImport("libryzenadj.dll")] public static extern int refresh_table(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern IntPtr get_table_values(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_stapm_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_stapm_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_stapm_time(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_fast_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_fast_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_slow_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_slow_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_apu_slow_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_apu_slow_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrm_current(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrm_current_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmsoc_current(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmsoc_current_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmmax_current(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmmax_current_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmsocmax_current(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_vrmsocmax_current_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_tctl_temp(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_tctl_temp_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_apu_skin_temp_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_apu_skin_temp_value(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_dgpu_skin_temp_limit(IntPtr ry);
+[DllImport("libryzenadj.dll")] public static extern float get_dgpu_skin_temp_value(IntPtr ry);
+
+[DllImport("kernel32.dll")] public static extern uint GetModuleFileName(IntPtr hModule, [Out]StringBuilder lpFilename, [In]int nSize);
+[DllImport("kernel32.dll")] public static extern Boolean GetSystemPowerStatus(out SystemPowerStatus sps);
+public struct SystemPowerStatus {
+ public Byte ACLineStatus;
+ public Byte BatteryFlag;
+ public Byte BatteryLifePercent;
+ public Byte Reserved1;
+ public Int32 BatteryLifeTime;
+ public Int32 BatteryFullLifeTime;
+}
+
+public static String getExpectedWinRing0DriverFilepath(){
+ StringBuilder fileName = new StringBuilder(255);
+ GetModuleFileName(IntPtr.Zero, fileName, fileName.Capacity);
+ return Path.GetDirectoryName(fileName.ToString()) + "\\WinRing0x64.sys";
+}
+
+public static String getDllImportErrors(){
+ try {
+ Marshal.PrelinkAll(typeof(adj));
+ } catch (Exception e) {
+ return e.Message;
+ }
+ return "";
+}
+'@
+
+if(-not ([System.Management.Automation.PSTypeName]'ryzen.adj').Type){
+ Add-Type -MemberDefinition $apiHeader -Namespace 'ryzen' -Name 'adj' -UsingNamespace ('System.Text', 'System.IO')
+}
+
+Add-Type -AssemblyName System.Windows.Forms
+function showErrorMsg ([String] $msg){
+ if($showErrorPopupsDuringInit){
+ [void][System.Windows.Forms.MessageBox]::Show($msg, $PSCommandPath,
+ [System.Windows.Forms.MessageBoxButtons]::OK,
+ [System.Windows.Forms.MessageBoxIcon]::Error)
+ }
+}
+
+$dllImportErrors = [ryzen.adj]::getDllImportErrors();
+if($dllImportErrors -or $Error){
+ Write-Error $dllImportErrors
+ showErrorMsg "Problem with using libryzenadj.dll$NL$NL$($Error -join $NL)"
+ exit 1
+}
+
+$winring0DriverFilepath = [ryzen.adj]::getExpectedWinRing0DriverFilepath()
+if(!(Test-Path $winring0DriverFilepath)) { Copy-Item -Path $pathToRyzenAdjDlls\WinRing0x64.sys -Destination $winring0DriverFilepath }
+
+$ry = [ryzen.adj]::init_ryzenadj()
+if($ry -eq 0){
+ $msg = "RyzenAdj could not get initialized.$($NL)Reason can be found inside Powershell$($NL)"
+ if($psISE) { $msg += "It is not possible to see the error reason inside ISE, you need to test it in PowerShell Console" }
+ showErrorMsg "$msg$NL$NL$($Error -join $NL)"
+ exit 1
+}
+
+function adjust ([String] $fieldName, [uInt32] $value) {
+ if($fieldName -eq $Script:monitorField) {
+ $newTargetValue = [math]::round($value * 0.001, 3, 0)
+ if($Script:monitorFieldAdjTarget -ne $newTargetValue){
+ $Script:monitorFieldAdjTarget = $newTargetValue
+ Write-Host "set new monitoring target $fieldName to $newTargetValue"
+ }
+ }
+ $res = Invoke-Expression "[ryzen.adj]::set_$fieldName($ry, $value)"
+ switch ($res) {
+ 0 {
+ if($debugMode) { Write-Host "set $fieldName to $value" }
+ return
+ }
+ -1 { Write-Error "set_$fieldName is not supported on this family"}
+ -3 { Write-Error "set_$fieldName is not supported on this SMU"}
+ -4 { Write-Error "set_$fieldName is rejected by SMU"}
+ default { Write-Error "set_$fieldName did fail with $res"}
+ }
+}
+
+function enable ([String] $fieldName) {
+ $res = Invoke-Expression "[ryzen.adj]::set_$fieldName($ry)"
+ switch ($res) {
+ 0 {
+ if($debugMode) { Write-Host "enable $fieldName"}
+ return
+ }
+ -1 { Write-Error "set_$fieldName is not supported on this family"}
+ -3 { Write-Error "set_$fieldName is not supported on this SMU"}
+ -4 { Write-Error "set_$fieldName is rejected by SMU"}
+ default { Write-Error "set_$fieldName did fail with $res"}
+ }
+}
+
+function testMonitorField {
+ if($monitorField -and $Script:monitorFieldAdjTarget -eq 0){
+ Write-Error ("You forgot to set $monitorField in your profile.$NL$NL" +
+ "If you ignore it, the script will apply values unnessasary often.$NL")
+ }
+}
+
+function updateMonitorFieldAdjResult {
+ if($monitorField){
+ [void][ryzen.adj]::refresh_table($ry)
+ $Script:monitorFieldAdjResult = [math]::round((getMonitorValue), 3, 0)
+ if($Script:monitorFieldAdjTarget -ne $Script:monitorFieldAdjResult){
+ Write-Host ("Warning - $monitorField adjust result $Script:monitorFieldAdjResult does not match target value $Script:monitorFieldAdjTarget. Value $Script:monitorFieldAdjResult will be used for monitoring")
+ }
+ }
+}
+
+function testConfiguration {
+ Write-Host "Test Adjustments"
+ if($Script:systemPowerStatus.ACLineStatus){
+ doAdjust_BatteryMode
+ testMonitorField
+ $Script:monitorFieldAdjTarget = 0
+ doAdjust_ACmode
+ } else {
+ doAdjust_ACmode
+ testMonitorField
+ $Script:monitorFieldAdjTarget = 0
+ doAdjust_BatteryMode
+ }
+ testMonitorField
+ updateMonitorFieldAdjResult
+
+ if($resetSTAPMUsage -and [ryzen.adj]::get_stapm_time($ry) -eq 1) {
+ Write-Error "resetSTAPMUsage function does only work on devices with active STAPM control and don't do anything on devices with enabled STT control."
+ }
+
+ if($Error -and $showErrorPopupsDuringInit){
+ $answer = [System.Windows.Forms.MessageBox]::Show("Your Adjustment configuration did not work.$NL$NL$($Error -join $NL)", $PSCommandPath,
+ [System.Windows.Forms.MessageBoxButtons]::AbortRetryIgnore,
+ [System.Windows.Forms.MessageBoxIcon]::Warning)
+ $Error.Clear()
+ if($answer -eq "Abort"){ exit 1 }
+ if($answer -eq "Retry"){ testConfiguration }
+ }
+}
+
+function getMonitorValue {
+ if($monitorField){
+ return Invoke-Expression "[ryzen.adj]::get_$monitorField($ry)"
+ }
+ return 0
+}
+
+function createOrDeleteHWINFOSensors {
+ if($updateHWINFOSensors){
+ New-Item -Path HKCU:\Software\HWiNFO64\Sensors\Custom -Name RyzenAdj -Force > $null
+ 'Key,Name,Value
+ Power0,STAPM Limit
+ Power1,STAPM
+ Power2,PPT FAST Limit
+ Power3,PPT FAST
+ Power4,PPT SLOW Limit
+ Power5,PPT SLOW
+ Power6,APU SLOW Limit
+ Power7,APU SLOW
+ Current0,TDC VRM Limit
+ Current1,TDC VRM
+ Current2,TDC VRM SoC Limit
+ Current3,TDC VRM SoC
+ Current4,EDC VRM Max Limit
+ Current5,EDC VRM Max
+ Current6,EDC VRM SoC Max Limit
+ Current7,EDC VRM SoC Max
+ Temp0,TCTL Temp Limit
+ Temp1,TCTL Temp
+ Temp2,SST APU Skin Temp Limit
+ Temp3,SST APU Skin Temp
+ Temp4,SST dGPU Skin Temp Limit
+ Temp5,SST dGPU Skin Temp
+ Usage0,STAPM Limit Usage, ("STAPM" / "STAPM Limit") * 100
+ Usage1,PPT FAST Limit Usage, ("PPT FAST" / "PPT FAST Limit") * 100
+ Usage2,PPT SLOW Limit Usage, ("PPT SLOW" / "PPT SLOW Limit") * 100
+ Usage3,APU SLOW Limit Usage, ("APU SLOW" / "APU SLOW Limit") * 100
+ Usage4,TDC VRM Limit Usage, ("TDC VRM" / "TDC VRM Limit") * 100
+ Usage5,TDC VRM SoC Limit Usage, ("TDC VRM SoC" / "TDC VRM SoC Limit") * 100
+ Usage6,EDC VRM Max Limit Usage, ("EDC VRM Max" / "EDC VRM Max Limit") * 100
+ Usage7,EDC VRM SoC Max Limit Usage, ("EDC VRM SoC Max" / "EDC VRM SoC Max Limit") * 100
+ Usage8,TCTL Temp Limit Usage, ("TCTL Temp" / "TCTL Temp Limit") * 100
+ Usage9,SST APU Skin Temp Limit Usage, ("SST APU Skin Temp" / "SST APU Skin Temp Limit") * 100
+ Usage10,SST dGPU Skin Temp Limit Usage, ("SST dGPU Skin Temp" / "SST dGPU Skin Temp Limit") * 100' | ConvertFrom-Csv -outvariable hwinfo_keys > $null
+ $hwinfo_keys | ForEach-Object {New-item -Path HKCU:\Software\HWiNFO64\Sensors\Custom\RyzenAdj -Name $_.Key -Force} > $null
+ $hwinfo_keys | ForEach-Object {[Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $_.Key,"Name",$_.Name)} > $null
+ $hwinfo_keys | Where Value -ne $null | ForEach-Object {[Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $_.Key,"Value",$_.Value)} > $null
+ } else {
+ Remove-Item HKCU:\Software\HWiNFO64\Sensors\Custom\RyzenAdj -Recurse -ErrorAction:Ignore
+ }
+}
+
+function setHWINFOValue ([String] $name, [float] $value) {
+ if(![float]::IsNaN($value)){ [Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $name,"Value",[String]$value) }
+}
+
+function updateHWINFOSensors {
+ setHWINFOValue Power0 ([ryzen.adj]::get_stapm_limit($ry))
+ setHWINFOValue Power1 ([ryzen.adj]::get_stapm_value($ry))
+ setHWINFOValue Power2 ([ryzen.adj]::get_fast_limit($ry))
+ setHWINFOValue Power3 ([ryzen.adj]::get_fast_value($ry))
+ setHWINFOValue Power4 ([ryzen.adj]::get_slow_limit($ry))
+ setHWINFOValue Power5 ([ryzen.adj]::get_slow_value($ry))
+ setHWINFOValue Power6 ([ryzen.adj]::get_apu_slow_limit($ry))
+ setHWINFOValue Power7 ([ryzen.adj]::get_apu_slow_value($ry))
+ setHWINFOValue Current0 ([ryzen.adj]::get_vrm_current($ry))
+ setHWINFOValue Current1 ([ryzen.adj]::get_vrm_current_value($ry))
+ setHWINFOValue Current2 ([ryzen.adj]::get_vrmsoc_current($ry))
+ setHWINFOValue Current3 ([ryzen.adj]::get_vrmsoc_current_value($ry))
+ setHWINFOValue Current4 ([ryzen.adj]::get_vrmmax_current($ry))
+ setHWINFOValue Current5 ([ryzen.adj]::get_vrmmax_current_value($ry))
+ setHWINFOValue Current6 ([ryzen.adj]::get_vrmsocmax_current($ry))
+ setHWINFOValue Current7 ([ryzen.adj]::get_vrmsocmax_current_value($ry))
+ setHWINFOValue Temp0 ([ryzen.adj]::get_tctl_temp($ry))
+ setHWINFOValue Temp1 ([ryzen.adj]::get_tctl_temp_value($ry))
+ setHWINFOValue Temp2 ([ryzen.adj]::get_apu_skin_temp_limit($ry))
+ setHWINFOValue Temp3 ([ryzen.adj]::get_apu_skin_temp_value($ry))
+ setHWINFOValue Temp4 ([ryzen.adj]::get_dgpu_skin_temp_limit($ry))
+ setHWINFOValue Temp5 ([ryzen.adj]::get_dgpu_skin_temp_value($ry))
+ #setHWINFOValue Usage11 $pmTable[546]
+}
+
+function resetSTAPMIfNeeded {
+ $stapm_limit = [ryzen.adj]::get_stapm_limit($ry)
+ $stapm_value = [ryzen.adj]::get_stapm_value($ry)
+ $stapm_hysteresis = 1 #Throttling starts arround ~0.9W before limit
+
+ if ($stapm_value -gt ($stapm_limit - $stapm_hysteresis)) {
+ $stapm_time = [ryzen.adj]::get_stapm_time($ry)
+ $reduced_stapm_limit = ($stapm_limit - 5) #reduce stapm by 5W
+ Write-Host "[STAPM_RESET] stapm_value ($stapm_value) nearing stapm_limit ($stapm_limit), resetting..."
+ [void][ryzen.adj]::set_stapm_limit($ry, ($reduced_stapm_limit) * 1000)
+ [void][ryzen.adj]::set_stapm_time($ry, 0)
+ [Threading.Thread]::Sleep(10) #10ms is usually enough time
+ [void][ryzen.adj]::set_stapm_time($ry, $stapm_time)
+ [void][ryzen.adj]::set_stapm_limit($ry, $stapm_limit * 1250) # add 25% STAPM limit in case we are at battery saving mode where applied values get reduced by 10% or 20%
+ }
+}
+
+if(-not $Script:repeatWaitTimeSeconds) { $Script:repeatWaitTimeSeconds = 5 }
+$Script:monitorFieldAdjResult = 0; #adjust result will be used for monitoring because SMU may only set 90% and 80% of your value
+$Script:monitorFieldAdjTarget = 0;
+$powerkey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\ControlSet001\Control\Power\User\PowerSchemes\")
+$Script:betterBattery = "961cc777-2547-4f9d-8174-7d86181b8a7a"
+$Script:betterPerformance = "00000000-0000-0000-0000-000000000000"
+$Script:bestPerformance = "ded574b5-45a0-4f42-8737-46345c09c238"
+$Script:acSlider = $powerkey.GetValue("ActiveOverlayACPowerScheme")
+$Script:dcSlider = $powerkey.GetValue("ActiveOverlayDCPowerScheme")
+
+$systemPowerStatus = New-Object ryzen.adj+SystemPowerStatus
+[void][ryzen.adj]::GetSystemPowerStatus([ref]$systemPowerStatus)
+
+testConfiguration
+
+<# Example how to get 560 lines of ptable
+$pmTable = [float[]]::new(560)
+$tablePtr = [ryzen.adj]::get_table_values($ry);
+[System.Runtime.InteropServices.Marshal]::Copy($tablePtr, $pmTable, 0, 560);
+#>
+createOrDeleteHWINFOSensors
+
+$mtxtArray = @()
+if($monitorField){$mtxtArray += "$monitorField changes"}
+if($monitorPowerSlider){$mtxtArray += "PowerSlider changes"}
+if($mtxtArray.Length){
+ $processType = "Monitor " + ($mtxtArray -join " and ")
+} else {
+ $processType = "Apply Settings"
+}
+Write-Host "$processType every $Script:repeatWaitTimeSeconds seconds..."
+while($true) {
+ $doAdjust = !$monitorField -and !$monitorPowerSlider
+ if($monitorField -or $updateHWINFOSensors -or $resetSTAPMUsage) {
+ [void][ryzen.adj]::refresh_table($ry)
+ #[System.Runtime.InteropServices.Marshal]::Copy($tablePtr, $pmTable, 0, 560);
+ }
+
+ if($updateHWINFOSensors){
+ updateHWINFOSensors
+ }
+
+ if($monitorPowerSlider -and ($Script:acSlider -ne $powerkey.GetValue("ActiveOverlayACPowerScheme") -or $Script:dcSlider -ne $powerkey.GetValue("ActiveOverlayDCPowerScheme"))){
+ Write-Host "Power Slider changed"
+ $Script:acSlider = $powerkey.GetValue("ActiveOverlayACPowerScheme")
+ $Script:dcSlider = $powerkey.GetValue("ActiveOverlayDCPowerScheme")
+ $doAdjust = $true
+ }
+ if($monitorField){
+ $monitorValue = getMonitorValue
+ if($Script:monitorFieldAdjResult -ne [math]::round($monitorValue, 3, 0)){
+ Write-Host "$monitorField value unexpectedly changed from $Script:monitorFieldAdjResult to $monitorValue"
+ $doAdjust = $true
+ }
+ }
+
+ if($resetSTAPMUsage){
+ resetSTAPMIfNeeded
+ }
+
+ if($doAdjust){
+ [void][ryzen.adj]::GetSystemPowerStatus([ref]$systemPowerStatus)
+ $oldWait = $Script:repeatWaitTimeSeconds
+ if($systemPowerStatus.ACLineStatus){
+ doAdjust_ACmode
+ } else {
+ doAdjust_BatteryMode
+ }
+ updateMonitorFieldAdjResult
+ if($oldWait -ne $Script:repeatWaitTimeSeconds ) { Write-Host "$processType every $Script:repeatWaitTimeSeconds seconds..." }
+ }
+
+ sleep $Script:repeatWaitTimeSeconds
+}
diff --git a/public/bin/ryzenadj.exe b/public/bin/ryzenadj.exe
index 7eb7071..ea689f2 100644
Binary files a/public/bin/ryzenadj.exe and b/public/bin/ryzenadj.exe differ
diff --git a/public/bin/ryzenadj.h b/public/bin/ryzenadj.h
deleted file mode 100644
index 5eb2eb1..0000000
--- a/public/bin/ryzenadj.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: LGPL */
-/* Copyright (C) 2019 Jiaxun Yang */
-/* RyzenAdj API */
-
-#ifndef RYZENADJ_H
-#define RYZENADJ_H
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include "nb_smu_ops.h"
-
-#ifdef _WIN32
-#define EXP __declspec(dllexport)
-#define CALL __stdcall
-#else
-#define EXP
-#define CALL
-#endif
-
-#define RYZENADJ_VER 5
-
-typedef struct {
- nb_t nb;
- pci_obj_t pci_obj;
- smu_t mp1_smu;
- smu_t psmu;
-} *ryzen_access;
-
-EXP ryzen_access CALL init_ryzenadj();
-
-EXP void CALL cleanup_ryzenadj(ryzen_access ry);
-
-EXP int CALL set_stapm_limit(ryzen_access, uint32_t value);
-EXP int CALL set_fast_limit(ryzen_access, uint32_t value);
-EXP int CALL set_slow_limit(ryzen_access, uint32_t value);
-EXP int CALL set_slow_time(ryzen_access, uint32_t value);
-EXP int CALL set_stapm_time(ryzen_access, uint32_t value);
-EXP int CALL set_tctl_temp(ryzen_access, uint32_t value);
-EXP int CALL set_vrm_current(ryzen_access, uint32_t value);
-EXP int CALL set_vrmsoc_current(ryzen_access, uint32_t value);
-EXP int CALL set_vrmmax_current(ryzen_access, uint32_t value);
-EXP int CALL set_vrmsocmax_current(ryzen_access, uint32_t value);
-EXP int CALL set_psi0_current(ryzen_access, uint32_t value);
-EXP int CALL set_psi0soc_current(ryzen_access, uint32_t value);
-EXP int CALL set_max_gfxclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_min_gfxclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_max_socclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_min_socclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_max_fclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_min_fclk_freq(ryzen_access, uint32_t value);
-EXP int CALL set_max_vcn(ryzen_access, uint32_t value);
-EXP int CALL set_min_vcn(ryzen_access, uint32_t value);
-EXP int CALL set_max_lclk(ryzen_access, uint32_t value);
-EXP int CALL set_min_lclk(ryzen_access, uint32_t value);
-
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/public/bin/uninstallServiceTask.bat b/public/bin/uninstallServiceTask.bat
new file mode 100644
index 0000000..6973e10
--- /dev/null
+++ b/public/bin/uninstallServiceTask.bat
@@ -0,0 +1,23 @@
+@echo off
+NET FILE 1>NUL 2>NUL
+if %errorlevel% NEQ 0 (
+ echo Deinstallation need to be run as Administrator to delete your Scheduled Task
+ pause
+ exit /B 0
+)
+
+reg query HKCU\Software\HWiNFO64\Sensors\Custom\RyzenAdj 2>NUL
+if %errorlevel% EQU 0 reg delete HKCU\Software\HWiNFO64\Sensors\Custom\RyzenAdj
+
+SCHTASKS /query /TN "AMD\RyzenAdj" 2>NUL
+
+if %errorlevel% NEQ 0 (
+ echo RyzenAdj Service Task is not installed
+ pause
+ exit /B 0
+)
+
+SCHTASKS /delete /TN "AMD\RyzenAdj" 2>NUL
+
+pause
+exit /B 0