diff --git a/HandheldCompanion.iss b/HandheldCompanion.iss
index 1c6ae8a71..d7134cd2a 100644
--- a/HandheldCompanion.iss
+++ b/HandheldCompanion.iss
@@ -1,597 +1,583 @@
-; -----------
-; CODE
-; -----------
-[Code]
-// types and variables
-type
- TDependency_Entry = record
- Filename: String;
- Parameters: String;
- Title: String;
- URL: String;
- Checksum: String;
- ForceSuccess: Boolean;
- RestartAfter: Boolean;
- end;
-
-var
- Dependency_Memo: String;
- Dependency_List: array of TDependency_Entry;
- Dependency_NeedRestart, Dependency_ForceX86: Boolean;
- Dependency_DownloadPage: TDownloadWizardPage;
-
-procedure Dependency_Add(const Filename, Parameters, Title, URL, Checksum: String; const ForceSuccess, RestartAfter: Boolean);
-var
- Dependency: TDependency_Entry;
- DependencyCount: Integer;
-begin
- Dependency_Memo := Dependency_Memo + #13#10 + '%1' + Title;
-
- Dependency.Filename := Filename;
- Dependency.Parameters := Parameters;
- Dependency.Title := Title;
-
- if FileExists(ExpandConstant('{tmp}{\}') + Filename) then begin
- Dependency.URL := '';
- end else begin
- Dependency.URL := URL;
- end;
-
- Dependency.Checksum := Checksum;
- Dependency.ForceSuccess := ForceSuccess;
- Dependency.RestartAfter := RestartAfter;
-
- DependencyCount := GetArrayLength(Dependency_List);
- SetArrayLength(Dependency_List, DependencyCount + 1);
- Dependency_List[DependencyCount] := Dependency;
-end;
-
-procedure Dependency_InitializeWizard;
-begin
- Dependency_DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil);
-end;
-
-function Dependency_PrepareToInstall(var NeedsRestart: Boolean): String;
-var
- DependencyCount, DependencyIndex, ResultCode: Integer;
- Retry: Boolean;
- TempValue: String;
-begin
- DependencyCount := GetArrayLength(Dependency_List);
-
- if DependencyCount > 0 then begin
- Dependency_DownloadPage.Show;
-
- for DependencyIndex := 0 to DependencyCount - 1 do begin
- if Dependency_List[DependencyIndex].URL <> '' then begin
- Dependency_DownloadPage.Clear;
- Dependency_DownloadPage.Add(Dependency_List[DependencyIndex].URL, Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Checksum);
-
- Retry := True;
- while Retry do begin
- Retry := False;
-
- try
- Dependency_DownloadPage.Download;
- except
- if Dependency_DownloadPage.AbortedByUser then begin
- Result := Dependency_List[DependencyIndex].Title;
- DependencyIndex := DependencyCount;
- end else begin
- case SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
- IDABORT: begin
- Result := Dependency_List[DependencyIndex].Title;
- DependencyIndex := DependencyCount;
- end;
- IDRETRY: begin
- Retry := True;
- end;
- end;
- end;
- end;
- end;
- end;
- end;
-
- if Result = '' then begin
- for DependencyIndex := 0 to DependencyCount - 1 do begin
- Dependency_DownloadPage.SetText(Dependency_List[DependencyIndex].Title, '');
- Dependency_DownloadPage.SetProgress(DependencyIndex + 1, DependencyCount + 1);
-
- while True do begin
- ResultCode := 0;
- if ShellExec('', ExpandConstant('{tmp}{\}') + Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then begin
- if Dependency_List[DependencyIndex].RestartAfter then begin
- if DependencyIndex = DependencyCount - 1 then begin
- Dependency_NeedRestart := True;
- end else begin
- NeedsRestart := True;
- Result := Dependency_List[DependencyIndex].Title;
- end;
- break;
- end else if (ResultCode = 0) or Dependency_List[DependencyIndex].ForceSuccess then begin // ERROR_SUCCESS (0)
- break;
- end else if ResultCode = 1641 then begin // ERROR_SUCCESS_REBOOT_INITIATED (1641)
- NeedsRestart := True;
- Result := Dependency_List[DependencyIndex].Title;
- break;
- end else if ResultCode = 3010 then begin // ERROR_SUCCESS_REBOOT_REQUIRED (3010)
- Dependency_NeedRestart := True;
- break;
- end;
- end;
-
- case SuppressibleMsgBox(FmtMessage(SetupMessage(msgErrorFunctionFailed), [Dependency_List[DependencyIndex].Title, IntToStr(ResultCode)]), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
- IDABORT: begin
- Result := Dependency_List[DependencyIndex].Title;
- break;
- end;
- IDIGNORE: begin
- break;
- end;
- end;
- end;
-
- if Result <> '' then begin
- break;
- end;
- end;
-
- if NeedsRestart then begin
- TempValue := '"' + ExpandConstant('{srcexe}') + '" /restart=1 /LANG="' + ExpandConstant('{language}') + '" /DIR="' + WizardDirValue + '" /GROUP="' + WizardGroupValue + '" /TYPE="' + WizardSetupType(False) + '" /COMPONENTS="' + WizardSelectedComponents(False) + '" /TASKS="' + WizardSelectedTasks(False) + '"';
- if WizardNoIcons then begin
- TempValue := TempValue + ' /NOICONS';
- end;
- RegWriteStringValue(HKA, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', '{#SetupSetting("AppName")}', TempValue);
- end;
- end;
-
- Dependency_DownloadPage.Hide;
- end;
-end;
-
-function Dependency_UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
-begin
- Result := '';
- if MemoUserInfoInfo <> '' then begin
- Result := Result + MemoUserInfoInfo + Newline + NewLine;
- end;
- if MemoDirInfo <> '' then begin
- Result := Result + MemoDirInfo + Newline + NewLine;
- end;
- if MemoTypeInfo <> '' then begin
- Result := Result + MemoTypeInfo + Newline + NewLine;
- end;
- if MemoComponentsInfo <> '' then begin
- Result := Result + MemoComponentsInfo + Newline + NewLine;
- end;
- if MemoGroupInfo <> '' then begin
- Result := Result + MemoGroupInfo + Newline + NewLine;
- end;
- if MemoTasksInfo <> '' then begin
- Result := Result + MemoTasksInfo;
- end;
-
- if Dependency_Memo <> '' then begin
- if MemoTasksInfo = '' then begin
- Result := Result + SetupMessage(msgReadyMemoTasks);
- end;
- Result := Result + FmtMessage(Dependency_Memo, [Space]);
- end;
-end;
-
-function Dependency_IsX64: Boolean;
-begin
- Result := not Dependency_ForceX86 and Is64BitInstallMode;
-end;
-
-function Dependency_String(const x86, x64: String): String;
-begin
- if Dependency_IsX64 then begin
- Result := x64;
- end else begin
- Result := x86;
- end;
-end;
-
-function Dependency_ArchSuffix: String;
-begin
- Result := Dependency_String('', '_x64');
-end;
-
-function Dependency_ArchTitle: String;
-begin
- Result := Dependency_String(' (x86)', ' (x64)');
-end;
-
-function Dependency_IsNetCoreInstalled(const Version: String): Boolean;
-var
- ResultCode: Integer;
-begin
- // source code: https://github.com/dotnet/deployment-tools/tree/master/src/clickonce/native/projects/NetCoreCheck
- if not FileExists(ExpandConstant('{tmp}{\}') + 'netcorecheck' + Dependency_ArchSuffix + '.exe') then begin
- ExtractTemporaryFile('netcorecheck' + Dependency_ArchSuffix + '.exe');
- end;
- Result := ShellExec('', ExpandConstant('{tmp}{\}') + 'netcorecheck' + Dependency_ArchSuffix + '.exe', Version, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0);
-end;
-
-procedure Dependency_AddDotNet80Desktop;
-begin
- // https://dotnet.microsoft.com/en-us/download/dotnet/8.0
- if not Dependency_IsNetCoreInstalled('Microsoft.WindowsDesktop.App 8.0.0') then begin
- Dependency_Add('dotNet80desktop' + Dependency_ArchSuffix + '.exe',
- '/lcid ' + IntToStr(GetUILanguage) + ' /passive /norestart',
- '.NET Desktop Runtime 8.0.0' + Dependency_ArchTitle,
- Dependency_String('https://download.visualstudio.microsoft.com/download/pr/b280d97f-25a9-4ab7-8a12-8291aa3af117/a37ed0e68f51fcd973e9f6cb4f40b1a7/windowsdesktop-runtime-8.0.0-win-x64.exe',
- 'https://download.visualstudio.microsoft.com/download/pr/f9e3b581-059d-429f-9f0d-1d1167ff7e32/bd7661030cd5d66cd3eee0fd20b24540/windowsdesktop-runtime-8.0.0-win-x86.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2005;
-begin
- // https://www.microsoft.com/en-US/download/details.aspx?id=26347
- if not IsMsiProductInstalled(Dependency_String('{86C9D5AA-F00C-4921-B3F2-C60AF92E2844}', '{A8D19029-8E5C-4E22-8011-48070F9E796E}'), PackVersionComponents(8, 0, 61000, 0)) then begin
- Dependency_Add('vcredist2005' + Dependency_ArchSuffix + '.exe',
- '/q',
- 'Visual C++ 2005 Service Pack 1 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x86.EXE', 'https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x64.EXE'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2008;
-begin
- // https://www.microsoft.com/en-US/download/details.aspx?id=26368
- if not IsMsiProductInstalled(Dependency_String('{DE2C306F-A067-38EF-B86C-03DE4B0312F9}', '{FDA45DDF-8E17-336F-A3ED-356B7B7C688A}'), PackVersionComponents(9, 0, 30729, 6161)) then begin
- Dependency_Add('vcredist2008' + Dependency_ArchSuffix + '.exe',
- '/q',
- 'Visual C++ 2008 Service Pack 1 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe', 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x64.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2010;
-begin
- // https://www.microsoft.com/en-US/download/details.aspx?id=26999
- if not IsMsiProductInstalled(Dependency_String('{1F4F1D2A-D9DA-32CF-9909-48485DA06DD5}', '{5B75F761-BAC8-33BC-A381-464DDDD813A3}'), PackVersionComponents(10, 0, 40219, 0)) then begin
- Dependency_Add('vcredist2010' + Dependency_ArchSuffix + '.exe',
- '/passive /norestart',
- 'Visual C++ 2010 Service Pack 1 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2012;
-begin
- // https://www.microsoft.com/en-US/download/details.aspx?id=30679
- if not IsMsiProductInstalled(Dependency_String('{4121ED58-4BD9-3E7B-A8B5-9F8BAAE045B7}', '{EFA6AFA1-738E-3E00-8101-FD03B86B29D1}'), PackVersionComponents(11, 0, 61030, 0)) then begin
- Dependency_Add('vcredist2012' + Dependency_ArchSuffix + '.exe',
- '/passive /norestart',
- 'Visual C++ 2012 Update 4 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2013;
-begin
- // https://support.microsoft.com/en-US/help/4032938
- if not IsMsiProductInstalled(Dependency_String('{B59F5BF1-67C8-3802-8E59-2CE551A39FC5}', '{20400CF0-DE7C-327E-9AE4-F0F38D9085F8}'), PackVersionComponents(12, 0, 40664, 0)) then begin
- Dependency_Add('vcredist2013' + Dependency_ArchSuffix + '.exe',
- '/passive /norestart',
- 'Visual C++ 2013 Update 5 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://download.visualstudio.microsoft.com/download/pr/10912113/5da66ddebb0ad32ebd4b922fd82e8e25/vcredist_x86.exe', 'https://download.visualstudio.microsoft.com/download/pr/10912041/cee5d6bca2ddbcd039da727bf4acb48a/vcredist_x64.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddVC2015To2019;
-begin
- // https://support.microsoft.com/en-US/help/2977003/the-latest-supported-visual-c-downloads
- if not IsMsiProductInstalled(Dependency_String('{65E5BD06-6392-3027-8C26-853107D3CF1A}', '{36F68A90-239C-34DF-B58C-64B30153CE35}'), PackVersionComponents(14, 29, 30037, 0)) then begin
- Dependency_Add('vcredist2019' + Dependency_ArchSuffix + '.exe',
- '/passive /norestart',
- 'Visual C++ 2015-2019 Redistributable' + Dependency_ArchTitle,
- Dependency_String('https://aka.ms/vs/16/release/vc_redist.x86.exe', 'https://aka.ms/vs/16/release/vc_redist.x64.exe'),
- '', False, False);
- end;
-end;
-
-procedure Dependency_AddDirectX;
-begin
- // https://www.microsoft.com/en-US/download/details.aspx?id=35
- Dependency_Add('dxwebsetup.exe',
- '/q',
- 'DirectX Runtime',
- 'https://download.microsoft.com/download/1/7/1/1718CCC4-6315-4D8E-9543-8E28A4E18C4C/dxwebsetup.exe',
- '', True, False);
-end;
-
-procedure Dependency_AddHideHide;
-begin
- Dependency_Add('HidHide_1.4.192_x64.exe',
- '/quiet /norestart',
- 'HidHide Drivers',
- 'https://github.com/nefarius/HidHide/releases/download/v1.4.192.0/HidHide_1.4.192_x64.exe',
- '', True, False);
-end;
-
-procedure Dependency_AddViGem;
-begin
- Dependency_Add('ViGEmBus_1.22.0_x64_x86_arm64.exe',
- '/quiet /norestart',
- 'ViGEmBus Setup',
- 'https://github.com/nefarius/ViGEmBus/releases/download/v1.22.0/ViGEmBus_1.22.0_x64_x86_arm64.exe',
- '', True, False);
-end;
-
-procedure Dependency_AddRTSS;
-begin
- Dependency_Add('RTSSSetup735Beta5.exe',
- '/S',
- 'RTSS Setup v7.3.5 Beta5',
- 'https://github.com/Valkirie/HandheldCompanion/raw/main/redist/RTSSSetup735Beta5.exe',
- '', True, False);
-end;
-
-procedure Dependency_AddHWiNFO;
-begin
- Dependency_Add('hwi_766.exe',
- '/silent',
- 'HWiNFO v7.6.6',
- 'https://github.com/Valkirie/HandheldCompanion/raw/main/redist/hwi_766.exe',
- '', True, False);
-end;
-
-[Setup]
-; -------------
-; SETUP
-; -------------
-#ifndef Dependency_NoExampleSetup
-
-; requires netcorecheck.exe and netcorecheck_x64.exe (see download link below)
-#define UseNetCoreCheck
-#ifdef UseNetCoreCheck
- #define UseDotNet80
-#endif
-
-;#define UseVC2005
-;#define UseVC2008
-;#define UseVC2010
-;#define UseVC2012
-;#define UseVC2013
-;#define UseVC2015To2019
-
-#define UseDirectX
-; install ViGem first
-#define UseViGem
-#define UseHideHide
-#define UseRTSS
-#define UseHWiNFO
-
-#define MyAppSetupName 'Handheld Companion'
-#define MyBuildId 'HandheldCompanion'
-#define MyAppVersion '0.19.1.8'
-#define MyAppPublisher 'BenjaminLSR'
-#define MyAppCopyright 'Copyright @ BenjaminLSR'
-#define MyAppURL 'https://github.com/Valkirie/HandheldCompanion'
-#define MyAppExeName "HandheldCompanion.exe"
-#define MyConfiguration "Release"
-
-#ifdef UseDotNet80
- #define MyConfigurationExt "net8.0"
-#endif
-
-AppName={#MyAppSetupName}
-AppVersion={#MyAppVersion}
-AppVerName={#MyAppSetupName}
-AppCopyright={#MyAppCopyright}
-VersionInfoVersion={#MyAppVersion}
-VersionInfoCompany={#MyAppPublisher}
-AppPublisher={#MyAppPublisher}
-AppPublisherURL={#MyAppURL}
-AppSupportURL={#MyAppURL}
-AppUpdatesURL={#MyAppURL}
-OutputBaseFilename={#MyBuildId}-{#MyAppVersion}
-DefaultGroupName={#MyAppSetupName}
-DefaultDirName={autopf}\{#MyAppSetupName}
-UninstallDisplayIcon={app}\{#MyAppExeName}
-SetupIconFile="{#SourcePath}\HandheldCompanion\Resources\icon.ico"
-SourceDir=redist
-OutputDir={#SourcePath}\install
-AllowNoIcons=yes
-MinVersion=6.0
-;PrivilegesRequired=admin
-PrivilegesRequiredOverridesAllowed=dialog
-Compression=lzma
-SolidCompression=yes
-
-// remove next line if you only deploy 32-bit binaries and dependencies
-ArchitecturesInstallIn64BitMode=x64
-
-[Languages]
-Name: en; MessagesFile: "compiler:Default.isl"
-
-[Setup]
-AlwaysRestart = yes
-CloseApplications = yes
-
-[Files]
-#ifdef UseNetCoreCheck
-// download netcorecheck.exe: https://go.microsoft.com/fwlink/?linkid=2135256
-// download netcorecheck_x64.exe: https://go.microsoft.com/fwlink/?linkid=2135504
-Source: "netcorecheck.exe"; Flags: dontcopy noencryption
-Source: "netcorecheck_x64.exe"; Flags: dontcopy noencryption
-#endif
-
-Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\WinRing0x64.dll"; DestDir: "{app}"; Flags: onlyifdoesntexist
-Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\WinRing0x64.sys"; DestDir: "{app}"; Flags: onlyifdoesntexist
-Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\*"; Excludes: "*WinRing0x64.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
-
-Source: "{#SourcePath}\redist\SegoeIcons.ttf"; DestDir: "{autofonts}"; FontInstall: "Segoe Fluent Icons (TrueType)"; Flags: onlyifdoesntexist uninsneveruninstall
-Source: "{#SourcePath}\redist\PromptFont.otf"; DestDir: "{autofonts}"; FontInstall: "PromptFont"; Flags: uninsneveruninstall
-
-[Icons]
-Name: "{group}\{#MyAppSetupName}"; Filename: "{app}\{#MyAppExeName}"
-Name: "{group}\{cm:UninstallProgram,{#MyAppSetupName}}"; Filename: "{uninstallexe}"
-Name: "{commondesktop}\{#MyAppSetupName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
-
-[Tasks]
-Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"
-
-[UninstallRun]
-Filename: "C:\Program Files\Nefarius Software Solutions\HidHide\x64\HidHideCLI.exe"; Parameters: "--cloak-off" ; RunOnceId: "CloakOff"; Flags: runascurrentuser runhidden
-
-[UninstallDelete]
-Type: filesandordirs; Name: "{app}"
-
-[Registry]
-Root: HKLM; Subkey: "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps"; Flags: uninsdeletekeyifempty
-Root: HKLM; Subkey: "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\HandheldCompanion.exe"; ValueType: string; ValueName: "DumpFolder"; ValueData: "{userdocs}\HandheldCompanion\dumps"; Flags: uninsdeletekey
-
-[Code]
-#include "./UpdateUninstallWizard.iss"
-
-procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
-var
- resultCode:integer;
-begin
- if CurUninstallStep = usUninstall then
- begin
- if not(checkListBox.checked[keepAllCheck]) then
- begin
- if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\profiles')) then
- DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\profiles'), True, True, True);
- if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys')) then
- DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys'), True, True, True);
- DelTree(ExpandConstant('{localappdata}\HandheldCompanion'), True, True, True);
- exit;
- end
- else
- begin
- if not(checkListBox.checked[profilesCheck]) then
- begin
- if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\profiles')) then
- DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\profiles'), True, True, True);
- end;
-
- if not(checkListBox.checked[hotkeysCheck]) then
- begin
- if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys')) then
- DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys'), True, True, True);
- end;
-
- if not(checkListBox.checked[applicationSettingsCheck]) then
- begin
- DelTree(ExpandConstant('{localappdata}\HandheldCompanion'), True, True, True);
- end;
- end;
-
- if not(keepHidhideCheckbox.Checked) then
- begin
- if(ShellExec('', 'msiexec.exe', '/X{BE49B9DE-F8EB-4F54-B312-DD4B601985FC}', '', SW_SHOW, ewWaitUntilTerminated, resultCode)) then
- begin
- log('Successfully executed Hidhide uninstaller');
- if(resultCode = 0) then
- log('Hidhide uninstaller finished successfully')
- else
- log('Hidhide uninstaller failed with exit code ' +intToStr(resultCode));
- end
- else
- begin
- log('Failed to execute Hidhide uninstaller');
- end;
- end;
-
- if not(keepVigemCheckbox.Checked) then
- begin
- if(ShellExec('', 'msiexec.exe', '/X{966606F3-2745-49E9-BF15-5C3EAA4E9077}', '', SW_SHOW, ewWaitUntilTerminated, resultCode)) then
- begin
- log('Successfully executed Vigem uninstaller');
- if(resultCode = 0) then
- log('Vigem uninstaller finished successfully')
- else
- log('Vigem uninstaller failed with exit code ' +intToStr(resultCode));
- end
- else
- begin
- log('Failed to execute Vigem uninstaller');
- end;
- end;
- end;
-end;
-
-
-procedure InitializeWizard;
-begin
- Dependency_InitializeWizard;
-end;
-
-function PrepareToInstall(var NeedsRestart: Boolean): String;
-begin
- Result := Dependency_PrepareToInstall(NeedsRestart);
-end;
-
-function NeedRestart: Boolean;
-begin
- Result := Dependency_NeedRestart;
-end;
-
-function UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
-begin
- Result := Dependency_UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo);
-end;
-
-function InitializeSetup: Boolean;
-begin
-
-#ifdef UseDotNet80
- Dependency_AddDotNet80Desktop;
-#endif
-
-#ifdef UseVC2005
- Dependency_AddVC2005;
-#endif
-#ifdef UseVC2008
- Dependency_AddVC2008;
-#endif
-#ifdef UseVC2010
- Dependency_AddVC2010;
-#endif
-#ifdef UseVC2012
- Dependency_AddVC2012;
-#endif
-#ifdef UseVC2013
- Dependency_AddVC2013;
-#endif
-#ifdef UseVC2015To2019
- Dependency_AddVC2015To2019;
-#endif
-
-#ifdef UseDirectX
- Dependency_AddDirectX;
-#endif
-
-#ifdef UseHideHide
- Dependency_AddHideHide;
-#endif
-
-#ifdef UseViGem
- Dependency_AddViGem;
-#endif
-
-#ifdef UseRTSS
- Dependency_AddRTSS;
-#endif
-
-#ifdef UseHWiNFO
- Dependency_AddHWiNFO;
-#endif
-
- Result := True;
-end;
-
-#endif
+; -----------
+; CODE
+; -----------
+[Code]
+// types and variables
+type
+ TDependency_Entry = record
+ Filename: String;
+ Parameters: String;
+ Title: String;
+ URL: String;
+ Checksum: String;
+ ForceSuccess: Boolean;
+ RestartAfter: Boolean;
+ end;
+
+var
+ Dependency_Memo: String;
+ Dependency_List: array of TDependency_Entry;
+ Dependency_NeedRestart, Dependency_ForceX86: Boolean;
+ Dependency_DownloadPage: TDownloadWizardPage;
+
+procedure Dependency_Add(const Filename, Parameters, Title, URL, Checksum: String; const ForceSuccess, RestartAfter: Boolean);
+var
+ Dependency: TDependency_Entry;
+ DependencyCount: Integer;
+begin
+ Dependency_Memo := Dependency_Memo + #13#10 + '%1' + Title;
+
+ Dependency.Filename := Filename;
+ Dependency.Parameters := Parameters;
+ Dependency.Title := Title;
+
+ if FileExists(ExpandConstant('{tmp}{\}') + Filename) then begin
+ Dependency.URL := '';
+ end else begin
+ Dependency.URL := URL;
+ end;
+
+ Dependency.Checksum := Checksum;
+ Dependency.ForceSuccess := ForceSuccess;
+ Dependency.RestartAfter := RestartAfter;
+
+ DependencyCount := GetArrayLength(Dependency_List);
+ SetArrayLength(Dependency_List, DependencyCount + 1);
+ Dependency_List[DependencyCount] := Dependency;
+end;
+
+procedure Dependency_InitializeWizard;
+begin
+ Dependency_DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), nil);
+end;
+
+function Dependency_PrepareToInstall(var NeedsRestart: Boolean): String;
+var
+ DependencyCount, DependencyIndex, ResultCode: Integer;
+ Retry: Boolean;
+ TempValue: String;
+begin
+ DependencyCount := GetArrayLength(Dependency_List);
+
+ if DependencyCount > 0 then begin
+ Dependency_DownloadPage.Show;
+
+ for DependencyIndex := 0 to DependencyCount - 1 do begin
+ if Dependency_List[DependencyIndex].URL <> '' then begin
+ Dependency_DownloadPage.Clear;
+ Dependency_DownloadPage.Add(Dependency_List[DependencyIndex].URL, Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Checksum);
+
+ Retry := True;
+ while Retry do begin
+ Retry := False;
+
+ try
+ Dependency_DownloadPage.Download;
+ except
+ if Dependency_DownloadPage.AbortedByUser then begin
+ Result := Dependency_List[DependencyIndex].Title;
+ DependencyIndex := DependencyCount;
+ end else begin
+ case SuppressibleMsgBox(AddPeriod(GetExceptionMessage), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
+ IDABORT: begin
+ Result := Dependency_List[DependencyIndex].Title;
+ DependencyIndex := DependencyCount;
+ end;
+ IDRETRY: begin
+ Retry := True;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+ end;
+
+ if Result = '' then begin
+ for DependencyIndex := 0 to DependencyCount - 1 do begin
+ Dependency_DownloadPage.SetText(Dependency_List[DependencyIndex].Title, '');
+ Dependency_DownloadPage.SetProgress(DependencyIndex + 1, DependencyCount + 1);
+
+ while True do begin
+ ResultCode := 0;
+ if ShellExec('', ExpandConstant('{tmp}{\}') + Dependency_List[DependencyIndex].Filename, Dependency_List[DependencyIndex].Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode) then begin
+ if Dependency_List[DependencyIndex].RestartAfter then begin
+ if DependencyIndex = DependencyCount - 1 then begin
+ Dependency_NeedRestart := True;
+ end else begin
+ NeedsRestart := True;
+ Result := Dependency_List[DependencyIndex].Title;
+ end;
+ break;
+ end else if (ResultCode = 0) or Dependency_List[DependencyIndex].ForceSuccess then begin // ERROR_SUCCESS (0)
+ break;
+ end else if ResultCode = 1641 then begin // ERROR_SUCCESS_REBOOT_INITIATED (1641)
+ NeedsRestart := True;
+ Result := Dependency_List[DependencyIndex].Title;
+ break;
+ end else if ResultCode = 3010 then begin // ERROR_SUCCESS_REBOOT_REQUIRED (3010)
+ Dependency_NeedRestart := True;
+ break;
+ end;
+ end;
+
+ case SuppressibleMsgBox(FmtMessage(SetupMessage(msgErrorFunctionFailed), [Dependency_List[DependencyIndex].Title, IntToStr(ResultCode)]), mbError, MB_ABORTRETRYIGNORE, IDIGNORE) of
+ IDABORT: begin
+ Result := Dependency_List[DependencyIndex].Title;
+ break;
+ end;
+ IDIGNORE: begin
+ break;
+ end;
+ end;
+ end;
+
+ if Result <> '' then begin
+ break;
+ end;
+ end;
+
+ if NeedsRestart then begin
+ TempValue := '"' + ExpandConstant('{srcexe}') + '" /restart=1 /LANG="' + ExpandConstant('{language}') + '" /DIR="' + WizardDirValue + '" /GROUP="' + WizardGroupValue + '" /TYPE="' + WizardSetupType(False) + '" /COMPONENTS="' + WizardSelectedComponents(False) + '" /TASKS="' + WizardSelectedTasks(False) + '"';
+ if WizardNoIcons then begin
+ TempValue := TempValue + ' /NOICONS';
+ end;
+ RegWriteStringValue(HKA, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', '{#SetupSetting("AppName")}', TempValue);
+ end;
+ end;
+
+ Dependency_DownloadPage.Hide;
+ end;
+end;
+
+function Dependency_UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
+begin
+ Result := '';
+ if MemoUserInfoInfo <> '' then begin
+ Result := Result + MemoUserInfoInfo + Newline + NewLine;
+ end;
+ if MemoDirInfo <> '' then begin
+ Result := Result + MemoDirInfo + Newline + NewLine;
+ end;
+ if MemoTypeInfo <> '' then begin
+ Result := Result + MemoTypeInfo + Newline + NewLine;
+ end;
+ if MemoComponentsInfo <> '' then begin
+ Result := Result + MemoComponentsInfo + Newline + NewLine;
+ end;
+ if MemoGroupInfo <> '' then begin
+ Result := Result + MemoGroupInfo + Newline + NewLine;
+ end;
+ if MemoTasksInfo <> '' then begin
+ Result := Result + MemoTasksInfo;
+ end;
+
+ if Dependency_Memo <> '' then begin
+ if MemoTasksInfo = '' then begin
+ Result := Result + SetupMessage(msgReadyMemoTasks);
+ end;
+ Result := Result + FmtMessage(Dependency_Memo, [Space]);
+ end;
+end;
+
+function Dependency_IsX64: Boolean;
+begin
+ Result := not Dependency_ForceX86 and Is64BitInstallMode;
+end;
+
+function Dependency_String(const x86, x64: String): String;
+begin
+ if Dependency_IsX64 then begin
+ Result := x64;
+ end else begin
+ Result := x86;
+ end;
+end;
+
+function Dependency_ArchSuffix: String;
+begin
+ Result := Dependency_String('', '_x64');
+end;
+
+function Dependency_ArchTitle: String;
+begin
+ Result := Dependency_String(' (x86)', ' (x64)');
+end;
+
+function Dependency_IsNetCoreInstalled(const Version: String): Boolean;
+var
+ ResultCode: Integer;
+begin
+ // source code: https://github.com/dotnet/deployment-tools/tree/master/src/clickonce/native/projects/NetCoreCheck
+ if not FileExists(ExpandConstant('{tmp}{\}') + 'netcorecheck' + Dependency_ArchSuffix + '.exe') then begin
+ ExtractTemporaryFile('netcorecheck' + Dependency_ArchSuffix + '.exe');
+ end;
+ Result := ShellExec('', ExpandConstant('{tmp}{\}') + 'netcorecheck' + Dependency_ArchSuffix + '.exe', Version, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and (ResultCode = 0);
+end;
+
+procedure Dependency_AddDotNet80Desktop;
+begin
+ // https://dotnet.microsoft.com/en-us/download/dotnet/8.0
+ if not Dependency_IsNetCoreInstalled('Microsoft.WindowsDesktop.App 8.0.0') then begin
+ Dependency_Add('dotNet80desktop' + Dependency_ArchSuffix + '.exe',
+ '/lcid ' + IntToStr(GetUILanguage) + ' /passive /norestart',
+ '.NET Desktop Runtime 8.0.0' + Dependency_ArchTitle,
+ Dependency_String('https://download.visualstudio.microsoft.com/download/pr/b280d97f-25a9-4ab7-8a12-8291aa3af117/a37ed0e68f51fcd973e9f6cb4f40b1a7/windowsdesktop-runtime-8.0.0-win-x64.exe',
+ 'https://download.visualstudio.microsoft.com/download/pr/f9e3b581-059d-429f-9f0d-1d1167ff7e32/bd7661030cd5d66cd3eee0fd20b24540/windowsdesktop-runtime-8.0.0-win-x86.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2005;
+begin
+ // https://www.microsoft.com/en-US/download/details.aspx?id=26347
+ if not IsMsiProductInstalled(Dependency_String('{86C9D5AA-F00C-4921-B3F2-C60AF92E2844}', '{A8D19029-8E5C-4E22-8011-48070F9E796E}'), PackVersionComponents(8, 0, 61000, 0)) then begin
+ Dependency_Add('vcredist2005' + Dependency_ArchSuffix + '.exe',
+ '/q',
+ 'Visual C++ 2005 Service Pack 1 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x86.EXE', 'https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x64.EXE'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2008;
+begin
+ // https://www.microsoft.com/en-US/download/details.aspx?id=26368
+ if not IsMsiProductInstalled(Dependency_String('{DE2C306F-A067-38EF-B86C-03DE4B0312F9}', '{FDA45DDF-8E17-336F-A3ED-356B7B7C688A}'), PackVersionComponents(9, 0, 30729, 6161)) then begin
+ Dependency_Add('vcredist2008' + Dependency_ArchSuffix + '.exe',
+ '/q',
+ 'Visual C++ 2008 Service Pack 1 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x86.exe', 'https://download.microsoft.com/download/5/D/8/5D8C65CB-C849-4025-8E95-C3966CAFD8AE/vcredist_x64.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2010;
+begin
+ // https://www.microsoft.com/en-US/download/details.aspx?id=26999
+ if not IsMsiProductInstalled(Dependency_String('{1F4F1D2A-D9DA-32CF-9909-48485DA06DD5}', '{5B75F761-BAC8-33BC-A381-464DDDD813A3}'), PackVersionComponents(10, 0, 40219, 0)) then begin
+ Dependency_Add('vcredist2010' + Dependency_ArchSuffix + '.exe',
+ '/passive /norestart',
+ 'Visual C++ 2010 Service Pack 1 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x86.exe', 'https://download.microsoft.com/download/1/6/5/165255E7-1014-4D0A-B094-B6A430A6BFFC/vcredist_x64.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2012;
+begin
+ // https://www.microsoft.com/en-US/download/details.aspx?id=30679
+ if not IsMsiProductInstalled(Dependency_String('{4121ED58-4BD9-3E7B-A8B5-9F8BAAE045B7}', '{EFA6AFA1-738E-3E00-8101-FD03B86B29D1}'), PackVersionComponents(11, 0, 61030, 0)) then begin
+ Dependency_Add('vcredist2012' + Dependency_ArchSuffix + '.exe',
+ '/passive /norestart',
+ 'Visual C++ 2012 Update 4 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x86.exe', 'https://download.microsoft.com/download/1/6/B/16B06F60-3B20-4FF2-B699-5E9B7962F9AE/VSU_4/vcredist_x64.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2013;
+begin
+ // https://support.microsoft.com/en-US/help/4032938
+ if not IsMsiProductInstalled(Dependency_String('{B59F5BF1-67C8-3802-8E59-2CE551A39FC5}', '{20400CF0-DE7C-327E-9AE4-F0F38D9085F8}'), PackVersionComponents(12, 0, 40664, 0)) then begin
+ Dependency_Add('vcredist2013' + Dependency_ArchSuffix + '.exe',
+ '/passive /norestart',
+ 'Visual C++ 2013 Update 5 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://download.visualstudio.microsoft.com/download/pr/10912113/5da66ddebb0ad32ebd4b922fd82e8e25/vcredist_x86.exe', 'https://download.visualstudio.microsoft.com/download/pr/10912041/cee5d6bca2ddbcd039da727bf4acb48a/vcredist_x64.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddVC2015To2019;
+begin
+ // https://support.microsoft.com/en-US/help/2977003/the-latest-supported-visual-c-downloads
+ if not IsMsiProductInstalled(Dependency_String('{65E5BD06-6392-3027-8C26-853107D3CF1A}', '{36F68A90-239C-34DF-B58C-64B30153CE35}'), PackVersionComponents(14, 29, 30037, 0)) then begin
+ Dependency_Add('vcredist2019' + Dependency_ArchSuffix + '.exe',
+ '/passive /norestart',
+ 'Visual C++ 2015-2019 Redistributable' + Dependency_ArchTitle,
+ Dependency_String('https://aka.ms/vs/16/release/vc_redist.x86.exe', 'https://aka.ms/vs/16/release/vc_redist.x64.exe'),
+ '', False, False);
+ end;
+end;
+
+procedure Dependency_AddDirectX;
+begin
+ // https://www.microsoft.com/en-US/download/details.aspx?id=35
+ Dependency_Add('dxwebsetup.exe',
+ '/q',
+ 'DirectX Runtime',
+ 'https://download.microsoft.com/download/1/7/1/1718CCC4-6315-4D8E-9543-8E28A4E18C4C/dxwebsetup.exe',
+ '', True, False);
+end;
+
+procedure Dependency_AddHideHide;
+begin
+ Dependency_Add('HidHide_1.4.192_x64.exe',
+ '/quiet /norestart',
+ 'HidHide Drivers',
+ 'https://github.com/nefarius/HidHide/releases/download/v1.4.192.0/HidHide_1.4.192_x64.exe',
+ '', True, False);
+end;
+
+procedure Dependency_AddViGem;
+begin
+ Dependency_Add('ViGEmBus_1.22.0_x64_x86_arm64.exe',
+ '/quiet /norestart',
+ 'ViGEmBus Setup',
+ 'https://github.com/nefarius/ViGEmBus/releases/download/v1.22.0/ViGEmBus_1.22.0_x64_x86_arm64.exe',
+ '', True, False);
+end;
+
+procedure Dependency_AddRTSS;
+begin
+ Dependency_Add('RTSSSetup735Beta5.exe',
+ '/S',
+ 'RTSS Setup v7.3.5 Beta5',
+ 'https://github.com/Valkirie/HandheldCompanion/raw/main/redist/RTSSSetup735Beta5.exe',
+ '', True, False);
+end;
+
+[Setup]
+; -------------
+; SETUP
+; -------------
+#ifndef Dependency_NoExampleSetup
+
+; requires netcorecheck.exe and netcorecheck_x64.exe (see download link below)
+#define UseNetCoreCheck
+#ifdef UseNetCoreCheck
+ #define UseDotNet80
+#endif
+
+;#define UseVC2005
+;#define UseVC2008
+;#define UseVC2010
+;#define UseVC2012
+;#define UseVC2013
+;#define UseVC2015To2019
+
+#define UseDirectX
+; install ViGem first
+#define UseViGem
+#define UseHideHide
+#define UseRTSS
+
+#define MyAppSetupName 'Handheld Companion'
+#define MyBuildId 'HandheldCompanion'
+#define MyAppVersion '0.20.3.0'
+#define MyAppPublisher 'BenjaminLSR'
+#define MyAppCopyright 'Copyright @ BenjaminLSR'
+#define MyAppURL 'https://github.com/Valkirie/HandheldCompanion'
+#define MyAppExeName "HandheldCompanion.exe"
+#define MyConfiguration "Release"
+
+#ifdef UseDotNet80
+ #define MyConfigurationExt "net8.0"
+#endif
+
+AppName={#MyAppSetupName}
+AppVersion={#MyAppVersion}
+AppVerName={#MyAppSetupName}
+AppCopyright={#MyAppCopyright}
+VersionInfoVersion={#MyAppVersion}
+VersionInfoCompany={#MyAppPublisher}
+AppPublisher={#MyAppPublisher}
+AppPublisherURL={#MyAppURL}
+AppSupportURL={#MyAppURL}
+AppUpdatesURL={#MyAppURL}
+OutputBaseFilename={#MyBuildId}-{#MyAppVersion}
+DefaultGroupName={#MyAppSetupName}
+DefaultDirName={autopf}\{#MyAppSetupName}
+UninstallDisplayIcon={app}\{#MyAppExeName}
+SetupIconFile="{#SourcePath}\HandheldCompanion\Resources\icon.ico"
+SourceDir=redist
+OutputDir={#SourcePath}\install
+AllowNoIcons=yes
+MinVersion=6.0
+;PrivilegesRequired=admin
+PrivilegesRequiredOverridesAllowed=dialog
+Compression=lzma
+SolidCompression=yes
+
+// remove next line if you only deploy 32-bit binaries and dependencies
+ArchitecturesInstallIn64BitMode=x64
+
+[Languages]
+Name: en; MessagesFile: "compiler:Default.isl"
+
+[Setup]
+AlwaysRestart = yes
+CloseApplications = yes
+
+[Files]
+#ifdef UseNetCoreCheck
+// download netcorecheck.exe: https://go.microsoft.com/fwlink/?linkid=2135256
+// download netcorecheck_x64.exe: https://go.microsoft.com/fwlink/?linkid=2135504
+Source: "netcorecheck.exe"; Flags: dontcopy noencryption
+Source: "netcorecheck_x64.exe"; Flags: dontcopy noencryption
+#endif
+
+Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\WinRing0x64.dll"; DestDir: "{app}"; Flags: onlyifdoesntexist
+Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\WinRing0x64.sys"; DestDir: "{app}"; Flags: onlyifdoesntexist
+Source: "{#SourcePath}\bin\{#MyConfiguration}\{#MyConfigurationExt}-windows10.0.19041.0\*"; Excludes: "*WinRing0x64.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+Source: "{#SourcePath}\redist\SegoeIcons.ttf"; DestDir: "{autofonts}"; FontInstall: "Segoe Fluent Icons (TrueType)"; Flags: onlyifdoesntexist uninsneveruninstall
+Source: "{#SourcePath}\redist\PromptFont.otf"; DestDir: "{autofonts}"; FontInstall: "PromptFont"; Flags: uninsneveruninstall
+
+[Icons]
+Name: "{group}\{#MyAppSetupName}"; Filename: "{app}\{#MyAppExeName}"
+Name: "{group}\{cm:UninstallProgram,{#MyAppSetupName}}"; Filename: "{uninstallexe}"
+Name: "{commondesktop}\{#MyAppSetupName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"
+
+[UninstallRun]
+Filename: "C:\Program Files\Nefarius Software Solutions\HidHide\x64\HidHideCLI.exe"; Parameters: "--cloak-off" ; RunOnceId: "CloakOff"; Flags: runascurrentuser runhidden
+
+[UninstallDelete]
+Type: filesandordirs; Name: "{app}"
+
+[Registry]
+Root: HKLM; Subkey: "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps"; Flags: uninsdeletekeyifempty
+Root: HKLM; Subkey: "Software\Microsoft\Windows\Windows Error Reporting\LocalDumps\HandheldCompanion.exe"; ValueType: string; ValueName: "DumpFolder"; ValueData: "{userdocs}\HandheldCompanion\dumps"; Flags: uninsdeletekey
+
+[Code]
+#include "./UpdateUninstallWizard.iss"
+
+procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
+var
+ resultCode:integer;
+begin
+ if CurUninstallStep = usUninstall then
+ begin
+ if not(checkListBox.checked[keepAllCheck]) then
+ begin
+ if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\profiles')) then
+ DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\profiles'), True, True, True);
+ if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys')) then
+ DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys'), True, True, True);
+ DelTree(ExpandConstant('{localappdata}\HandheldCompanion'), True, True, True);
+ exit;
+ end
+ else
+ begin
+ if not(checkListBox.checked[profilesCheck]) then
+ begin
+ if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\profiles')) then
+ DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\profiles'), True, True, True);
+ end;
+
+ if not(checkListBox.checked[hotkeysCheck]) then
+ begin
+ if DirExists(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys')) then
+ DelTree(ExpandConstant('{userdocs}\{#MyBuildId}\hotkeys'), True, True, True);
+ end;
+
+ if not(checkListBox.checked[applicationSettingsCheck]) then
+ begin
+ DelTree(ExpandConstant('{localappdata}\HandheldCompanion'), True, True, True);
+ end;
+ end;
+
+ if not(keepHidhideCheckbox.Checked) then
+ begin
+ if(ShellExec('', 'msiexec.exe', '/X{BE49B9DE-F8EB-4F54-B312-DD4B601985FC}', '', SW_SHOW, ewWaitUntilTerminated, resultCode)) then
+ begin
+ log('Successfully executed Hidhide uninstaller');
+ if(resultCode = 0) then
+ log('Hidhide uninstaller finished successfully')
+ else
+ log('Hidhide uninstaller failed with exit code ' +intToStr(resultCode));
+ end
+ else
+ begin
+ log('Failed to execute Hidhide uninstaller');
+ end;
+ end;
+
+ if not(keepVigemCheckbox.Checked) then
+ begin
+ if(ShellExec('', 'msiexec.exe', '/X{966606F3-2745-49E9-BF15-5C3EAA4E9077}', '', SW_SHOW, ewWaitUntilTerminated, resultCode)) then
+ begin
+ log('Successfully executed Vigem uninstaller');
+ if(resultCode = 0) then
+ log('Vigem uninstaller finished successfully')
+ else
+ log('Vigem uninstaller failed with exit code ' +intToStr(resultCode));
+ end
+ else
+ begin
+ log('Failed to execute Vigem uninstaller');
+ end;
+ end;
+ end;
+end;
+
+
+procedure InitializeWizard;
+begin
+ Dependency_InitializeWizard;
+end;
+
+function PrepareToInstall(var NeedsRestart: Boolean): String;
+begin
+ Result := Dependency_PrepareToInstall(NeedsRestart);
+end;
+
+function NeedRestart: Boolean;
+begin
+ Result := Dependency_NeedRestart;
+end;
+
+function UpdateReadyMemo(const Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
+begin
+ Result := Dependency_UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo);
+end;
+
+function InitializeSetup: Boolean;
+begin
+
+#ifdef UseDotNet80
+ Dependency_AddDotNet80Desktop;
+#endif
+
+#ifdef UseVC2005
+ Dependency_AddVC2005;
+#endif
+#ifdef UseVC2008
+ Dependency_AddVC2008;
+#endif
+#ifdef UseVC2010
+ Dependency_AddVC2010;
+#endif
+#ifdef UseVC2012
+ Dependency_AddVC2012;
+#endif
+#ifdef UseVC2013
+ Dependency_AddVC2013;
+#endif
+#ifdef UseVC2015To2019
+ Dependency_AddVC2015To2019;
+#endif
+
+#ifdef UseDirectX
+ Dependency_AddDirectX;
+#endif
+
+#ifdef UseHideHide
+ Dependency_AddHideHide;
+#endif
+
+#ifdef UseViGem
+ Dependency_AddViGem;
+#endif
+
+#ifdef UseRTSS
+ Dependency_AddRTSS;
+#endif
+
+ Result := True;
+end;
+
+#endif
\ No newline at end of file
diff --git a/HandheldCompanion/ADLX_3DSettings.dll b/HandheldCompanion/ADLX_3DSettings.dll
new file mode 100644
index 000000000..7cdeefa6f
Binary files /dev/null and b/HandheldCompanion/ADLX_3DSettings.dll differ
diff --git a/HandheldCompanion/ADLX_DisplaySettings.dll b/HandheldCompanion/ADLX_DisplaySettings.dll
new file mode 100644
index 000000000..dc8b70eae
Binary files /dev/null and b/HandheldCompanion/ADLX_DisplaySettings.dll differ
diff --git a/HandheldCompanion/Actions/AxisActions.cs b/HandheldCompanion/Actions/AxisActions.cs
index 40ec13ae4..bd5e31c1a 100644
--- a/HandheldCompanion/Actions/AxisActions.cs
+++ b/HandheldCompanion/Actions/AxisActions.cs
@@ -21,7 +21,7 @@ public class AxisActions : GyroActions
public AxisActions()
{
- this.ActionType = ActionType.Joystick;
+ this.actionType = ActionType.Joystick;
this.Value = new Vector2();
}
diff --git a/HandheldCompanion/Actions/ButtonActions.cs b/HandheldCompanion/Actions/ButtonActions.cs
index 5e56ea707..2b95662ac 100644
--- a/HandheldCompanion/Actions/ButtonActions.cs
+++ b/HandheldCompanion/Actions/ButtonActions.cs
@@ -13,7 +13,7 @@ public class ButtonActions : IActions
public ButtonActions()
{
- this.ActionType = ActionType.Button;
+ this.actionType = ActionType.Button;
this.Value = false;
this.prevValue = false;
diff --git a/HandheldCompanion/Actions/IActions.cs b/HandheldCompanion/Actions/IActions.cs
index 98e03a224..ab25b1683 100644
--- a/HandheldCompanion/Actions/IActions.cs
+++ b/HandheldCompanion/Actions/IActions.cs
@@ -19,6 +19,17 @@ public enum ActionType
Special = 6,
}
+ [Serializable]
+ public enum ActionState
+ {
+ Stopped = 0,
+ Running = 1,
+ Aborted = 2,
+ Succeed = 3,
+ Suspended = 4,
+ Forced = 5,
+ }
+
[Serializable]
public enum ModifierSet
{
@@ -36,7 +47,9 @@ public enum ModifierSet
public enum PressType
{
Short = 0,
- Long = 1,
+ Long = 1, // hold for x ms and get an action
+ Hold = 2, // press and hold the command for x ms
+ Double = 3,
}
[Serializable]
@@ -71,15 +84,17 @@ public abstract class IActions : ICloneable
{ ModifierSet.ShiftControlAlt, new KeyCode[] { KeyCode.LShift, KeyCode.LControl, KeyCode.LMenu } },
};
- public ActionType ActionType = ActionType.Disabled;
+ public ActionType actionType = ActionType.Disabled;
+ public PressType pressType = PressType.Short;
+ public ActionState actionState = ActionState.Stopped;
protected object Value;
protected object prevValue;
- // TODO: multiple delay, delay ranges
- public PressType PressType = PressType.Short;
- public int LongPressTime = 450; // default value for steam
- protected int pressTimer = -1; // -1 inactive, >= 0 active
+ public int ActionTimer = 200; // default value for steam
+ public int pressTimer = -1; // -1 inactive, >= 0 active
+
+ private int pressCount = 0; // used to store previous press value for double tap
public bool Turbo;
public int TurboDelay = 30;
@@ -89,6 +104,8 @@ public abstract class IActions : ICloneable
public bool Toggle;
protected bool IsToggled;
+ public bool Interruptable = true;
+
public HapticMode HapticMode = HapticMode.Off;
public HapticStrength HapticStrength = HapticStrength.Low;
@@ -110,21 +127,203 @@ public virtual void SetHaptic(ButtonFlags button, bool up)
public virtual void Execute(ButtonFlags button, bool value)
{
- switch(PressType)
+ if (actionState == ActionState.Suspended)
+ {
+ // bypass output
+ this.Value = false;
+ this.prevValue = value;
+ return;
+ }
+ else if (actionState == ActionState.Forced)
+ {
+ // bypass output
+ value = true;
+ }
+
+ switch (pressType)
{
case PressType.Long:
{
- if (value || (pressTimer <= LongPressTime && pressTimer >= 0))
+ if (value)
+ {
+ // update state
+ actionState = ActionState.Running;
+
+ // update timer
+ pressTimer += TimerManager.GetPeriod();
+
+ if (pressTimer >= ActionTimer)
+ {
+ // update state
+ actionState = ActionState.Succeed;
+ }
+ else
+ {
+ // bypass output
+ this.Value = false;
+ this.prevValue = value;
+ return;
+ }
+ }
+ else
+ {
+ // key was released too early
+ if (actionState == ActionState.Running)
+ {
+ // update state
+ actionState = ActionState.Aborted;
+
+ // update timer
+ pressTimer = Math.Max(50, pressTimer);
+ }
+ else if (actionState == ActionState.Succeed)
+ {
+ // update state
+ actionState = ActionState.Stopped;
+
+ // update timer
+ pressTimer = -1;
+ }
+ else if (actionState == ActionState.Stopped)
+ {
+ // update timer
+ pressTimer = -1;
+ }
+
+ if (actionState == ActionState.Aborted)
+ {
+ // set to aborted for a time equal to the actions was "running"
+ if (pressTimer >= 0)
+ {
+ // update state
+ actionState = ActionState.Aborted;
+
+ // update timer
+ pressTimer -= TimerManager.GetPeriod();
+ }
+ else
+ {
+ // update state
+ actionState = ActionState.Stopped;
+
+ // update timer
+ pressTimer = -1;
+ }
+ }
+ }
+ }
+ break;
+
+ case PressType.Hold:
+ {
+ if (value || (pressTimer <= ActionTimer && pressTimer >= 0))
{
+ // update state
+ actionState = ActionState.Running;
+
+ // update timer
pressTimer += TimerManager.GetPeriod();
+
+ // bypass output (simple)
value = true;
}
- else if(pressTimer >= LongPressTime)
+ else if (pressTimer >= ActionTimer)
{
+ // update state
+ actionState = ActionState.Stopped;
+
+ // reset var(s)
pressTimer = -1;
}
}
break;
+
+ case PressType.Double:
+ {
+ if (value)
+ {
+ // increase press count
+ if ((bool)prevValue != value)
+ pressCount++;
+ }
+
+ switch (pressCount)
+ {
+ default:
+ {
+ if (actionState != ActionState.Stopped)
+ {
+ // update timer
+ pressTimer += TimerManager.GetPeriod();
+
+ if (pressTimer >= 50)
+ {
+ // update state
+ actionState = ActionState.Stopped;
+
+ // reset var(s)
+ pressCount = 0;
+ pressTimer = 0;
+ }
+ }
+
+ // bypass output
+ this.Value = false;
+ this.prevValue = value;
+ return;
+ }
+
+ case 1:
+ {
+ // update state
+ actionState = ActionState.Running;
+
+ // update timer
+ pressTimer += TimerManager.GetPeriod();
+
+ // too slow to press again ?
+ if (pressTimer > ActionTimer)
+ {
+ // update state
+ actionState = ActionState.Aborted;
+
+ // reset var(s)
+ pressCount = 0;
+ pressTimer = 0;
+ }
+
+ // bypass output
+ this.Value = false;
+ this.prevValue = value;
+ return;
+ }
+
+ case 2:
+ {
+ // on time
+ if (pressTimer <= ActionTimer && value)
+ {
+ // update state
+ actionState = ActionState.Succeed;
+
+ // reset var(s)
+ pressCount = 2;
+ pressTimer = ActionTimer;
+ }
+ else
+ {
+ // update state
+ actionState = ActionState.Stopped;
+
+ // reset var(s)
+ pressCount = 0;
+ pressTimer = 0;
+ }
+ }
+ break;
+ }
+ }
+ break;
}
if (Toggle)
diff --git a/HandheldCompanion/Actions/KeyboardActions.cs b/HandheldCompanion/Actions/KeyboardActions.cs
index d58a37739..6f1c488af 100644
--- a/HandheldCompanion/Actions/KeyboardActions.cs
+++ b/HandheldCompanion/Actions/KeyboardActions.cs
@@ -20,7 +20,7 @@ public class KeyboardActions : IActions
public KeyboardActions()
{
- this.ActionType = ActionType.Keyboard;
+ this.actionType = ActionType.Keyboard;
this.Value = false;
this.prevValue = false;
diff --git a/HandheldCompanion/Actions/MouseActions.cs b/HandheldCompanion/Actions/MouseActions.cs
index fdc4941be..97fdc8c00 100644
--- a/HandheldCompanion/Actions/MouseActions.cs
+++ b/HandheldCompanion/Actions/MouseActions.cs
@@ -59,7 +59,7 @@ public class MouseActions : GyroActions
public MouseActions()
{
- this.ActionType = ActionType.Mouse;
+ this.actionType = ActionType.Mouse;
this.Value = false;
this.prevValue = false;
diff --git a/HandheldCompanion/Actions/SpecialActions.cs b/HandheldCompanion/Actions/SpecialActions.cs
index e71040516..5845e0194 100644
--- a/HandheldCompanion/Actions/SpecialActions.cs
+++ b/HandheldCompanion/Actions/SpecialActions.cs
@@ -32,7 +32,7 @@ public class SpecialActions : IActions
public SpecialActions()
{
- this.ActionType = ActionType.Special;
+ this.actionType = ActionType.Special;
}
public SpecialActions(SpecialActionsType type) : this()
diff --git a/HandheldCompanion/Actions/TriggerActions.cs b/HandheldCompanion/Actions/TriggerActions.cs
index 5aa394b9c..e18661611 100644
--- a/HandheldCompanion/Actions/TriggerActions.cs
+++ b/HandheldCompanion/Actions/TriggerActions.cs
@@ -16,7 +16,7 @@ public class TriggerActions : IActions
public TriggerActions()
{
- this.ActionType = ActionType.Trigger;
+ this.actionType = ActionType.Trigger;
this.Value = (short)0;
}
diff --git a/HandheldCompanion/App.config b/HandheldCompanion/App.config
index bf7669c66..a3ffdcfcf 100644
--- a/HandheldCompanion/App.config
+++ b/HandheldCompanion/App.config
@@ -185,9 +185,6 @@
True
-
- True
-
3
@@ -227,6 +224,9 @@
False
+
+ False
+
0
@@ -245,6 +245,12 @@
False
+
+ False
+
+
+ 2
+
\ No newline at end of file
diff --git a/HandheldCompanion/App.xaml b/HandheldCompanion/App.xaml
index 0f61123f6..e41d783e8 100644
--- a/HandheldCompanion/App.xaml
+++ b/HandheldCompanion/App.xaml
@@ -68,6 +68,10 @@
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Controllers/DS4Controller.cs b/HandheldCompanion/Controllers/DS4Controller.cs
index 7028dc7b5..a081322cf 100644
--- a/HandheldCompanion/Controllers/DS4Controller.cs
+++ b/HandheldCompanion/Controllers/DS4Controller.cs
@@ -112,11 +112,6 @@ public override void SetLightColor(byte R, byte G, byte B)
});
}
- public override void Cleanup()
- {
- TimerManager.Tick -= UpdateInputs;
- }
-
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Controllers/DualSenseController.cs b/HandheldCompanion/Controllers/DualSenseController.cs
index 2c9884e36..f23bb9eba 100644
--- a/HandheldCompanion/Controllers/DualSenseController.cs
+++ b/HandheldCompanion/Controllers/DualSenseController.cs
@@ -105,11 +105,6 @@ public override void SetLightColor(byte R, byte G, byte B)
});
}
- public override void Cleanup()
- {
- TimerManager.Tick -= UpdateInputs;
- }
-
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Controllers/GordonController.cs b/HandheldCompanion/Controllers/GordonController.cs
index 637c007f8..14dcdac54 100644
--- a/HandheldCompanion/Controllers/GordonController.cs
+++ b/HandheldCompanion/Controllers/GordonController.cs
@@ -282,11 +282,6 @@ private void Close()
catch { }
}
- public override void Cleanup()
- {
- TimerManager.Tick -= UpdateInputs;
- }
-
public ushort GetHapticIntensity(byte input, ushort maxIntensity)
{
return (ushort)(input * maxIntensity * VibrationStrength / 255);
diff --git a/HandheldCompanion/Controllers/IController.xaml.cs b/HandheldCompanion/Controllers/IController.xaml.cs
index 8ab2a6e99..7e3f74323 100644
--- a/HandheldCompanion/Controllers/IController.xaml.cs
+++ b/HandheldCompanion/Controllers/IController.xaml.cs
@@ -2,7 +2,7 @@
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -354,11 +354,6 @@ public virtual void Unplug()
});
}
- // like Unplug but one that can be safely called when controller is already removed
- public virtual void Cleanup()
- {
- }
-
public bool IsHidden()
{
// bool hide_device = HidHide.IsRegistered(Details.deviceInstanceId);
diff --git a/HandheldCompanion/Controllers/LegionController.cs b/HandheldCompanion/Controllers/LegionController.cs
index d3ea3b717..d870afbef 100644
--- a/HandheldCompanion/Controllers/LegionController.cs
+++ b/HandheldCompanion/Controllers/LegionController.cs
@@ -37,15 +37,22 @@ private enum BackEnum
Y1 = 128,
}
+ private enum ControllerState
+ {
+ Unk0 = 0,
+ Unk1 = 1,
+ Wired = 2,
+ Wireless = 3,
+ }
+
private HidDevice hidDevice;
private const byte FRONT_IDX = 17;
private const byte BACK_IDX = 19;
private const byte STATUS_IDX = 0;
- private const byte PING_IDX = 40;
- private HashSet READY_STATES = new HashSet() {25, 60};
+ private const byte LCONTROLLER_STATE_IDX = 11;
+ private const byte RCONTROLLER_STATE_IDX = 12;
- private const byte MIN_WIRELESS_STATUS = 40;
- private const byte MAX_WIRELESS_STATUS = 50;
+ private HashSet READY_STATES = new HashSet() {25, 60};
private Thread dataThread;
private bool dataThreadRunning;
@@ -64,8 +71,9 @@ public bool IsWireless
{
get
{
- byte status = GetStatus(PING_IDX);
- return (status >= MIN_WIRELESS_STATUS && status <= MAX_WIRELESS_STATUS);
+ byte LControllerState = GetStatus(LCONTROLLER_STATE_IDX);
+ byte RControllerState = GetStatus(RCONTROLLER_STATE_IDX);
+ return LControllerState == (byte)ControllerState.Wireless || RControllerState == (byte)ControllerState.Wireless;
}
}
@@ -149,36 +157,42 @@ private byte GetStatus(int idx)
public override void Plug()
{
hidDevice = GetHidDevice();
-
if (hidDevice is not null && hidDevice.IsConnected)
{
if (!hidDevice.IsOpen)
- hidDevice.OpenDevice();
-
- dataThreadRunning = true;
- dataThread = new Thread(dataThreadLoop);
- dataThread.IsBackground = true;
- dataThread.Start();
+ hidDevice.OpenDevice();
+
+ // start data thread
+ if (dataThread is null)
+ {
+ dataThreadRunning = true;
+
+ dataThread = new Thread(dataThreadLoop);
+ dataThread.IsBackground = true;
+ dataThread.Start();
+ }
}
base.Plug();
}
public override void Unplug()
- {
+ {
+ // kill data thread
+ if (dataThread is not null)
+ {
+ dataThreadRunning = false;
+ dataThread.Join();
+ dataThread = null;
+ }
+
if (hidDevice is not null)
{
- // kill rumble thread
- dataThreadRunning = false;
- if (dataThread is not null)
- dataThread.Join();
-
if (hidDevice.IsConnected && hidDevice.IsOpen)
- {
- hidDevice.CloseDevice();
- hidDevice.Dispose();
- hidDevice = null;
- }
+ hidDevice.CloseDevice();
+
+ hidDevice.Dispose();
+ hidDevice = null;
}
base.Unplug();
@@ -240,12 +254,13 @@ private async void dataThreadLoop(object? obj)
continue;
HidReport report = hidDevice.ReadReport();
-
if (report is not null)
{
// check if packet is safe
- if (READY_STATES.Contains(report.Data[STATUS_IDX]))
- Data = report.Data;
+ if (READY_STATES.Contains(report.Data[STATUS_IDX]))
+ {
+ Data = report.Data;
+ }
}
}
}
diff --git a/HandheldCompanion/Controllers/ProController.cs b/HandheldCompanion/Controllers/ProController.cs
index 170232f27..e3d9b08d9 100644
--- a/HandheldCompanion/Controllers/ProController.cs
+++ b/HandheldCompanion/Controllers/ProController.cs
@@ -48,11 +48,6 @@ public override void Unplug()
base.Unplug();
}
- public override void Cleanup()
- {
- TimerManager.Tick -= UpdateInputs;
- }
-
public override void SetVibration(byte LargeMotor, byte SmallMotor)
{
// HD rumble isn't yet supported
diff --git a/HandheldCompanion/Controllers/XInputController.cs b/HandheldCompanion/Controllers/XInputController.cs
index 4e06b6faf..819c718c3 100644
--- a/HandheldCompanion/Controllers/XInputController.cs
+++ b/HandheldCompanion/Controllers/XInputController.cs
@@ -159,11 +159,6 @@ public override void Unplug()
base.Unplug();
}
- public override void Cleanup()
- {
- TimerManager.Tick -= UpdateInputs;
- }
-
public static UserIndex TryGetUserIndex(PnPDetails details)
{
XInputCapabilitiesEx capabilitiesEx = new();
diff --git a/HandheldCompanion/Controls/Hints/Hint_AMD_IntegerScalingCheck.cs b/HandheldCompanion/Controls/Hints/Hint_AMD_IntegerScalingCheck.cs
new file mode 100644
index 000000000..74f017a12
--- /dev/null
+++ b/HandheldCompanion/Controls/Hints/Hint_AMD_IntegerScalingCheck.cs
@@ -0,0 +1,80 @@
+using HandheldCompanion.Managers;
+using HandheldCompanion.Misc;
+using HandheldCompanion.Processors;
+using HandheldCompanion.Utils;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Diagnostics;
+using System.Management;
+using System.Windows;
+
+namespace HandheldCompanion.Controls.Hints
+{
+ public class Hint_AMD_IntegerScalingCheck : IHint
+ {
+ public Hint_AMD_IntegerScalingCheck() : base()
+ {
+ // default state
+ this.HintActionButton.Visibility = Visibility.Visible;
+
+ this.HintTitle.Text = Properties.Resources.Hint_AMD_IntegerScalingCheck;
+ this.HintDescription.Text = Properties.Resources.Hint_AMD_IntegerScalingCheckDesc;
+ this.HintReadMe.Text = Properties.Resources.Hint_AMD_IntegerScalingCheckReadme;
+
+ this.HintActionButton.Content = Properties.Resources.Hint_AMD_IntegerScalingCheckAction;
+
+ // manage events
+ PerformanceManager.Initialized += PerformanceManager_Initialized;
+ }
+
+ private void PerformanceManager_Initialized()
+ {
+ Processor processor = PerformanceManager.GetProcessor();
+
+ if (processor is not null && processor is AMDProcessor)
+ CheckSettings();
+ }
+
+ private void CheckSettings()
+ {
+ // read OS specific values
+ int EmbeddedIntegerScalingSupport = RegistryUtils.GetInt(@"SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000", "DalEmbeddedIntegerScalingSupport");
+
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ this.Visibility = EmbeddedIntegerScalingSupport != 1 ? Visibility.Visible : Visibility.Collapsed;
+ });
+ }
+
+ protected override async void HintActionButton_Click(object sender, RoutedEventArgs e)
+ {
+ RegistryUtils.SetValue(@"SYSTEM\ControlSet001\Control\Class\{4d36e968-e325-11ce-bfc1-08002be10318}\0000", "DalEmbeddedIntegerScalingSupport", 1);
+
+ var result = Dialog.ShowAsync($"{Properties.Resources.Dialog_ForceRestartTitle}",
+ $"{Properties.Resources.Dialog_ForceRestartDesc}",
+ ContentDialogButton.Primary, null,
+ $"{Properties.Resources.Dialog_Yes}",
+ $"{Properties.Resources.Dialog_No}");
+
+ await result;
+
+ switch (result.Result)
+ {
+ case ContentDialogResult.Primary:
+ using (Process shutdown = new())
+ {
+ shutdown.StartInfo.FileName = "shutdown.exe";
+ shutdown.StartInfo.Arguments = "-r -t 3";
+
+ shutdown.StartInfo.UseShellExecute = false;
+ shutdown.StartInfo.CreateNoWindow = true;
+ shutdown.Start();
+ }
+ break;
+ case ContentDialogResult.Secondary:
+ break;
+ }
+ }
+ }
+}
diff --git a/HandheldCompanion/Controls/Hints/Hint_CoreIsolationCheck.cs b/HandheldCompanion/Controls/Hints/Hint_CoreIsolationCheck.cs
index 54537025b..8630a0700 100644
--- a/HandheldCompanion/Controls/Hints/Hint_CoreIsolationCheck.cs
+++ b/HandheldCompanion/Controls/Hints/Hint_CoreIsolationCheck.cs
@@ -1,6 +1,6 @@
using HandheldCompanion.Misc;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Diagnostics;
using System.Management;
diff --git a/HandheldCompanion/Controls/Hints/Hint_LegionGoLegionSpace.cs b/HandheldCompanion/Controls/Hints/Hint_LegionGoLegionSpace.cs
new file mode 100644
index 000000000..8f74c2b31
--- /dev/null
+++ b/HandheldCompanion/Controls/Hints/Hint_LegionGoLegionSpace.cs
@@ -0,0 +1,128 @@
+using HandheldCompanion.Devices;
+using HandheldCompanion.Utils;
+using HandheldCompanion.Views;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.ServiceProcess;
+using System.Threading.Tasks;
+using System.Timers;
+using System.Windows;
+
+namespace HandheldCompanion.Controls.Hints
+{
+ public class Hint_LegionGoLegionSpace : IHint
+ {
+ private List serviceNames = new()
+ {
+ "DAService",
+ };
+
+ private List taskNames = new()
+ {
+ "LegionGoQuickSettings",
+ "LegionSpace",
+ "LSDaemon"
+ };
+
+ private List serviceControllers = new();
+ private Timer serviceTimer;
+
+ public Hint_LegionGoLegionSpace() : base()
+ {
+ if (MainWindow.CurrentDevice is not LegionGo)
+ return;
+
+ // Get all the services installed on the local computer
+ ServiceController[] services = ServiceController.GetServices();
+ foreach (string serviceName in serviceNames)
+ {
+ if (services.Any(s => serviceNames.Contains(s.ServiceName)))
+ {
+ // Create a service controller object for the specified service
+ ServiceController serviceController = new ServiceController(serviceName);
+ serviceControllers.Add(serviceController);
+ }
+ }
+
+ // Check if any of the services in the list exist
+ if (!serviceControllers.Any())
+ return;
+
+ serviceTimer = new Timer(4000);
+ serviceTimer.Elapsed += ServiceTimer_Elapsed;
+ serviceTimer.Start();
+
+ // default state
+ this.HintActionButton.Visibility = Visibility.Visible;
+
+ this.HintTitle.Text = Properties.Resources.Hint_LegionGoServices;
+ this.HintDescription.Text = Properties.Resources.Hint_LegionGoServicesDesc;
+ this.HintReadMe.Text = Properties.Resources.Hint_LegionGoServicesReadme;
+
+ this.HintActionButton.Content = Properties.Resources.Hint_LegionGoServicesAction;
+ }
+
+ private void ServiceTimer_Elapsed(object? sender, ElapsedEventArgs e)
+ {
+ if (!serviceControllers.Any())
+ return;
+
+ // Check if any of the services in the list exist and are running
+ bool anyRunning = false;
+
+ foreach (ServiceController serviceController in serviceControllers)
+ {
+ serviceController.Refresh();
+ if (serviceController.Status == ServiceControllerStatus.Running)
+ {
+ anyRunning = true;
+ break;
+ }
+ }
+
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ this.Visibility = anyRunning ? Visibility.Visible : Visibility.Collapsed;
+ });
+ }
+
+ protected override void HintActionButton_Click(object sender, RoutedEventArgs e)
+ {
+ if (!serviceControllers.Any())
+ return;
+
+ Task.Run(async () =>
+ {
+ // Disable services
+ foreach (ServiceController serviceController in serviceControllers)
+ {
+ // Disable service from doing anything anymore
+ ServiceUtils.ChangeStartMode(serviceController, ServiceStartMode.Disabled, out string error);
+
+ // Stop tasks related to service
+ foreach (string taskName in taskNames)
+ {
+ var taskProcess = Process.GetProcessesByName(taskName).FirstOrDefault();
+ if (taskProcess != null && !taskProcess.HasExited)
+ {
+ taskProcess.Kill();
+ }
+ }
+
+ // Stop running service
+ if (serviceController.Status == ServiceControllerStatus.Running)
+ serviceController.Stop();
+ }
+ });
+ }
+
+ public override void Stop()
+ {
+ serviceTimer.Stop();
+ base.Stop();
+ }
+ }
+}
diff --git a/HandheldCompanion/Controls/Mapping/AxisMapping.xaml b/HandheldCompanion/Controls/Mapping/AxisMapping.xaml
index 1bac32689..913421d36 100644
--- a/HandheldCompanion/Controls/Mapping/AxisMapping.xaml
+++ b/HandheldCompanion/Controls/Mapping/AxisMapping.xaml
@@ -6,12 +6,12 @@
xmlns:local="clr-namespace:HandheldCompanion.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1500"
d:DesignWidth="800"
mc:Ignorable="d">
-
+
@@ -60,475 +60,565 @@
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0} °, ElementName=Axis2AxisRotation, Mode=OneWay}" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ FlowDirection="LeftToRight"
+ IsMoveToPointEnabled="True"
+ IsSnapToTickEnabled="True"
+ Maximum="270"
+ Minimum="0"
+ ScrollViewer.PanningMode="HorizontalOnly"
+ Style="{DynamicResource SliderStyle1}"
+ TickFrequency="90"
+ TickPlacement="BottomRight"
+ ToolTip="{Binding Value, StringFormat=N0, RelativeSource={RelativeSource Self}, Mode=OneWay}"
+ ValueChanged="Axis_Rotation_Slider_ValueChanged" />
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat=N3, ElementName=Axis2MouseFilterCutoff, Mode=OneWay}" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Controls/Mapping/AxisMapping.xaml.cs b/HandheldCompanion/Controls/Mapping/AxisMapping.xaml.cs
index bc5abbc14..90492dfa3 100644
--- a/HandheldCompanion/Controls/Mapping/AxisMapping.xaml.cs
+++ b/HandheldCompanion/Controls/Mapping/AxisMapping.xaml.cs
@@ -3,7 +3,7 @@
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Windows;
using System.Windows.Controls;
@@ -53,7 +53,7 @@ internal void SetIActions(IActions actions)
base.SetIActions(actions);
// update UI
- ActionComboBox.SelectedIndex = (int)actions.ActionType;
+ ActionComboBox.SelectedIndex = (int)actions.actionType;
}
private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -70,10 +70,10 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
TargetComboBox.IsEnabled = ActionComboBox.SelectedIndex != 0;
// get current controller
- var controller = ControllerManager.GetEmulatedController();
+ IController? controller = ControllerManager.GetEmulatedController();
// populate target dropdown based on action type
- var type = (ActionType)ActionComboBox.SelectedIndex;
+ ActionType type = (ActionType)ActionComboBox.SelectedIndex;
if (type == ActionType.Disabled)
{
@@ -91,10 +91,10 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
if (controller is null)
return;
- foreach (var axis in IController.GetTargetAxis())
+ foreach (AxisLayoutFlags axis in IController.GetTargetAxis())
{
// create a label, store ButtonFlags as Tag and Label as controller specific string
- var buttonLabel = new Label { Tag = axis, Content = controller.GetAxisName(axis) };
+ Label buttonLabel = new Label { Tag = axis, Content = controller.GetAxisName(axis) };
TargetComboBox.Items.Add(buttonLabel);
if (axis.Equals(((AxisActions)Actions).Axis))
@@ -129,8 +129,7 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
}
// create a label, store MouseActionsType as Tag and Label as controller specific string
- var buttonLabel = new Label
- { Tag = mouseType, Content = EnumUtils.GetDescriptionFromEnumValue(mouseType) };
+ Label buttonLabel = new Label { Tag = mouseType, Content = EnumUtils.GetDescriptionFromEnumValue(mouseType) };
TargetComboBox.Items.Add(buttonLabel);
if (mouseType.Equals(((MouseActions)Actions).MouseType))
@@ -148,6 +147,10 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
Axis2MouseFilterCutoff.Value = ((MouseActions)this.Actions).FilterCutoff;
}
+ // if no target element was selected, pick the first one
+ if (TargetComboBox.SelectedItem is null)
+ TargetComboBox.SelectedIndex = 0;
+
base.Update();
}
@@ -160,7 +163,7 @@ private void Target_SelectionChanged(object sender, SelectionChangedEventArgs e)
return;
// generate IActions based on settings
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
{
@@ -191,7 +194,7 @@ private void Axis2AxisAutoRotate_Toggled(object sender, RoutedEventArgs e)
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AutoRotate = Axis2AxisAutoRotate.IsOn;
@@ -206,7 +209,7 @@ private void Axis_Rotation_Slider_ValueChanged(object sender, RoutedPropertyChan
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisInverted = (((int)Axis2AxisRotation.Value / 90) & 2) == 2;
@@ -222,7 +225,7 @@ private void Axis_InnerDeadzone_Slider_ValueChanged(object sender, RoutedPropert
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisDeadZoneInner = (int)Axis2AxisInnerDeadzone.Value;
@@ -237,7 +240,7 @@ private void Axis_OuterDeadzone_Slider_ValueChanged(object sender, RoutedPropert
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisDeadZoneOuter = (int)Axis2AxisOuterDeadzone.Value;
@@ -252,7 +255,7 @@ private void Axis_AntiDeadZone_Slider_ValueChanged(object sender, RoutedProperty
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisAntiDeadZone = (int)Axis2AxisAntiDeadzone.Value;
@@ -267,7 +270,7 @@ private void Axis2AxisImproveCircularity_Toggled(object sender, RoutedEventArgs
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).ImproveCircularity = Axis2AxisImproveCircularity.IsOn;
@@ -282,7 +285,7 @@ private void Axis2MousePointerSpeed_ValueChanged(object sender, RoutedPropertyCh
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).Sensivity = (int)Axis2MousePointerSpeed.Value;
@@ -297,7 +300,7 @@ private void Axis2MouseAutoRotate_Toggled(object sender, RoutedEventArgs e)
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).AutoRotate = Axis2MouseAutoRotate.IsOn;
@@ -312,7 +315,7 @@ private void Axis2MouseRotation_ValueChanged(object sender, RoutedPropertyChange
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).AxisInverted = (((int)Axis2MouseRotation.Value / 90) & 2) == 2;
@@ -328,7 +331,7 @@ private void Axis2MouseDeadzone_ValueChanged(object sender, RoutedPropertyChange
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).Deadzone = (int)Axis2MouseDeadzone.Value;
@@ -343,7 +346,7 @@ private void Axis2MouseAcceleration_ValueChanged(object sender, RoutedPropertyCh
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)this.Actions).Acceleration = (float)Axis2MouseAcceleration.Value;
@@ -359,7 +362,7 @@ private void Axis2MouseFiltering_Toggled(object sender, RoutedEventArgs e)
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)this.Actions).Filtering = Axis2MouseFiltering.IsOn;
@@ -374,7 +377,7 @@ private void Axis2MouseFilterCutoff_ValueChanged(object sender, RoutedPropertyCh
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)this.Actions).FilterCutoff = (float)Axis2MouseFilterCutoff.Value;
diff --git a/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml b/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml
index 1f4394781..82ad10483 100644
--- a/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml
+++ b/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml
@@ -6,7 +6,7 @@
xmlns:local="clr-namespace:HandheldCompanion.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1000"
d:DesignWidth="800"
mc:Ignorable="d">
@@ -39,12 +39,14 @@
-
-
+
+
+
+
@@ -73,101 +75,109 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
-
-
-
+ Text="{Binding Value, StringFormat={}{0} ms, ElementName=Turbo_Slider, Mode=OneWay}" />
+
+
+
+
+
+
+
+
-
-
+
+
+ Text="Interruptable" />
+ Toggled="Toggle_Interruptable_Toggled" />
-
-
-
-
-
-
-
+ BorderThickness="0,1,0,0" />
-
-
-
-
+
+
+ Text="Press to toggle" />
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ BorderThickness="0,1,0,0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml.cs b/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml.cs
index 272f1d223..ad3238b9a 100644
--- a/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml.cs
+++ b/HandheldCompanion/Controls/Mapping/ButtonMapping.xaml.cs
@@ -4,11 +4,12 @@
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
+using System.Linq;
namespace HandheldCompanion.Controls;
@@ -67,7 +68,7 @@ public void SetIActions(IActions actions)
base.SetIActions(actions);
// update UI
- ActionComboBox.SelectedIndex = (int)actions.ActionType;
+ ActionComboBox.SelectedIndex = (int)actions.actionType;
}
public IActions GetIActions()
@@ -90,10 +91,10 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
TargetComboBox.IsEnabled = ActionComboBox.SelectedIndex != 0;
// get current controller
- var controller = ControllerManager.GetEmulatedController();
+ IController controller = ControllerManager.GetEmulatedController();
// populate target dropdown based on action type
- var type = (ActionType)ActionComboBox.SelectedIndex;
+ ActionType type = (ActionType)ActionComboBox.SelectedIndex;
if (type == ActionType.Disabled)
{
@@ -107,22 +108,16 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
if (Actions is null || Actions is not ButtonActions)
Actions = new ButtonActions();
- foreach (var button in IController.GetTargetButtons())
+ foreach (ButtonFlags button in IController.GetTargetButtons())
{
// create a label, store ButtonFlags as Tag and Label as controller specific string
- var buttonLabel = new Label { Tag = button, Content = controller.GetButtonName(button) };
+ Label buttonLabel = new Label { Tag = button, Content = controller.GetButtonName(button) };
TargetComboBox.Items.Add(buttonLabel);
if (button.Equals(((ButtonActions)Actions).Button))
TargetComboBox.SelectedItem = buttonLabel;
}
- // settings
- if (TargetComboBox.SelectedItem is not null)
- PressComboBox.SelectedIndex = (int)this.Actions.PressType;
- else
- this.Actions.PressType = (PressType)PressComboBox.SelectedIndex;
-
// button specific settings
}
else if (type == ActionType.Keyboard)
@@ -132,10 +127,8 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
// use optimized lazily created list
TargetComboBox.ItemsSource = keyList;
-
- foreach (var keyLabel in keyList)
- if (keyLabel.Tag.Equals(((KeyboardActions)this.Actions).Key))
- TargetComboBox.SelectedItem = keyLabel;
+ foreach (var keyLabel in keyList.Where(keyLabel => keyLabel.Tag.Equals(((KeyboardActions)this.Actions).Key)))
+ TargetComboBox.SelectedItem = keyLabel;
// keyboard specific settings
ModifierComboBox.SelectedIndex = (int)((KeyboardActions)this.Actions).Modifiers;
@@ -156,35 +149,34 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
}
// create a label, store MouseActionsType as Tag and Label as controller specific string
- var buttonLabel = new Label
- { Tag = mouseType, Content = EnumUtils.GetDescriptionFromEnumValue(mouseType) };
+ Label buttonLabel = new Label { Tag = mouseType, Content = EnumUtils.GetDescriptionFromEnumValue(mouseType) };
TargetComboBox.Items.Add(buttonLabel);
if (mouseType.Equals(((MouseActions)Actions).MouseType))
TargetComboBox.SelectedItem = buttonLabel;
}
- // settings
- if (TargetComboBox.SelectedItem is not null)
- PressComboBox.SelectedIndex = (int)this.Actions.PressType;
- else
- this.Actions.PressType = (PressType)PressComboBox.SelectedIndex;
-
// mouse specific settings
ModifierComboBox.SelectedIndex = (int)((MouseActions)this.Actions).Modifiers;
}
- // press type is treated specially, it can be set before action
+ // settings
if (TargetComboBox.SelectedItem is not null)
- PressComboBox.SelectedIndex = (int)this.Actions.PressType;
+ PressComboBox.SelectedIndex = (int)this.Actions.pressType;
else
- this.Actions.PressType = (PressType)PressComboBox.SelectedIndex;
- Button2ButtonPressDelay.Visibility = Actions.PressType == PressType.Long ? Visibility.Visible : Visibility.Collapsed;
+ this.Actions.pressType = (PressType)PressComboBox.SelectedIndex;
+
+ // if no target element was selected, pick the first one
+ if (TargetComboBox.SelectedItem is null)
+ TargetComboBox.SelectedIndex = 0;
+
+ Button2ButtonPressDelay.Visibility = Actions.pressType != PressType.Short ? Visibility.Visible : Visibility.Collapsed;
// settings
- LongPressDelaySlider.Value = (int)this.Actions.LongPressTime;
+ LongPressDelaySlider.Value = (int)this.Actions.ActionTimer;
Toggle_Turbo.IsOn = this.Actions.Turbo;
Turbo_Slider.Value = this.Actions.TurboDelay;
+ Toggle_Interruptable.IsOn = this.Actions.Interruptable;
Toggle_Toggle.IsOn = this.Actions.Toggle;
HapticModeComboBox.SelectedIndex = (int)this.Actions.HapticMode;
HapticStrengthComboBox.SelectedIndex = (int)this.Actions.HapticStrength;
@@ -201,7 +193,7 @@ private void Target_SelectionChanged(object sender, SelectionChangedEventArgs e)
return;
// generate IActions based on settings
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Button:
{
@@ -240,9 +232,9 @@ private void Press_SelectionChanged(object sender, SelectionChangedEventArgs e)
if (this.Actions is null)
return;
- this.Actions.PressType = (PressType)PressComboBox.SelectedIndex;
+ this.Actions.pressType = (PressType)PressComboBox.SelectedIndex;
- Button2ButtonPressDelay.Visibility = Actions.PressType == PressType.Long ? Visibility.Visible : Visibility.Collapsed;
+ Button2ButtonPressDelay.Visibility = Actions.pressType != PressType.Short ? Visibility.Visible : Visibility.Collapsed;
base.Update();
}
@@ -252,7 +244,7 @@ private void LongPressDelaySlider_ValueChanged(object sender, RoutedPropertyChan
if (this.Actions is null)
return;
- this.Actions.LongPressTime = (int)LongPressDelaySlider.Value;
+ this.Actions.ActionTimer = (int)LongPressDelaySlider.Value;
base.Update();
}
@@ -264,7 +256,7 @@ private void Modifier_SelectionChanged(object sender, SelectionChangedEventArgs
ModifierSet mods = (ModifierSet)ModifierComboBox.SelectedIndex;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Keyboard:
((KeyboardActions)this.Actions).Modifiers = mods;
@@ -327,4 +319,14 @@ private void HapticStrength_SelectionChanged(object sender, SelectionChangedEven
base.Update();
}
+
+ private void Toggle_Interruptable_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (this.Actions is null)
+ return;
+
+ this.Actions.Interruptable = Toggle_Interruptable.IsOn;
+
+ base.Update();
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Controls/Mapping/ButtonStack.xaml.cs b/HandheldCompanion/Controls/Mapping/ButtonStack.xaml.cs
index ca89c8a1f..dc4d1e16f 100644
--- a/HandheldCompanion/Controls/Mapping/ButtonStack.xaml.cs
+++ b/HandheldCompanion/Controls/Mapping/ButtonStack.xaml.cs
@@ -1,6 +1,6 @@
using HandheldCompanion.Actions;
using HandheldCompanion.Inputs;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
diff --git a/HandheldCompanion/Controls/Mapping/GyroMapping.xaml b/HandheldCompanion/Controls/Mapping/GyroMapping.xaml
index 206ee2186..dabe9d517 100644
--- a/HandheldCompanion/Controls/Mapping/GyroMapping.xaml
+++ b/HandheldCompanion/Controls/Mapping/GyroMapping.xaml
@@ -7,7 +7,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:HandheldCompanion.Properties"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1500"
d:DesignWidth="800"
mc:Ignorable="d">
diff --git a/HandheldCompanion/Controls/Mapping/GyroMapping.xaml.cs b/HandheldCompanion/Controls/Mapping/GyroMapping.xaml.cs
index 5dae39bec..b0bfb3d95 100644
--- a/HandheldCompanion/Controls/Mapping/GyroMapping.xaml.cs
+++ b/HandheldCompanion/Controls/Mapping/GyroMapping.xaml.cs
@@ -3,7 +3,7 @@
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Windows;
using System.Windows.Controls;
@@ -100,7 +100,7 @@ internal void SetIActions(IActions actions)
GyroHotkey.inputsChord.State = ((GyroActions)actions).MotionTrigger.Clone() as ButtonState;
GyroHotkey.DrawInput();
- ActionComboBox.SelectedIndex = (int)actions.ActionType;
+ ActionComboBox.SelectedIndex = (int)actions.actionType;
}
private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -231,7 +231,7 @@ private void Target_SelectionChanged(object sender, SelectionChangedEventArgs e)
return;
// generate IActions based on settings
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
{
@@ -262,7 +262,7 @@ private void Axis2AxisAutoRotate_Toggled(object sender, RoutedEventArgs e)
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AutoRotate = Axis2AxisAutoRotate.IsOn;
@@ -277,7 +277,7 @@ private void Axis_Rotation_Slider_ValueChanged(object sender, RoutedPropertyChan
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisInverted = (((int)Axis2AxisRotation.Value / 90) & 2) == 2;
@@ -293,7 +293,7 @@ private void Axis_InnerDeadzone_Slider_ValueChanged(object sender, RoutedPropert
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisDeadZoneInner = (int)Axis2AxisInnerDeadzone.Value;
@@ -308,7 +308,7 @@ private void Axis_OuterDeadzone_Slider_ValueChanged(object sender, RoutedPropert
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisDeadZoneOuter = (int)Axis2AxisOuterDeadzone.Value;
@@ -323,7 +323,7 @@ private void Axis_AntiDeadZone_Slider_ValueChanged(object sender, RoutedProperty
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).AxisAntiDeadZone = (int)Axis2AxisAntiDeadzone.Value;
@@ -338,7 +338,7 @@ private void Axis2AxisImproveCircularity_Toggled(object sender, RoutedEventArgs
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Joystick:
((AxisActions)Actions).ImproveCircularity = Axis2AxisImproveCircularity.IsOn;
@@ -353,7 +353,7 @@ private void Axis2MousePointerSpeed_ValueChanged(object sender, RoutedPropertyCh
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).Sensivity = (int)Axis2MousePointerSpeed.Value;
@@ -368,7 +368,7 @@ private void Axis2MouseAutoRotate_Toggled(object sender, RoutedEventArgs e)
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).AutoRotate = Axis2MouseAutoRotate.IsOn;
@@ -383,7 +383,7 @@ private void Axis2MouseRotation_ValueChanged(object sender, RoutedPropertyChange
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).AxisInverted = (((int)Axis2MouseRotation.Value / 90) & 2) == 2;
@@ -399,7 +399,7 @@ private void Axis2MouseDeadzone_ValueChanged(object sender, RoutedPropertyChange
if (Actions is null)
return;
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)Actions).Deadzone = (int)Axis2MouseDeadzone.Value;
@@ -414,7 +414,7 @@ private void Axis2MouseAcceleration_ValueChanged(object sender, RoutedPropertyCh
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Mouse:
((MouseActions)this.Actions).Acceleration = (float)Axis2MouseAcceleration.Value;
diff --git a/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml b/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml
index 0d1c04207..f8e156628 100644
--- a/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml
+++ b/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml
@@ -7,12 +7,12 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:resx="clr-namespace:HandheldCompanion.Properties"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1000"
d:DesignWidth="800"
mc:Ignorable="d">
-
+
@@ -61,131 +61,154 @@
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml.cs b/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml.cs
index 852fb6434..4e6439c2c 100644
--- a/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml.cs
+++ b/HandheldCompanion/Controls/Mapping/TriggerMapping.xaml.cs
@@ -2,7 +2,7 @@
using HandheldCompanion.Controllers;
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System.Windows;
using System.Windows.Controls;
@@ -51,7 +51,7 @@ internal void SetIActions(IActions actions)
base.SetIActions(actions);
// update UI
- ActionComboBox.SelectedIndex = (int)actions.ActionType;
+ ActionComboBox.SelectedIndex = (int)actions.actionType;
}
private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -100,6 +100,10 @@ private void Action_SelectionChanged(object sender, SelectionChangedEventArgs e)
}
}
+ // if no target element was selected, pick the first one
+ if (TargetComboBox.SelectedItem is null)
+ TargetComboBox.SelectedIndex = 0;
+
// settings
Trigger2TriggerInnerDeadzone.Value = ((TriggerActions)this.Actions).AxisDeadZoneInner;
Trigger2TriggerOuterDeadzone.Value = ((TriggerActions)this.Actions).AxisDeadZoneOuter;
@@ -117,7 +121,7 @@ private void Target_SelectionChanged(object sender, SelectionChangedEventArgs e)
return;
// generate IActions based on settings
- switch (Actions.ActionType)
+ switch (Actions.actionType)
{
case ActionType.Trigger:
{
@@ -135,7 +139,7 @@ private void Trigger2TriggerInnerDeadzone_ValueChanged(object sender, RoutedProp
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Trigger:
((TriggerActions)this.Actions).AxisDeadZoneInner = (int)Trigger2TriggerInnerDeadzone.Value;
@@ -150,7 +154,7 @@ private void Trigger2TriggerOuterDeadzone_ValueChanged(object sender, RoutedProp
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Trigger:
((TriggerActions)this.Actions).AxisDeadZoneOuter = (int)Trigger2TriggerOuterDeadzone.Value;
@@ -165,7 +169,7 @@ private void Trigger2TriggerAntiDeadzone_ValueChanged(object sender, RoutedPrope
if (this.Actions is null)
return;
- switch (this.Actions.ActionType)
+ switch (this.Actions.actionType)
{
case ActionType.Trigger:
((TriggerActions)this.Actions).AxisAntiDeadZone = (int)Trigger2TriggerAntiDeadzone.Value;
diff --git a/HandheldCompanion/Controls/ProcessEx.xaml b/HandheldCompanion/Controls/ProcessEx.xaml
index 1d2382797..202ade3be 100644
--- a/HandheldCompanion/Controls/ProcessEx.xaml
+++ b/HandheldCompanion/Controls/ProcessEx.xaml
@@ -37,7 +37,7 @@
-
+
@@ -59,15 +59,63 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
diff --git a/HandheldCompanion/Controls/ProcessEx.xaml.cs b/HandheldCompanion/Controls/ProcessEx.xaml.cs
index 2f5475195..f4a5d6b9b 100644
--- a/HandheldCompanion/Controls/ProcessEx.xaml.cs
+++ b/HandheldCompanion/Controls/ProcessEx.xaml.cs
@@ -1,13 +1,20 @@
using HandheldCompanion.Managers;
using HandheldCompanion.Platforms;
using HandheldCompanion.Utils;
+using Microsoft.Win32;
+using Newtonsoft.Json.Linq;
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
+using Windows.Foundation.Collections;
namespace HandheldCompanion.Controls;
@@ -26,26 +33,30 @@ public enum ProcessFilter
}
public string _Executable;
-
private string _Title;
-
- public ConcurrentList Children = new();
+ public string Path;
public ProcessFilter Filter;
+ public PlatformType Platform { get; set; }
public ImageSource imgSource;
public ProcessThread MainThread;
-
public IntPtr MainWindowHandle;
- public string Path;
-
private ThreadState prevThreadState = ThreadState.Terminated;
private ThreadWaitReason prevThreadWaitReason = ThreadWaitReason.UserRequest;
public Process Process;
private readonly int ProcessId;
+ private LockObject updateLock = new();
+
+ public ConcurrentList Children = new();
+
+ private const string AppCompatRegistry = @"Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers";
+ public static string RunAsAdminRegistryValue = "RUNASADMIN";
+ public static string DisabledMaximizedWindowedValue = "DISABLEDXMAXIMIZEDWINDOWEDMODE";
+ public static string HighDPIAwareValue = "HIGHDPIAWARE";
public ProcessEx()
{
@@ -56,14 +67,10 @@ public ProcessEx(Process process, string path, string executable, ProcessFilter
{
Process = process;
ProcessId = process.Id;
-
Path = path;
-
Executable = executable;
- MainWindowTitle = executable; // temporary, will be overwritten by ProcessManager
-
+ MainWindowTitle = path;
Filter = filter;
- Platform = PlatformManager.GetPlatform(Process);
if (!string.IsNullOrEmpty(path) && File.Exists(path))
{
@@ -76,6 +83,76 @@ public ProcessEx(Process process, string path, string executable, ProcessFilter
}
}
+ public static string GetAppCompatFlags(string Path)
+ {
+ if (string.IsNullOrEmpty(Path))
+ return string.Empty;
+
+ using (var key = Registry.CurrentUser.OpenSubKey(AppCompatRegistry))
+ {
+ string valueStr = (string)key?.GetValue(Path);
+ return valueStr;
+ }
+ }
+
+ public static void SetAppCompatFlag(string Path, string Flag, bool value)
+ {
+ if (string.IsNullOrEmpty(Path))
+ return;
+
+ using (var key = Registry.CurrentUser.CreateSubKey(AppCompatRegistry, RegistryKeyPermissionCheck.ReadWriteSubTree))
+ {
+ if (key != null)
+ {
+ List values = new List { "~" }; ;
+ string valueStr = (string)key.GetValue(Path);
+
+ if (!string.IsNullOrEmpty(valueStr))
+ values = valueStr.Split(' ').ToList();
+
+ values.Remove(Flag);
+
+ if (value)
+ values.Add(Flag);
+
+ if (values.Count == 1 && values[0] == "~" && !string.IsNullOrEmpty(valueStr))
+ key.DeleteValue(Path);
+ else
+ key.SetValue(Path, string.Join(" ", values), RegistryValueKind.String);
+ }
+ }
+ }
+
+ public bool FullScreenOptimization
+ {
+ get
+ {
+ string valueStr = GetAppCompatFlags(Path);
+ return !string.IsNullOrEmpty(valueStr)
+ && valueStr.Split(' ').Any(s => s == DisabledMaximizedWindowedValue);
+ }
+
+ set
+ {
+ SetAppCompatFlag(Path, DisabledMaximizedWindowedValue, value);
+ }
+ }
+
+ public bool HighDPIAware
+ {
+ get
+ {
+ string valueStr = GetAppCompatFlags(Path);
+ return !string.IsNullOrEmpty(valueStr)
+ && valueStr.Split(' ').Any(s => s == HighDPIAwareValue);
+ }
+
+ set
+ {
+ SetAppCompatFlag(Path, HighDPIAwareValue, value);
+ }
+ }
+
public string MainWindowTitle
{
get => _Title;
@@ -98,30 +175,28 @@ public string Executable
}
}
- public PlatformType Platform { get; set; }
-
- public void Dispose()
- {
- if (Process is not null)
- Process.Dispose();
- if (MainThread is not null)
- MainThread.Dispose();
- Children.Dispose();
-
- GC.SuppressFinalize(this); //now, the finalizer won't be called
- }
-
public int GetProcessId()
{
return ProcessId;
}
- public bool HasExited()
+ public bool HasExited
{
- if (Process is not null)
- return Process.HasExited;
+ get
+ {
+ if (Process is not null)
+ return Process.HasExited;
- return true;
+ return true;
+ }
+ }
+
+ public bool IsSuspended
+ {
+ get
+ {
+ return prevThreadWaitReason == ThreadWaitReason.Suspended;
+ }
}
public void Refresh()
@@ -132,46 +207,47 @@ public void Refresh()
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- switch (MainThread.ThreadState)
+ using (new ScopedLock(updateLock))
{
- case ThreadState.Wait:
- {
- // monitor if the process main thread was suspended or resumed
- if (MainThread.WaitReason != prevThreadWaitReason)
+ switch (MainThread.ThreadState)
+ {
+ case ThreadState.Wait:
{
- prevThreadWaitReason = MainThread.WaitReason;
-
- switch (prevThreadWaitReason)
+ // monitor if the process main thread was suspended or resumed
+ if (MainThread.WaitReason != prevThreadWaitReason)
{
- case ThreadWaitReason.Suspended:
- SuspendToggle.IsOn = true;
- break;
-
- default:
- SuspendToggle.IsOn = false;
- break;
+ prevThreadWaitReason = MainThread.WaitReason;
+
+ switch (prevThreadWaitReason)
+ {
+ case ThreadWaitReason.Suspended:
+ SuspendToggle.IsOn = true;
+ break;
+
+ default:
+ SuspendToggle.IsOn = false;
+ break;
+ }
}
}
- }
- break;
-
- case ThreadState.Terminated:
- {
- // dispose from MainThread
- MainThread.Dispose();
- MainThread = null;
- }
- break;
- }
+ break;
- // update previous state
- prevThreadState = MainThread.ThreadState;
- });
- }
+ case ThreadState.Terminated:
+ {
+ // dispose from MainThread
+ MainThread.Dispose();
+ MainThread = null;
+ }
+ break;
+ }
- public bool IsSuspended()
- {
- return prevThreadWaitReason == ThreadWaitReason.Suspended;
+ // update previous state
+ prevThreadState = MainThread.ThreadState;
+
+ T_FullScreenOptimization.IsOn = !FullScreenOptimization;
+ T_HighDPIAware.IsOn = !HighDPIAware;
+ }
+ });
}
public void RefreshChildProcesses()
@@ -190,6 +266,10 @@ public void RefreshChildProcesses()
private void SuspendToggle_Toggled(object sender, RoutedEventArgs e)
{
+ // wait until lock is released
+ if (updateLock)
+ return;
+
switch (SuspendToggle.IsOn)
{
case true:
@@ -204,8 +284,6 @@ private void SuspendToggle_Toggled(object sender, RoutedEventArgs e)
ProcessManager.ResumeProcess(this);
break;
}
-
- Refresh();
}
private void B_KillProcess_Clicked(object sender, RoutedEventArgs e)
@@ -213,4 +291,33 @@ private void B_KillProcess_Clicked(object sender, RoutedEventArgs e)
if (Process is not null)
Process.Kill();
}
+
+ public void Dispose()
+ {
+ if (Process is not null)
+ Process.Dispose();
+ if (MainThread is not null)
+ MainThread.Dispose();
+ Children.Dispose();
+
+ GC.SuppressFinalize(this); //now, the finalizer won't be called
+ }
+
+ private void FullScreenOptimization_Toggled(object sender, RoutedEventArgs e)
+ {
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ FullScreenOptimization = !T_FullScreenOptimization.IsOn;
+ }
+
+ private void HighDPIAware_Toggled(object sender, RoutedEventArgs e)
+ {
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ HighDPIAware = !T_HighDPIAware.IsOn;
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Converters/InverseAppThemeConverter.cs b/HandheldCompanion/Converters/InverseAppThemeConverter.cs
index 53fa9299f..4b2e465f2 100644
--- a/HandheldCompanion/Converters/InverseAppThemeConverter.cs
+++ b/HandheldCompanion/Converters/InverseAppThemeConverter.cs
@@ -1,4 +1,4 @@
-using Inkore.UI.WPF.Modern;
+using iNKORE.UI.WPF.Modern;
using System;
using System.Globalization;
using System.Windows.Data;
diff --git a/HandheldCompanion/DSU/DSUServer.cs b/HandheldCompanion/DSU/DSUServer.cs
index 18355ab96..dedc8ad03 100644
--- a/HandheldCompanion/DSU/DSUServer.cs
+++ b/HandheldCompanion/DSU/DSUServer.cs
@@ -11,7 +11,6 @@
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;
-using Timer = System.Timers.Timer;
namespace HandheldCompanion;
@@ -73,7 +72,8 @@ public class DSUServer
private const ushort MaxProtocolVersion = 1001;
private SemaphoreSlim _pool;
- private SocketAsyncEventArgs[] argsList;
+ //private SocketAsyncEventArgs[] argsList;
+ private byte[][] dataBuffers;
private readonly Dictionary clients = new();
@@ -93,12 +93,19 @@ public class DSUServer
private uint serverId;
private int udpPacketCount;
private Socket udpSock;
- private Timer udpTimer;
public DSUServer()
{
PadMacAddress = new PhysicalAddress(new byte[] { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 });
- portInfoGet = GetPadDetailForIdx;
+ portInfoGet = GetPadDetailForIdx;
+ _pool = new SemaphoreSlim(ARG_BUFFER_LEN);
+ dataBuffers = new byte[ARG_BUFFER_LEN][];
+ for (int num = 0; num < ARG_BUFFER_LEN; num++)
+ {
+ SocketAsyncEventArgs args = new SocketAsyncEventArgs();
+ args.Completed += SocketEvent_AsyncCompleted;
+ dataBuffers[num] = new byte[100];
+ }
padMeta = new DualShockPadMeta()
{
@@ -110,32 +117,6 @@ public DSUServer()
Model = DsModel.DS4,
PadState = DsState.Connected
};
-
- udpTimer = new(5000);
- udpTimer.AutoReset = false;
- udpTimer.Elapsed += UdpTimer_Elapsed;
- }
-
- private void ResetPool()
- {
- if (_pool is not null)
- _pool.Release();
-
- _pool = new SemaphoreSlim(ARG_BUFFER_LEN);
-
- if (argsList is not null && argsList.Length != 0)
- foreach(SocketAsyncEventArgs args in argsList)
- args.Dispose();
-
- argsList = new SocketAsyncEventArgs[ARG_BUFFER_LEN];
-
- for (int num = 0; num < ARG_BUFFER_LEN; num++)
- {
- SocketAsyncEventArgs args = new SocketAsyncEventArgs();
- args.SetBuffer(new byte[100], 0, 100);
- args.Completed += SocketEvent_Completed;
- argsList[num] = args;
- }
}
private void GetPadDetailForIdx(int padIdx, ref DualShockPadMeta meta)
@@ -152,14 +133,16 @@ public override string ToString()
return GetType().Name;
}
- private void SocketEvent_Completed(object sender, SocketAsyncEventArgs e)
+ private void SocketEvent_AsyncCompleted(object sender, SocketAsyncEventArgs e)
{
_pool.Release();
+ e.Dispose();
}
- private void CompletedSynchronousSocketEvent()
+ private void CompletedSynchronousSocketEvent(SocketAsyncEventArgs args)
{
_pool.Release();
+ args.Dispose();
}
private int BeginPacket(byte[] packetBuf, ushort reqProtocolVersion = MaxProtocolVersion)
@@ -191,38 +174,42 @@ private void FinishPacket(byte[] packetBuf)
var crcCalc = Crc32Algorithm.Compute(packetBuf);
Array.Copy(BitConverter.GetBytes(crcCalc), 0, packetBuf, 8, 4);
- }
-
- private void SendPacket(IPEndPoint clientEP, byte[] usefulData, ushort reqProtocolVersion = MaxProtocolVersion)
- {
- var packetData = new byte[usefulData.Length + 16];
- var currIdx = BeginPacket(packetData, reqProtocolVersion);
- Array.Copy(usefulData, 0, packetData, currIdx, usefulData.Length);
- FinishPacket(packetData);
- poolLock.EnterWriteLock();
- //try { udpSock.SendTo(packetData, clientEP); }
- var temp = listInd;
- listInd = ++listInd % ARG_BUFFER_LEN;
- var args = argsList[temp];
- poolLock.ExitWriteLock();
-
- _pool.Wait();
- args.RemoteEndPoint = clientEP;
- Array.Copy(packetData, args.Buffer, packetData.Length);
- //args.SetBuffer(packetData, 0, packetData.Length);
- var sentAsync = false;
- try
- {
- sentAsync = udpSock.SendToAsync(args);
- if (!sentAsync) CompletedSynchronousSocketEvent();
- }
- catch (Exception /*e*/)
- {
- }
- finally
- {
- if (!sentAsync) CompletedSynchronousSocketEvent();
- }
+ }
+
+ private void SendPacket(IPEndPoint clientEP, byte[] usefulData, ushort reqProtocolVersion = MaxProtocolVersion)
+ {
+ byte[] packetData = new byte[usefulData.Length + 16];
+ int currIdx = BeginPacket(packetData, reqProtocolVersion);
+ Array.Copy(usefulData, 0, packetData, currIdx, usefulData.Length);
+ FinishPacket(packetData);
+
+ //try { udpSock.SendTo(packetData, clientEP); }
+ int temp = 0;
+ poolLock.EnterWriteLock();
+ temp = listInd;
+ listInd = ++listInd % ARG_BUFFER_LEN;
+ SocketAsyncEventArgs args = new SocketAsyncEventArgs()
+ {
+ RemoteEndPoint = clientEP,
+ };
+ args.SetBuffer(dataBuffers[temp], 0, 100);
+ args.Completed += SocketEvent_AsyncCompleted;
+ poolLock.ExitWriteLock();
+
+ _pool.Wait();
+ Array.Copy(packetData, args.Buffer, packetData.Length);
+ //args.SetBuffer(packetData, 0, packetData.Length);
+ bool sentAsync = false;
+ try
+ {
+ sentAsync = udpSock.SendToAsync(args);
+ //if (!sentAsync) CompletedSynchronousSocketEvent();
+ }
+ catch (Exception /*e*/) { }
+ finally
+ {
+ if (!sentAsync) CompletedSynchronousSocketEvent(args);
+ }
}
private void ProcessIncoming(byte[] localMsg, IPEndPoint clientEP)
@@ -391,7 +378,6 @@ private void ReceiveCallback(IAsyncResult iar)
if (running)
{
ResetUDPConn();
- return;
}
}
catch (Exception /*e*/) { }
@@ -418,9 +404,9 @@ private void StartReceive()
catch (SocketException /*ex*/)
{
if (running)
- {
- ResetUDPConn();
- return;
+ {
+ ResetUDPConn();
+ StartReceive();
}
}
catch (Exception /*ex*/) { }
@@ -432,25 +418,15 @@ private void StartReceive()
/// connection is terminated. Avoids memory leak
///
private void ResetUDPConn()
- {
- // suspend UDP
- if (running)
- Stop();
-
- udpTimer.Stop();
- udpTimer.Start();
- }
-
- private void UdpTimer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
- {
- // resume UDP
- Start();
+ {
+ uint IOC_IN = 0x80000000;
+ uint IOC_VENDOR = 0x18000000;
+ uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
+ udpSock.IOControl((int)SIO_UDP_CONNRESET, new byte[] { Convert.ToByte(false) }, null);
}
public bool Start()
{
- ResetPool();
-
try
{
udpSock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
@@ -734,28 +710,30 @@ public void Tick(long ticks)
foreach (var cl in clientsList)
{
- //try { udpSock.SendTo(outputData, cl); }
int temp = 0;
poolLock.EnterWriteLock();
temp = listInd;
- listInd = ++listInd % ARG_BUFFER_LEN;
- SocketAsyncEventArgs args = argsList[temp];
+ listInd = ++listInd % ARG_BUFFER_LEN;
+ SocketAsyncEventArgs args = new SocketAsyncEventArgs()
+ {
+ RemoteEndPoint = cl,
+ };
+ args.SetBuffer(dataBuffers[temp], 0, 100);
+ args.Completed += SocketEvent_AsyncCompleted;
poolLock.ExitWriteLock();
_pool.Wait();
- args.RemoteEndPoint = cl;
Array.Copy(outputData, args.Buffer, outputData.Length);
bool sentAsync = false;
try
{
bool sendAsync = udpSock.SendToAsync(args);
- if (!sendAsync) CompletedSynchronousSocketEvent();
}
catch (SocketException /*ex*/) { }
catch (Exception /*ex*/) { }
finally
{
- if (!sentAsync) CompletedSynchronousSocketEvent();
+ if (!sentAsync) CompletedSynchronousSocketEvent(args);
}
}
}
diff --git a/HandheldCompanion/Devices/AOKZOE/AOKZOEA1.cs b/HandheldCompanion/Devices/AOKZOE/AOKZOEA1.cs
index c7a70a88e..85d6c3296 100644
--- a/HandheldCompanion/Devices/AOKZOE/AOKZOEA1.cs
+++ b/HandheldCompanion/Devices/AOKZOE/AOKZOEA1.cs
@@ -112,6 +112,21 @@ public override void Close()
ECRamDirectWrite(0x4F1, ECDetails, 0x00);
ECRamDirectWrite(0x4F2, ECDetails, 0x00);
base.Close();
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\u220C";
+ case ButtonFlags.OEM2:
+ return "\u2210";
+ case ButtonFlags.OEM3:
+ return "\u2211";
+ }
+
+ return defaultGlyph;
}
public override string GetGlyph(ButtonFlags button)
diff --git a/HandheldCompanion/Devices/ASUS/ROGAlly.cs b/HandheldCompanion/Devices/ASUS/ROGAlly.cs
index ceeaa5208..7e6c9f516 100644
--- a/HandheldCompanion/Devices/ASUS/ROGAlly.cs
+++ b/HandheldCompanion/Devices/ASUS/ROGAlly.cs
@@ -1,686 +1,688 @@
-using HandheldCompanion.Devices.ASUS;
-using HandheldCompanion.Inputs;
-using HandheldCompanion.Managers;
-using HandheldCompanion.Utils;
-using HidLibrary;
-using Nefarius.Utilities.DeviceManagement.PnP;
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Media;
-using WindowsInput.Events;
-using static HandheldCompanion.Utils.DeviceUtils;
-using Task = System.Threading.Tasks.Task;
-
-namespace HandheldCompanion.Devices;
-
-public class ROGAlly : IDevice
-{
- private readonly Dictionary keyMapping = new()
- {
- { 0, ButtonFlags.None },
- { 166, ButtonFlags.OEM1 },
- { 56, ButtonFlags.OEM2 },
- { 165, ButtonFlags.OEM3 },
- { 167, ButtonFlags.OEM4 },
- { 168, ButtonFlags.OEM4 },
- };
-
- private Dictionary hidDevices = new();
- private AsusACPI asusACPI;
-
- private const byte INPUT_HID_ID = 0x5a;
- private const byte AURA_HID_ID = 0x5d;
- private const int ASUS_ID = 0x0b05;
-
- public static readonly byte[] LED_INIT1 = new byte[] { AURA_HID_ID, 0xb9 };
- public static readonly byte[] LED_INIT2 = Encoding.ASCII.GetBytes("]ASUS Tech.Inc.");
- public static readonly byte[] LED_INIT3 = new byte[] { AURA_HID_ID, 0x05, 0x20, 0x31, 0, 0x1a };
- public static readonly byte[] LED_INIT4 = Encoding.ASCII.GetBytes("^ASUS Tech.Inc.");
- public static readonly byte[] LED_INIT5 = new byte[] { 0x5e, 0x05, 0x20, 0x31, 0, 0x1a };
-
- static byte[] MESSAGE_APPLY = { AURA_HID_ID, 0xb4 };
- static byte[] MESSAGE_SET = { AURA_HID_ID, 0xb5, 0, 0, 0 };
-
- public override bool IsOpen => hidDevices.ContainsKey(INPUT_HID_ID) && hidDevices[INPUT_HID_ID].IsOpen && asusACPI is not null && asusACPI.IsOpen();
-
- private enum AuraMode
- {
- SolidColor = 0,
- Breathing = 1,
- Wheel = 2,
- Rainbow = 3,
- Wave = 4,
- }
-
- private enum AuraSpeed
- {
- Slow = 0xeb,
- Medium = 0xf5,
- Fast = 0xe1,
- }
-
- private enum AuraDirection
- {
- Forward = 0,
- Reverse = 1,
- }
-
- private enum LEDZone
- {
- All = 0,
- JoystickLeftSideLeft = 1,
- JoystickLeftSideRight = 2,
- JoystickRightSideLeft = 3,
- JoystickRightSideRight = 4,
- }
-
- public ROGAlly()
- {
- // device specific settings
- ProductIllustration = "device_rog_ally";
-
- // used to monitor OEM specific inputs
- _vid = 0x0B05;
- _pid = 0x1ABE;
-
- // https://www.amd.com/en/products/apu/amd-ryzen-z1
- // https://www.amd.com/en/products/apu/amd-ryzen-z1-extreme
- // https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
- nTDP = new double[] { 15, 15, 20 };
- cTDP = new double[] { 5, 30 };
- GfxClock = new double[] { 100, 2700 };
- CpuClock = 5100;
-
- GyrometerAxis = new Vector3(-1.0f, 1.0f, 1.0f);
- GyrometerAxisSwap = new SortedDictionary
- {
- { 'X', 'X' },
- { 'Y', 'Z' },
- { 'Z', 'Y' }
- };
-
- AccelerometerAxis = new Vector3(1.0f, 1.0f, 1.0f);
- AccelerometerAxisSwap = new SortedDictionary
- {
- { 'X', 'X' },
- { 'Y', 'Z' },
- { 'Z', 'Y' }
- };
-
- // device specific capacities
- Capabilities |= DeviceCapabilities.FanControl;
- Capabilities |= DeviceCapabilities.DynamicLighting;
- Capabilities |= DeviceCapabilities.DynamicLightingBrightness;
-
- // dynamic lighting capacities
- DynamicLightingCapabilities |= LEDLevel.SolidColor;
- DynamicLightingCapabilities |= LEDLevel.Breathing;
- DynamicLightingCapabilities |= LEDLevel.Rainbow;
- // DynamicLightingCapabilities |= LEDLevel.Wave;
- DynamicLightingCapabilities |= LEDLevel.Wheel;
- DynamicLightingCapabilities |= LEDLevel.Ambilight;
-
- powerProfileQuiet = new(Properties.Resources.PowerProfileSilentName, Properties.Resources.PowerProfileSilentDescription)
- {
- Default = true,
- OEMPowerMode = (int)AsusMode.Silent,
- OSPowerMode = PowerMode.BetterBattery,
- Guid = PowerMode.BetterBattery
- };
-
- powerProfileBalanced = new(Properties.Resources.PowerProfilePerformanceName, Properties.Resources.PowerProfilePerformanceDescription)
- {
- Default = true,
- OEMPowerMode = (int)AsusMode.Performance,
- OSPowerMode = PowerMode.BetterPerformance,
- Guid = PowerMode.BetterPerformance
- };
-
- powerProfileCool = new(Properties.Resources.PowerProfileTurboName, Properties.Resources.PowerProfileTurboDescription)
- {
- Default = true,
- OEMPowerMode = (int)AsusMode.Turbo,
- OSPowerMode = PowerMode.BestPerformance,
- Guid = PowerMode.BestPerformance
- };
-
- OEMChords.Add(new DeviceChord("CC",
- new List(), new List(),
- false, ButtonFlags.OEM1
- ));
-
- OEMChords.Add(new DeviceChord("AC",
- new List(), new List(),
- false, ButtonFlags.OEM2
- ));
-
- // M1 and M2 do a repeating input when holding the button
- OEMChords.Add(new DeviceChord("M1",
- new List { KeyCode.F17 },
- new List { KeyCode.F17 },
- false, ButtonFlags.OEM3
- ));
-
- OEMChords.Add(new DeviceChord("M2",
- new List { KeyCode.F18 },
- new List { KeyCode.F18 },
- false, ButtonFlags.OEM4
- ));
- }
-
- private byte[] flushBufferWriteChanges = new byte[64]
- {
- 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] modeGame = new byte[64]
- {
- 0x5A, 0xD1, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] modeMouse = new byte[64]
- {
- 0x5A, 0xD1, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] dPadUpDownDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x01, 0x2C, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x88, 0x76, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] dPadLeftRightDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x02, 0x2C, 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0D, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] joySticksDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x03, 0x2C, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] shoulderButtonsDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x04, 0x2C, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] faceButtonsABDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x05, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] faceButtonsXYDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x06, 0x2C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] viewAndMenuDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x07, 0x2C, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] M1M2Default = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] M1F17M2F18 = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] triggersDefault = new byte[64]
- {
- 0x5A, 0xD1, 0x02, 0x09, 0x2C, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] commitReset1of4 = new byte[64]
- {
- 0x5A, 0xD1, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-
- };
-
- private byte[] commitReset2of4 = new byte[64]
- {
- 0x5A, 0xD1, 0x06, 0x02, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] commitReset3of4 = new byte[64]
- {
- 0x5A, 0xD1, 0x04, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- private byte[] commitReset4of4 = new byte[64]
- {
- 0x5A, 0xD1, 0x05, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
- public override bool Open()
- {
- var success = base.Open();
- if (!success)
- return false;
-
- // try open asus ACPI
- asusACPI = new AsusACPI();
- if (asusACPI is null)
- return false;
-
- // force M1/M2 to send F17 and F18
- ConfigureController(true);
-
- return true;
- }
-
- public override void Close()
- {
- // close Asus ACPI
- if (asusACPI is not null)
- asusACPI.Close();
-
- // restore default M1/M2 behavior
- ConfigureController(false);
-
- // close devices
- foreach (HidDevice hidDevice in hidDevices.Values)
- {
- if (!hidDevice.IsConnected)
- continue;
-
- if (hidDevice.IsOpen)
- {
- hidDevice.MonitorDeviceEvents = false;
- hidDevice.CloseDevice();
- }
- }
-
- base.Close();
- }
-
- public override bool IsReady()
- {
- IEnumerable devices = GetHidDevices(_vid, _pid);
- foreach (HidDevice device in devices)
- {
- if (!device.IsConnected)
- continue;
-
- if (device.ReadFeatureData(out byte[] data, INPUT_HID_ID))
- {
- device.OpenDevice();
- device.MonitorDeviceEvents = true;
-
- hidDevices[INPUT_HID_ID] = device;
-
- Task ReportDevice = Task.Run(async () => await device.ReadReportAsync());
- ReportDevice.ContinueWith(t => OnReport(ReportDevice.Result, device));
- }
- else if (device.ReadFeatureData(out data, AURA_HID_ID))
- {
- hidDevices[AURA_HID_ID] = device;
- }
- }
-
- hidDevices.TryGetValue(INPUT_HID_ID, out HidDevice hidDevice);
- if (hidDevice is null || !hidDevice.IsConnected)
- return false;
-
- PnPDevice pnpDevice = PnPDevice.GetDeviceByInterfaceId(hidDevice.DevicePath);
- string device_parent = pnpDevice.GetProperty(DevicePropertyKey.Device_Parent);
-
- PnPDevice pnpParent = PnPDevice.GetDeviceByInstanceId(device_parent);
- Guid parent_guid = pnpParent.GetProperty(DevicePropertyKey.Device_ClassGuid);
- string parent_instanceId = pnpParent.GetProperty(DevicePropertyKey.Device_InstanceId);
-
- return DeviceHelper.IsDeviceAvailable(parent_guid, parent_instanceId);
- }
-
- private void OnReport(HidReport result, HidDevice device)
- {
- Task ReportDevice = Task.Run(async () => await device.ReadReportAsync());
- ReportDevice.ContinueWith(t => OnReport(ReportDevice.Result, device));
-
- // get key
- byte key = result.Data[0];
- HandleEvent(key);
- }
-
- public override void SetFanControl(bool enable, int mode = 0)
- {
- if (!IsOpen)
- return;
-
- switch (enable)
- {
- case false:
- asusACPI.DeviceSet(AsusACPI.PerformanceMode, mode);
- return;
- }
- }
-
- public override void SetFanDuty(double percent)
- {
- if (!IsOpen)
- return;
-
- asusACPI.SetFanSpeed(AsusFan.CPU, Convert.ToByte(percent));
- asusACPI.SetFanSpeed(AsusFan.GPU, Convert.ToByte(percent));
- }
-
- public override float ReadFanDuty()
- {
- if (!IsOpen)
- return 100.0f;
-
- int cpuFan = asusACPI.DeviceGet(AsusACPI.CPU_Fan);
- int gpuFan = asusACPI.DeviceGet(AsusACPI.GPU_Fan);
- return (cpuFan + gpuFan) / 2 * 100;
- }
-
- public override void SetKeyPressDelay(HIDmode controllerMode)
- {
- switch (controllerMode)
- {
- case HIDmode.DualShock4Controller:
- KeyPressDelay = 180;
- break;
- default:
- KeyPressDelay = 20;
- break;
- }
- }
-
- private void HandleEvent(byte key)
- {
- if (!keyMapping.ContainsKey(key))
- return;
-
- // get button
- ButtonFlags button = keyMapping[key];
- switch (key)
- {
- case 167: // Armory crate: Hold
- KeyPress(button);
- break;
-
- case 168: // Armory crate: Hold, released
- KeyRelease(button);
- break;
-
- default:
- case 56: // Armory crate: Click
- case 166: // Command center: Click
- {
- Task.Factory.StartNew(async () =>
- {
- KeyPress(button);
- await Task.Delay(KeyPressDelay);
- KeyRelease(button);
- });
- }
- break;
- }
- }
-
- public override bool SetLedBrightness(int brightness)
- {
- //ROG ALly brightness range is: 0 - 3 range, 0 is off, convert from 0 - 100 % range
- brightness = (int)Math.Round(brightness / 33.33);
-
- if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
- {
- if (!hidDevice.IsConnected)
- return false;
-
- byte[] msg = { AURA_HID_ID, 0xba, 0xc5, 0xc4, (byte)brightness };
- return hidDevice.WriteFeatureData(msg);
- }
-
- return false;
- }
-
- public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
- {
- if (!DynamicLightingCapabilities.HasFlag(level))
- return false;
-
- // Apply the color for the left and right LED
- AuraMode auraMode = AuraMode.SolidColor;
-
- switch (level)
- {
- case LEDLevel.SolidColor:
- auraMode = AuraMode.SolidColor;
- break;
- case LEDLevel.Breathing:
- auraMode = AuraMode.Breathing;
- break;
- case LEDLevel.Rainbow:
- auraMode = AuraMode.Rainbow;
- break;
- case LEDLevel.Wave:
- auraMode = AuraMode.Wave;
- break;
- case LEDLevel.Wheel:
- auraMode = AuraMode.Wheel;
- break;
- case LEDLevel.Ambilight:
- return ApplyColorFast(MainColor, SecondaryColor);
- }
-
- AuraSpeed auraSpeed = AuraSpeed.Fast;
- if (speed <= 33)
- auraSpeed = AuraSpeed.Slow;
- else if (speed > 33 && speed <= 66)
- auraSpeed = AuraSpeed.Medium;
- else
- auraSpeed = AuraSpeed.Fast;
-
- return ApplyColor(auraMode, MainColor, SecondaryColor, auraSpeed);
- }
-
- private bool ApplyColor(AuraMode mode, Color MainColor, Color SecondaryColor, AuraSpeed speed = AuraSpeed.Slow, AuraDirection direction = AuraDirection.Forward)
- {
- if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
- {
- if (!hidDevice.IsConnected)
- return false;
-
- hidDevice.Write(AuraMessage(mode, MainColor, SecondaryColor, speed, LEDZone.All));
- hidDevice.Write(MESSAGE_APPLY);
- hidDevice.Write(MESSAGE_SET);
-
- return true;
- }
-
- return false;
- }
-
- private bool ApplyColorFast(Color MainColor, Color SecondaryColor)
- {
- if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
- {
- if (!hidDevice.IsConnected)
- return false;
-
- // Left joystick
- hidDevice.Write(AuraMessage(AuraMode.SolidColor, MainColor, MainColor, AuraSpeed.Slow, LEDZone.JoystickLeftSideLeft));
- hidDevice.Write(AuraMessage(AuraMode.SolidColor, MainColor, MainColor, AuraSpeed.Slow, LEDZone.JoystickLeftSideRight));
-
- // Right joystick
- hidDevice.Write(AuraMessage(AuraMode.SolidColor, SecondaryColor, SecondaryColor, AuraSpeed.Slow, LEDZone.JoystickRightSideLeft));
- hidDevice.Write(AuraMessage(AuraMode.SolidColor, SecondaryColor, SecondaryColor, AuraSpeed.Slow, LEDZone.JoystickRightSideRight));
-
- return true;
- }
-
- return false;
- }
-
- private static byte[] AuraMessage(AuraMode mode, Color LEDColor1, Color LEDColor2, AuraSpeed speed, LEDZone zone, LEDDirection direction = LEDDirection.Up)
- {
- byte[] msg = new byte[17];
- msg[0] = AURA_HID_ID;
- msg[1] = 0xb3;
- msg[2] = (byte)zone; // Zone
- msg[3] = (byte)mode; // Aura Mode
- msg[4] = LEDColor1.R; // R
- msg[5] = LEDColor1.G; // G
- msg[6] = LEDColor1.B; // B
- msg[7] = (byte)speed; // aura.speed as u8;
- msg[8] = (byte)direction; // aura.direction as u8;
- msg[9] = (mode == AuraMode.Breathing) ? (byte)1 : (byte)0;
- msg[10] = LEDColor2.R; // R
- msg[11] = LEDColor2.G; // G
- msg[12] = LEDColor2.B; // B
- return msg;
- }
-
- public override string GetGlyph(ButtonFlags button)
- {
- switch (button)
- {
- case ButtonFlags.OEM1:
- return "\uE006";
- case ButtonFlags.OEM2:
- return "\uE005";
- case ButtonFlags.OEM3:
- return "\u2212";
- case ButtonFlags.OEM4:
- return "\u2213";
- }
-
- return defaultGlyph;
- }
-
- private void ConfigureController(bool Remap)
- {
- /*
- Generic function
- 23 HID commands of 64 bytes each
-
- 1. Mode
- 2. Flush buffer, write changes
- 3. DPad up and down
- 4. Flush buffer, write changes
- 5. DPad left and right
- 6. Flush buffer, write changes
- 7. JoysSticks
- 8. Flush buffer, write changes
- 9. Shoulder buttons
- 10. Flush buffer, write changes
- 11. AB Facebuttons
- 12. Flush buffer, write changes
- 13. XY Facebuttons
- 14. Flush buffer, write changes
- 15. View and menu
- 16. Flush buffer, write changes
- 17. M1 and M2
- 18. Flush buffer, write changes
- 19. Triggers
- 20. Commit and reset 1 of 4
- 21. Commit and reset 2 of 4
- 22. Commit and reset 3 of 4
- 23. Commit and reset 4 of 4
- */
-
- SendHidControlWrite(modeGame); // 1
- SendHidControlWrite(flushBufferWriteChanges); // 2
-
- SendHidControlWrite(dPadUpDownDefault); // 3
- SendHidControlWrite(flushBufferWriteChanges); // 4
-
- SendHidControlWrite(dPadLeftRightDefault); // 5
- SendHidControlWrite(flushBufferWriteChanges); // 6
-
- SendHidControlWrite(joySticksDefault); // 7
- SendHidControlWrite(flushBufferWriteChanges); // 8
-
- SendHidControlWrite(shoulderButtonsDefault); // 9
- SendHidControlWrite(flushBufferWriteChanges); // 10
-
- SendHidControlWrite(faceButtonsABDefault); // 11
- SendHidControlWrite(flushBufferWriteChanges); // 12
-
- SendHidControlWrite(faceButtonsXYDefault); // 13
- SendHidControlWrite(flushBufferWriteChanges); // 14
-
- SendHidControlWrite(viewAndMenuDefault); // 15
- SendHidControlWrite(flushBufferWriteChanges); // 16
-
- // Choose the appropriate mapping based on the 'Remap' flag
- SendHidControlWrite(Remap ? M1F17M2F18 : M1M2Default); // Step 17
-
- SendHidControlWrite(flushBufferWriteChanges); // 18
-
- SendHidControlWrite(triggersDefault); // 19
-
- SendHidControlWrite(commitReset1of4); // 20
- SendHidControlWrite(commitReset2of4); // 21
- SendHidControlWrite(commitReset3of4); // 22
- SendHidControlWrite(commitReset4of4); // 23
- }
-
- public void SendHidControlWrite(byte[] data)
- {
- if (hidDevices.TryGetValue(INPUT_HID_ID, out HidDevice device))
- {
- if (device.IsConnected)
- device.WriteFeatureData(data);
- }
-
- }
+using HandheldCompanion.Devices.ASUS;
+using HandheldCompanion.Inputs;
+using HandheldCompanion.Managers;
+using HandheldCompanion.Utils;
+using HidLibrary;
+using Nefarius.Utilities.DeviceManagement.PnP;
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using WindowsInput.Events;
+using static HandheldCompanion.Utils.DeviceUtils;
+using Task = System.Threading.Tasks.Task;
+
+namespace HandheldCompanion.Devices;
+
+public class ROGAlly : IDevice
+{
+ private readonly Dictionary keyMapping = new()
+ {
+ { 0, ButtonFlags.None },
+ { 166, ButtonFlags.OEM1 },
+ { 56, ButtonFlags.OEM2 },
+ { 165, ButtonFlags.OEM3 },
+ { 167, ButtonFlags.OEM4 },
+ { 168, ButtonFlags.OEM4 },
+ };
+
+ private Dictionary hidDevices = new();
+ private AsusACPI asusACPI;
+
+ private const byte INPUT_HID_ID = 0x5a;
+ private const byte AURA_HID_ID = 0x5d;
+ private const int ASUS_ID = 0x0b05;
+
+ public static readonly byte[] LED_INIT1 = new byte[] { AURA_HID_ID, 0xb9 };
+ public static readonly byte[] LED_INIT2 = Encoding.ASCII.GetBytes("]ASUS Tech.Inc.");
+ public static readonly byte[] LED_INIT3 = new byte[] { AURA_HID_ID, 0x05, 0x20, 0x31, 0, 0x1a };
+ public static readonly byte[] LED_INIT4 = Encoding.ASCII.GetBytes("^ASUS Tech.Inc.");
+ public static readonly byte[] LED_INIT5 = new byte[] { 0x5e, 0x05, 0x20, 0x31, 0, 0x1a };
+
+ static byte[] MESSAGE_APPLY = { AURA_HID_ID, 0xb4 };
+ static byte[] MESSAGE_SET = { AURA_HID_ID, 0xb5, 0, 0, 0 };
+
+ public override bool IsOpen => hidDevices.ContainsKey(INPUT_HID_ID) && hidDevices[INPUT_HID_ID].IsOpen && asusACPI is not null && asusACPI.IsOpen();
+
+ private enum AuraMode
+ {
+ SolidColor = 0,
+ Breathing = 1,
+ Wheel = 2,
+ Rainbow = 3,
+ Wave = 4,
+ }
+
+ private enum AuraSpeed
+ {
+ Slow = 0xeb,
+ Medium = 0xf5,
+ Fast = 0xe1,
+ }
+
+ private enum AuraDirection
+ {
+ Forward = 0,
+ Reverse = 1,
+ }
+
+ private enum LEDZone
+ {
+ All = 0,
+ JoystickLeftSideLeft = 1,
+ JoystickLeftSideRight = 2,
+ JoystickRightSideLeft = 3,
+ JoystickRightSideRight = 4,
+ }
+
+ public ROGAlly()
+ {
+ // device specific settings
+ ProductIllustration = "device_rog_ally";
+
+ // used to monitor OEM specific inputs
+ _vid = 0x0B05;
+ _pid = 0x1ABE;
+
+ // https://www.amd.com/en/products/apu/amd-ryzen-z1
+ // https://www.amd.com/en/products/apu/amd-ryzen-z1-extreme
+ // https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
+ nTDP = new double[] { 15, 15, 20 };
+ cTDP = new double[] { 5, 30 };
+ GfxClock = new double[] { 100, 2700 };
+ CpuClock = 5100;
+
+ GyrometerAxis = new Vector3(-1.0f, 1.0f, 1.0f);
+ GyrometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'X' },
+ { 'Y', 'Z' },
+ { 'Z', 'Y' }
+ };
+
+ AccelerometerAxis = new Vector3(1.0f, 1.0f, 1.0f);
+ AccelerometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'X' },
+ { 'Y', 'Z' },
+ { 'Z', 'Y' }
+ };
+
+ // device specific capacities
+ Capabilities |= DeviceCapabilities.FanControl;
+ Capabilities |= DeviceCapabilities.DynamicLighting;
+ Capabilities |= DeviceCapabilities.DynamicLightingBrightness;
+
+ // dynamic lighting capacities
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
+ DynamicLightingCapabilities |= LEDLevel.Breathing;
+ DynamicLightingCapabilities |= LEDLevel.Rainbow;
+ DynamicLightingCapabilities |= LEDLevel.Wheel;
+ DynamicLightingCapabilities |= LEDLevel.Ambilight;
+
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileROGAllySilentName, Properties.Resources.PowerProfileROGAllySilentDescription)
+ {
+ Default = true,
+ DeviceDefault = true,
+ OEMPowerMode = (int)AsusMode.Silent,
+ OSPowerMode = OSPowerMode.BetterBattery,
+ Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a")
+ });
+
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileROGAllyPerformanceName, Properties.Resources.PowerProfileROGAllyPerformanceDescription)
+ {
+ Default = true,
+ DeviceDefault = true,
+ OEMPowerMode = (int)AsusMode.Performance,
+ OSPowerMode = OSPowerMode.BetterPerformance,
+ Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f")
+ });
+
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileROGAllyTurboName, Properties.Resources.PowerProfileROGAllyTurboDescription)
+ {
+ Default = true,
+ DeviceDefault = true,
+ OEMPowerMode = (int)AsusMode.Turbo,
+ OSPowerMode = OSPowerMode.BestPerformance,
+ Guid = new("ded574b5-45a0-4f42-8737-46345c09c238")
+ });
+
+ OEMChords.Add(new DeviceChord("CC",
+ new List(), new List(),
+ false, ButtonFlags.OEM1
+ ));
+
+ OEMChords.Add(new DeviceChord("AC",
+ new List(), new List(),
+ false, ButtonFlags.OEM2
+ ));
+
+ // M1 and M2 do a repeating input when holding the button
+ OEMChords.Add(new DeviceChord("M1",
+ new List { KeyCode.F17 },
+ new List { KeyCode.F17 },
+ false, ButtonFlags.OEM3
+ ));
+
+ OEMChords.Add(new DeviceChord("M2",
+ new List { KeyCode.F18 },
+ new List { KeyCode.F18 },
+ false, ButtonFlags.OEM4
+ ));
+ }
+
+ private byte[] flushBufferWriteChanges = new byte[64]
+ {
+ 0x5A, 0xD1, 0x0A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] modeGame = new byte[64]
+ {
+ 0x5A, 0xD1, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] modeMouse = new byte[64]
+ {
+ 0x5A, 0xD1, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] dPadUpDownDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x01, 0x2C, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x8C, 0x88, 0x76, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] dPadLeftRightDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x02, 0x2C, 0x01, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x23, 0x00, 0x00, 0x00, 0x01, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x0D, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] joySticksDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x03, 0x2C, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] shoulderButtonsDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x04, 0x2C, 0x01, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] faceButtonsABDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x05, 0x2C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x31, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] faceButtonsXYDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x06, 0x2C, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x82, 0x4D, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] viewAndMenuDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x07, 0x2C, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] M1M2Default = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x8F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] M1F17M2F18 = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x08, 0x2C, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x30, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] triggersDefault = new byte[64]
+ {
+ 0x5A, 0xD1, 0x02, 0x09, 0x2C, 0x01, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0E, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] commitReset1of4 = new byte[64]
+ {
+ 0x5A, 0xD1, 0x0F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+ };
+
+ private byte[] commitReset2of4 = new byte[64]
+ {
+ 0x5A, 0xD1, 0x06, 0x02, 0x64, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] commitReset3of4 = new byte[64]
+ {
+ 0x5A, 0xD1, 0x04, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ private byte[] commitReset4of4 = new byte[64]
+ {
+ 0x5A, 0xD1, 0x05, 0x04, 0x00, 0x64, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ public override bool Open()
+ {
+ var success = base.Open();
+ if (!success)
+ return false;
+
+ // try open asus ACPI
+ asusACPI = new AsusACPI();
+ if (asusACPI is null)
+ return false;
+
+ // force M1/M2 to send F17 and F18
+ ConfigureController(true);
+
+ return true;
+ }
+
+ public override void Close()
+ {
+ // close Asus ACPI
+ if (asusACPI is not null)
+ asusACPI.Close();
+
+ // restore default M1/M2 behavior
+ ConfigureController(false);
+
+ // close devices
+ foreach (HidDevice hidDevice in hidDevices.Values)
+ {
+ if (!hidDevice.IsConnected)
+ continue;
+
+ if (hidDevice.IsOpen)
+ {
+ hidDevice.MonitorDeviceEvents = false;
+ hidDevice.CloseDevice();
+ }
+ }
+
+ base.Close();
+ }
+
+ public override bool IsReady()
+ {
+ IEnumerable devices = GetHidDevices(_vid, _pid);
+ foreach (HidDevice device in devices)
+ {
+ if (!device.IsConnected)
+ continue;
+
+ if (device.ReadFeatureData(out byte[] data, INPUT_HID_ID))
+ {
+ device.OpenDevice();
+ device.MonitorDeviceEvents = true;
+
+ hidDevices[INPUT_HID_ID] = device;
+
+ Task ReportDevice = Task.Run(async () => await device.ReadReportAsync());
+ ReportDevice.ContinueWith(t => OnReport(ReportDevice.Result, device));
+ }
+ else if (device.ReadFeatureData(out data, AURA_HID_ID))
+ {
+ hidDevices[AURA_HID_ID] = device;
+ }
+ }
+
+ hidDevices.TryGetValue(INPUT_HID_ID, out HidDevice hidDevice);
+ if (hidDevice is null || !hidDevice.IsConnected)
+ return false;
+
+ PnPDevice pnpDevice = PnPDevice.GetDeviceByInterfaceId(hidDevice.DevicePath);
+ string device_parent = pnpDevice.GetProperty(DevicePropertyKey.Device_Parent);
+
+ PnPDevice pnpParent = PnPDevice.GetDeviceByInstanceId(device_parent);
+ Guid parent_guid = pnpParent.GetProperty(DevicePropertyKey.Device_ClassGuid);
+ string parent_instanceId = pnpParent.GetProperty(DevicePropertyKey.Device_InstanceId);
+
+ return DeviceHelper.IsDeviceAvailable(parent_guid, parent_instanceId);
+ }
+
+ private void OnReport(HidReport result, HidDevice device)
+ {
+ Task ReportDevice = Task.Run(async () => await device.ReadReportAsync());
+ ReportDevice.ContinueWith(t => OnReport(ReportDevice.Result, device));
+
+ // get key
+ byte key = result.Data[0];
+ HandleEvent(key);
+ }
+
+ public override void SetFanControl(bool enable, int mode = 0)
+ {
+ if (!IsOpen)
+ return;
+
+ switch (enable)
+ {
+ case false:
+ asusACPI.DeviceSet(AsusACPI.PerformanceMode, mode);
+ return;
+ }
+ }
+
+ public override void SetFanDuty(double percent)
+ {
+ if (!IsOpen)
+ return;
+
+ asusACPI.SetFanSpeed(AsusFan.CPU, Convert.ToByte(percent));
+ asusACPI.SetFanSpeed(AsusFan.GPU, Convert.ToByte(percent));
+ }
+
+ public override float ReadFanDuty()
+ {
+ if (!IsOpen)
+ return 100.0f;
+
+ int cpuFan = asusACPI.DeviceGet(AsusACPI.CPU_Fan);
+ int gpuFan = asusACPI.DeviceGet(AsusACPI.GPU_Fan);
+ return (cpuFan + gpuFan) / 2 * 100;
+ }
+
+ public override void SetKeyPressDelay(HIDmode controllerMode)
+ {
+ switch (controllerMode)
+ {
+ case HIDmode.DualShock4Controller:
+ KeyPressDelay = 180;
+ break;
+ default:
+ KeyPressDelay = 20;
+ break;
+ }
+ }
+
+ private void HandleEvent(byte key)
+ {
+ if (!keyMapping.ContainsKey(key))
+ return;
+
+ // get button
+ ButtonFlags button = keyMapping[key];
+ switch (key)
+ {
+ case 167: // Armory crate: Hold
+ KeyPress(button);
+ break;
+
+ case 168: // Armory crate: Hold, released
+ KeyRelease(button);
+ break;
+
+ default:
+ case 56: // Armory crate: Click
+ case 166: // Command center: Click
+ {
+ Task.Factory.StartNew(async () =>
+ {
+ KeyPress(button);
+ await Task.Delay(KeyPressDelay);
+ KeyRelease(button);
+ });
+ }
+ break;
+ }
+ }
+
+ public override bool SetLedBrightness(int brightness)
+ {
+ //ROG ALly brightness range is: 0 - 3 range, 0 is off, convert from 0 - 100 % range
+ brightness = (int)Math.Round(brightness / 33.33);
+
+ if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
+ {
+ if (!hidDevice.IsConnected)
+ return false;
+
+ byte[] msg = { AURA_HID_ID, 0xba, 0xc5, 0xc4, (byte)brightness };
+ return hidDevice.WriteFeatureData(msg);
+ }
+
+ return false;
+ }
+
+ public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
+ {
+ if (!DynamicLightingCapabilities.HasFlag(level))
+ return false;
+
+ // Apply the color for the left and right LED
+ AuraMode auraMode = AuraMode.SolidColor;
+
+ switch (level)
+ {
+ case LEDLevel.SolidColor:
+ auraMode = AuraMode.SolidColor;
+ break;
+ case LEDLevel.Breathing:
+ auraMode = AuraMode.Breathing;
+ break;
+ case LEDLevel.Rainbow:
+ auraMode = AuraMode.Rainbow;
+ break;
+ case LEDLevel.Wave:
+ auraMode = AuraMode.Wave;
+ break;
+ case LEDLevel.Wheel:
+ auraMode = AuraMode.Wheel;
+ break;
+ case LEDLevel.Ambilight:
+ return ApplyColorFast(MainColor, SecondaryColor);
+ }
+
+ AuraSpeed auraSpeed = AuraSpeed.Fast;
+ if (speed <= 33)
+ auraSpeed = AuraSpeed.Slow;
+ else if (speed > 33 && speed <= 66)
+ auraSpeed = AuraSpeed.Medium;
+ else
+ auraSpeed = AuraSpeed.Fast;
+
+ return ApplyColor(auraMode, MainColor, SecondaryColor, auraSpeed);
+ }
+
+ private bool ApplyColor(AuraMode mode, Color MainColor, Color SecondaryColor, AuraSpeed speed = AuraSpeed.Slow, AuraDirection direction = AuraDirection.Forward)
+ {
+ if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
+ {
+ if (!hidDevice.IsConnected)
+ return false;
+
+ hidDevice.Write(AuraMessage(mode, MainColor, SecondaryColor, speed, LEDZone.All));
+ hidDevice.Write(MESSAGE_APPLY);
+ hidDevice.Write(MESSAGE_SET);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private bool ApplyColorFast(Color MainColor, Color SecondaryColor)
+ {
+ if (hidDevices.TryGetValue(AURA_HID_ID, out HidDevice hidDevice))
+ {
+ if (!hidDevice.IsConnected)
+ return false;
+
+ // Left joystick
+ hidDevice.Write(AuraMessage(AuraMode.SolidColor, MainColor, MainColor, AuraSpeed.Slow, LEDZone.JoystickLeftSideLeft));
+ hidDevice.Write(AuraMessage(AuraMode.SolidColor, MainColor, MainColor, AuraSpeed.Slow, LEDZone.JoystickLeftSideRight));
+
+ // Right joystick
+ hidDevice.Write(AuraMessage(AuraMode.SolidColor, SecondaryColor, SecondaryColor, AuraSpeed.Slow, LEDZone.JoystickRightSideLeft));
+ hidDevice.Write(AuraMessage(AuraMode.SolidColor, SecondaryColor, SecondaryColor, AuraSpeed.Slow, LEDZone.JoystickRightSideRight));
+
+ return true;
+ }
+
+ return false;
+ }
+
+ private static byte[] AuraMessage(AuraMode mode, Color LEDColor1, Color LEDColor2, AuraSpeed speed, LEDZone zone, LEDDirection direction = LEDDirection.Up)
+ {
+ byte[] msg = new byte[17];
+ msg[0] = AURA_HID_ID;
+ msg[1] = 0xb3;
+ msg[2] = (byte)zone; // Zone
+ msg[3] = (byte)mode; // Aura Mode
+ msg[4] = LEDColor1.R; // R
+ msg[5] = LEDColor1.G; // G
+ msg[6] = LEDColor1.B; // B
+ msg[7] = (byte)speed; // aura.speed as u8;
+ msg[8] = (byte)direction; // aura.direction as u8;
+ msg[9] = (mode == AuraMode.Breathing) ? (byte)1 : (byte)0;
+ msg[10] = LEDColor2.R; // R
+ msg[11] = LEDColor2.G; // G
+ msg[12] = LEDColor2.B; // B
+ return msg;
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\uE006";
+ case ButtonFlags.OEM2:
+ return "\uE005";
+ case ButtonFlags.OEM3:
+ return "\u2212";
+ case ButtonFlags.OEM4:
+ return "\u2213";
+ }
+
+ return defaultGlyph;
+ }
+
+ private void ConfigureController(bool Remap)
+ {
+ /*
+ Generic function
+ 23 HID commands of 64 bytes each
+
+ 1. Mode
+ 2. Flush buffer, write changes
+ 3. DPad up and down
+ 4. Flush buffer, write changes
+ 5. DPad left and right
+ 6. Flush buffer, write changes
+ 7. JoysSticks
+ 8. Flush buffer, write changes
+ 9. Shoulder buttons
+ 10. Flush buffer, write changes
+ 11. AB Facebuttons
+ 12. Flush buffer, write changes
+ 13. XY Facebuttons
+ 14. Flush buffer, write changes
+ 15. View and menu
+ 16. Flush buffer, write changes
+ 17. M1 and M2
+ 18. Flush buffer, write changes
+ 19. Triggers
+ 20. Commit and reset 1 of 4
+ 21. Commit and reset 2 of 4
+ 22. Commit and reset 3 of 4
+ 23. Commit and reset 4 of 4
+ */
+
+ SendHidControlWrite(modeGame); // 1
+ SendHidControlWrite(flushBufferWriteChanges); // 2
+
+ SendHidControlWrite(dPadUpDownDefault); // 3
+ SendHidControlWrite(flushBufferWriteChanges); // 4
+
+ SendHidControlWrite(dPadLeftRightDefault); // 5
+ SendHidControlWrite(flushBufferWriteChanges); // 6
+
+ SendHidControlWrite(joySticksDefault); // 7
+ SendHidControlWrite(flushBufferWriteChanges); // 8
+
+ SendHidControlWrite(shoulderButtonsDefault); // 9
+ SendHidControlWrite(flushBufferWriteChanges); // 10
+
+ SendHidControlWrite(faceButtonsABDefault); // 11
+ SendHidControlWrite(flushBufferWriteChanges); // 12
+
+ SendHidControlWrite(faceButtonsXYDefault); // 13
+ SendHidControlWrite(flushBufferWriteChanges); // 14
+
+ SendHidControlWrite(viewAndMenuDefault); // 15
+ SendHidControlWrite(flushBufferWriteChanges); // 16
+
+ // Choose the appropriate mapping based on the 'Remap' flag
+ SendHidControlWrite(Remap ? M1F17M2F18 : M1M2Default); // Step 17
+
+ SendHidControlWrite(flushBufferWriteChanges); // 18
+
+ SendHidControlWrite(triggersDefault); // 19
+
+ SendHidControlWrite(commitReset1of4); // 20
+ SendHidControlWrite(commitReset2of4); // 21
+ SendHidControlWrite(commitReset3of4); // 22
+ SendHidControlWrite(commitReset4of4); // 23
+ }
+
+ public void SendHidControlWrite(byte[] data)
+ {
+ if (hidDevices.TryGetValue(INPUT_HID_ID, out HidDevice device))
+ {
+ if (device.IsConnected)
+ device.WriteFeatureData(data);
+ }
+
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEO2.cs b/HandheldCompanion/Devices/AYANEO/AYANEO2.cs
index 73a4ce119..77c6ad751 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEO2.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEO2.cs
@@ -1,9 +1,9 @@
-using HandheldCompanion.Inputs;
+using HandheldCompanion.Inputs;
using System.Collections.Generic;
using System.Numerics;
-using WindowsInput.Events;
-
+using WindowsInput.Events;
namespace HandheldCompanion.Devices;
+using static HandheldCompanion.Utils.DeviceUtils;
public class AYANEO2 : AYANEO.AYANEODevice
{
@@ -16,7 +16,7 @@ public AYANEO2()
// https://www.amd.com/en/products/apu/amd-ryzen-7-6800u
nTDP = new double[] { 15, 15, 20 };
cTDP = new double[] { 3, 33 };
- GfxClock = new double[] { 100, 2200 };
+ GfxClock = new double[] { 100, 2200 };
CpuClock = 4700;
GyrometerAxis = new Vector3(1.0f, 1.0f, 1.0f);
@@ -36,8 +36,9 @@ public AYANEO2()
};
// device specific capacities
- Capabilities = DeviceCapabilities.FanControl;
+ Capabilities = DeviceCapabilities.FanControl;
Capabilities |= DeviceCapabilities.DynamicLighting;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
ECDetails = new ECDetails
{
@@ -72,7 +73,7 @@ public AYANEO2()
new List { KeyCode.LWin, KeyCode.D },
false, ButtonFlags.OEM2
));
- }
+ }
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEO2021.cs b/HandheldCompanion/Devices/AYANEO/AYANEO2021.cs
index d75f622b3..e77a7c023 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEO2021.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEO2021.cs
@@ -53,6 +53,21 @@ public AYANEO2021()
new List { KeyCode.O, KeyCode.LWin, KeyCode.RControlKey },
false, ButtonFlags.OEM3
));
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\uE008";
+ case ButtonFlags.OEM2:
+ return "\u242F";
+ case ButtonFlags.OEM3:
+ return "\u243D";
+ }
+
+ return defaultGlyph;
}
public override string GetGlyph(ButtonFlags button)
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEOAIR.cs b/HandheldCompanion/Devices/AYANEO/AYANEOAIR.cs
index d07c76d40..90dace153 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEOAIR.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEOAIR.cs
@@ -1,8 +1,9 @@
using HandheldCompanion.Inputs;
using System.Collections.Generic;
using System.Numerics;
-using WindowsInput.Events;
+using WindowsInput.Events;
namespace HandheldCompanion.Devices;
+using static HandheldCompanion.Utils.DeviceUtils;
public class AYANEOAIR : AYANEO.AYANEODevice
{
@@ -15,7 +16,7 @@ public AYANEOAIR()
// https://www.amd.com/en/products/apu/amd-ryzen-5-5560u
nTDP = new double[] { 12, 12, 15 };
cTDP = new double[] { 3, 15 };
- GfxClock = new double[] { 100, 1600 };
+ GfxClock = new double[] { 100, 1600 };
CpuClock = 4000;
GyrometerAxisSwap = new SortedDictionary
@@ -36,6 +37,7 @@ public AYANEOAIR()
// device specific capacities
Capabilities = DeviceCapabilities.FanControl;
Capabilities |= DeviceCapabilities.DynamicLighting;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
ECDetails = new ECDetails
{
@@ -70,8 +72,8 @@ public AYANEOAIR()
new List { KeyCode.LWin, KeyCode.D },
false, ButtonFlags.OEM2
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEOAIRPlus.cs b/HandheldCompanion/Devices/AYANEO/AYANEOAIRPlus.cs
index feed5d1cb..320d36b75 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEOAIRPlus.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEOAIRPlus.cs
@@ -1,10 +1,10 @@
-using HandheldCompanion.Devices.AYANEO;
+using HandheldCompanion.Devices.AYANEO;
using HandheldCompanion.Inputs;
-using System;
+using System;
using System.Collections.Generic;
using System.Numerics;
using System.Windows.Media;
-using WindowsInput.Events;
+using WindowsInput.Events;
using static HandheldCompanion.Utils.DeviceUtils;
namespace HandheldCompanion.Devices;
@@ -35,20 +35,20 @@ public AYANEOAIRPlus()
// device specific capacities
// todo, missing fan control
- Capabilities |= DeviceCapabilities.DynamicLighting;
- DynamicLightingCapabilities |= LEDLevel.SolidColor;
- DynamicLightingCapabilities |= LEDLevel.Ambilight;
-
- // Ayaneo Air Plus info based on:
- // https://github.com/JustEnoughLinuxOS/distribution/blob/main/packages/hardware/quirks/devices/AYANEO%20AIR%20Plus/bin/ledcontrol
- ECDetails = new ECDetails
- {
- AddressStatusCommandPort = 0x4E,
- AddressDataPort = 0x4F,
- AddressFanControl = 0x0, // Unknown
- AddressFanDuty = 0x0, // Unknown
- FanValueMin = 0, // Unknown
- FanValueMax = 100 // Unknown
+ Capabilities |= DeviceCapabilities.DynamicLighting;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
+ DynamicLightingCapabilities |= LEDLevel.Ambilight;
+
+ // Ayaneo Air Plus info based on:
+ // https://github.com/JustEnoughLinuxOS/distribution/blob/main/packages/hardware/quirks/devices/AYANEO%20AIR%20Plus/bin/ledcontrol
+ ECDetails = new ECDetails
+ {
+ AddressStatusCommandPort = 0x4E,
+ AddressDataPort = 0x4F,
+ AddressFanControl = 0x0, // Unknown
+ AddressFanDuty = 0x0, // Unknown
+ FanValueMin = 0, // Unknown
+ FanValueMax = 100 // Unknown
};
OEMChords.Add(new DeviceChord("Custom Key Top Right",
@@ -74,8 +74,8 @@ public AYANEOAIRPlus()
new List { KeyCode.D, KeyCode.LWin },
false, ButtonFlags.OEM2
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
@@ -93,241 +93,241 @@ public override string GetGlyph(ButtonFlags button)
return defaultGlyph;
}
- private void LedOpen()
- {
- ECRamDirectWrite(0x87, ECDetails, 0xA5);
- }
-
- private void LedClose(byte param)
- {
- ECRamDirectWrite(param, ECDetails, 0x01);
- }
-
- private void LedAck()
- {
- ECRamDirectWrite(0x70, ECDetails, 0x00);
- LedClose(0x86);
- }
-
- private void LedEnable()
- {
- // Set LED ON
- LedState(0x37);
-
- LedOpen();
- ECRamDirectWrite(0x70, ECDetails, 0x00);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0xB2, ECDetails, 0xBA);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x72, ECDetails, 0xBA);
- LedClose(0x86);
-
- LedAck();
+ private void LedOpen()
+ {
+ ECRamDirectWrite(0x87, ECDetails, 0xA5);
+ }
+
+ private void LedClose(byte param)
+ {
+ ECRamDirectWrite(param, ECDetails, 0x01);
+ }
+
+ private void LedAck()
+ {
+ ECRamDirectWrite(0x70, ECDetails, 0x00);
+ LedClose(0x86);
}
- private void LedDisable()
- {
- // Set LED OFF
- LedState(0x31);
+ private void LedEnable()
+ {
+ // Set LED ON
+ LedState(0x37);
+
+ LedOpen();
+ ECRamDirectWrite(0x70, ECDetails, 0x00);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0xB2, ECDetails, 0xBA);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x72, ECDetails, 0xBA);
+ LedClose(0x86);
+
+ LedAck();
}
- private void LedApply()
- {
- LedOpen();
- ECRamDirectWrite(0xBF, ECDetails, 0x00);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x7F, ECDetails, 0x00);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0xC0, ECDetails, 0x00);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x80, ECDetails, 0x00);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0xC1, ECDetails, 0x05);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x81, ECDetails, 0x05);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0xC2, ECDetails, 0x05);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x82, ECDetails, 0x05);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0xC3, ECDetails, 0x05);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0x83, ECDetails, 0x05);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0xC4, ECDetails, 0x05);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x84, ECDetails, 0x05);
- LedClose(0x86);
-
- LedOpen();
- ECRamDirectWrite(0xC5, ECDetails, 0x07);
- LedClose(0xC6);
-
- LedOpen();
- ECRamDirectWrite(0x85, ECDetails, 0x07);
- LedClose(0x86);
-
- LedAck();
+ private void LedDisable()
+ {
+ // Set LED OFF
+ LedState(0x31);
}
- private void LedState(byte value)
- {
- // 0x31 = off
- // 0x37 = on
- byte[] zones = { 0xB2, 0x72 };
-
- LedOpen();
- foreach (byte zone in zones)
- {
- ECRamDirectWrite(zone, ECDetails, value);
- ECRamDirectWrite(0xC6, ECDetails, 0x01);
- }
- LedAck();
- }
-
- private void SetLEDColorL(Color color)
- {
- byte red = color.R;
- byte green = color.G;
- byte blue = color.B;
-
- LedOpen();
- for (byte i = 0xB3; i <= 0xBC; i += 3)
- {
- ECRamDirectWrite(i, ECDetails, red);
- ECRamDirectWrite((byte)(i + 1), ECDetails, green);
- ECRamDirectWrite((byte)(i + 2), ECDetails, blue);
- }
- LedAck();
- }
-
- private void SetLEDColorR(Color color)
- {
- byte red = color.R;
- byte green = color.G;
- byte blue = color.B;
-
- LedOpen();
- for (byte i = 0x73; i <= 0x7C; i += 3)
- {
- ECRamDirectWrite(i, ECDetails, red);
- ECRamDirectWrite((byte)(i + 1), ECDetails, green);
- ECRamDirectWrite((byte)(i + 2), ECDetails, blue);
- }
- LedAck();
- }
-
- private void SetLEDColor(Color color)
- {
- SetLEDColorL(color);
- SetLEDColorR(color);
- }
-
- public override bool ECRamDirectWrite(ushort address, ECDetails details, byte data)
- {
- ushort address2 = BitConverter.ToUInt16(new byte[] { (byte)address, 0xD1 }, 0);
- return base.ECRamDirectWrite(address2, details, data);
+ private void LedApply()
+ {
+ LedOpen();
+ ECRamDirectWrite(0xBF, ECDetails, 0x00);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x7F, ECDetails, 0x00);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0xC0, ECDetails, 0x00);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x80, ECDetails, 0x00);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0xC1, ECDetails, 0x05);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x81, ECDetails, 0x05);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0xC2, ECDetails, 0x05);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x82, ECDetails, 0x05);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0xC3, ECDetails, 0x05);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0x83, ECDetails, 0x05);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0xC4, ECDetails, 0x05);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x84, ECDetails, 0x05);
+ LedClose(0x86);
+
+ LedOpen();
+ ECRamDirectWrite(0xC5, ECDetails, 0x07);
+ LedClose(0xC6);
+
+ LedOpen();
+ ECRamDirectWrite(0x85, ECDetails, 0x07);
+ LedClose(0x86);
+
+ LedAck();
}
+ private void LedState(byte value)
+ {
+ // 0x31 = off
+ // 0x37 = on
+ byte[] zones = { 0xB2, 0x72 };
+
+ LedOpen();
+ foreach (byte zone in zones)
+ {
+ ECRamDirectWrite(zone, ECDetails, value);
+ ECRamDirectWrite(0xC6, ECDetails, 0x01);
+ }
+ LedAck();
+ }
+
+ private void SetLEDColorL(Color color)
+ {
+ byte red = color.R;
+ byte green = color.G;
+ byte blue = color.B;
+
+ LedOpen();
+ for (byte i = 0xB3; i <= 0xBC; i += 3)
+ {
+ ECRamDirectWrite(i, ECDetails, red);
+ ECRamDirectWrite((byte)(i + 1), ECDetails, green);
+ ECRamDirectWrite((byte)(i + 2), ECDetails, blue);
+ }
+ LedAck();
+ }
+
+ private void SetLEDColorR(Color color)
+ {
+ byte red = color.R;
+ byte green = color.G;
+ byte blue = color.B;
+
+ LedOpen();
+ for (byte i = 0x73; i <= 0x7C; i += 3)
+ {
+ ECRamDirectWrite(i, ECDetails, red);
+ ECRamDirectWrite((byte)(i + 1), ECDetails, green);
+ ECRamDirectWrite((byte)(i + 2), ECDetails, blue);
+ }
+ LedAck();
+ }
+
+ private void SetLEDColor(Color color)
+ {
+ SetLEDColorL(color);
+ SetLEDColorR(color);
+ }
+
+ public override bool ECRamDirectWrite(ushort address, ECDetails details, byte data)
+ {
+ ushort address2 = BitConverter.ToUInt16(new byte[] { (byte)address, 0xD1 }, 0);
+ return base.ECRamDirectWrite(address2, details, data);
+ }
+
public override bool SetLedStatus(bool status)
- {
- switch(status)
- {
- case true:
- LedEnable();
- break;
- case false:
- LedDisable();
- break;
+ {
+ switch(status)
+ {
+ case true:
+ LedEnable();
+ break;
+ case false:
+ LedDisable();
+ break;
}
return true;
- }
-
- public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
- {
- if (!DynamicLightingCapabilities.HasFlag(level))
- return false;
-
- switch (level)
- {
- case LEDLevel.SolidColor:
- SetLEDColor(MainColor);
- break;
- case LEDLevel.Ambilight:
- SetLEDColorL(MainColor);
- SetLEDColorR(SecondaryColor);
- break;
- }
-
- LedApply();
-
- return true;
- }
-
- public override bool SetLedBrightness(int brightness)
- {
- // we might want to store colors on SetLedColor() and brightness on SetLedBrightness()
- // so that we can let people mess with brightness slider
- return base.SetLedBrightness(brightness);
+ }
+
+ public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
+ {
+ if (!DynamicLightingCapabilities.HasFlag(level))
+ return false;
+
+ switch (level)
+ {
+ case LEDLevel.SolidColor:
+ SetLEDColor(MainColor);
+ break;
+ case LEDLevel.Ambilight:
+ SetLEDColorL(MainColor);
+ SetLEDColorR(SecondaryColor);
+ break;
+ }
+
+ LedApply();
+
+ return true;
+ }
+
+ public override bool SetLedBrightness(int brightness)
+ {
+ // we might want to store colors on SetLedColor() and brightness on SetLedBrightness()
+ // so that we can let people mess with brightness slider
+ return base.SetLedBrightness(brightness);
}
/*
private bool prevWasBlack = true;
public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level)
- {
- if (MainColor == Colors.Black)
- {
- ayaneoLED.LedDisable();
- prevWasBlack = true;
- return true;
- }
- else if (prevWasBlack)
- {
- ayaneoLED.LedEnable();
- prevWasBlack = false;
- }
-
- // Set LED color
- ayaneoLED.SetLEDColor(MainColor);
+ {
+ if (MainColor == Colors.Black)
+ {
+ ayaneoLED.LedDisable();
+ prevWasBlack = true;
+ return true;
+ }
+ else if (prevWasBlack)
+ {
+ ayaneoLED.LedEnable();
+ prevWasBlack = false;
+ }
+
+ // Set LED color
+ ayaneoLED.SetLEDColor(MainColor);
ayaneoLED.LedApply();
return true;
}
- public bool SetAmbilight(Color LEDColor1, Color LEDColor2)
- {
- // Set LED color
- ayaneoLED.SetLEDColorL(LEDColor1);
- ayaneoLED.SetLEDColorR(LEDColor2);
- ayaneoLED.LedApply();
- return true;
+ public bool SetAmbilight(Color LEDColor1, Color LEDColor2)
+ {
+ // Set LED color
+ ayaneoLED.SetLEDColorL(LEDColor1);
+ ayaneoLED.SetLEDColorR(LEDColor2);
+ ayaneoLED.LedApply();
+ return true;
}
*/
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEODevice.cs b/HandheldCompanion/Devices/AYANEO/AYANEODevice.cs
index 3c17e3da4..63c6b2032 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEODevice.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEODevice.cs
@@ -19,12 +19,12 @@ private enum JoystickSelection
private byte maxIntensity = 100; // Use the max brightness for color brightness combination value
private int prevBatteryLevelPercentage;
- private PowerStatus prevPowerStatus;
+ private PowerLineStatus prevPowerStatus;
public AYANEODevice()
{
- prevPowerStatus = SystemInformation.PowerStatus;
- prevBatteryLevelPercentage = (int)(prevPowerStatus.BatteryLifePercent * 100);
+ prevPowerStatus = SystemInformation.PowerStatus.PowerLineStatus;
+ prevBatteryLevelPercentage = (int)(SystemInformation.PowerStatus.BatteryLifePercent * 100);
PowerManager.PowerStatusChanged += PowerManager_PowerStatusChanged;
}
@@ -40,12 +40,19 @@ private void PowerManager_PowerStatusChanged(PowerStatus powerStatus)
int currentBatteryLevelPercentage = (int)(powerStatus.BatteryLifePercent * 100);
// Check if the device went from battery to charging
- if (powerStatus.PowerLineStatus == PowerLineStatus.Online && prevPowerStatus.PowerLineStatus == PowerLineStatus.Offline)
+ if (powerStatus.PowerLineStatus == PowerLineStatus.Online && prevPowerStatus == PowerLineStatus.Offline)
{
LogManager.LogDebug("Ayaneo LED, device went from battery to charging, apply color");
base.PowerStatusChange(this);
}
+ // Check if the device went from charging to battery
+ if (powerStatus.PowerLineStatus == PowerLineStatus.Offline && prevPowerStatus == PowerLineStatus.Online)
+ {
+ LogManager.LogDebug("Ayaneo LED, device went from charging to battery, apply color");
+ base.PowerStatusChange(this);
+ }
+
// Check for the battery level change scenarios
// Check if the battery went from 99 or lower to 100
@@ -64,7 +71,7 @@ private void PowerManager_PowerStatusChanged(PowerStatus powerStatus)
// Track battery level % and power status for next round
prevBatteryLevelPercentage = currentBatteryLevelPercentage;
- prevPowerStatus = powerStatus;
+ prevPowerStatus = powerStatus.PowerLineStatus;
}
private void SetJoystick(JoystickSelection joyStick)
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEOKUN.cs b/HandheldCompanion/Devices/AYANEO/AYANEOKUN.cs
new file mode 100644
index 000000000..670929043
--- /dev/null
+++ b/HandheldCompanion/Devices/AYANEO/AYANEOKUN.cs
@@ -0,0 +1,218 @@
+using HandheldCompanion.Inputs;
+using HandheldCompanion.Utils;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Threading;
+using System.Windows.Media;
+using WindowsInput.Events;
+using static HandheldCompanion.Utils.DeviceUtils;
+namespace HandheldCompanion.Devices;
+
+public class AYANEOKUN : AYANEO.AYANEODevice
+{
+ private enum LEDGroup
+ {
+ JoystickLeft = 1,
+ JoystickRight = 2,
+ JoystickBoth = 3,
+ AYAButton = 4,
+ }
+
+ private static byte[] AYA_ZONES = new byte[] { 4 };
+ private static byte[] STICK_ZONES = new byte[] { 1, 2, 3, 4 };
+
+ private Color color = Color.FromRgb(0, 0, 0);
+
+ public AYANEOKUN()
+ {
+ // device specific settings
+ ProductIllustration = "device_aya_kun";
+ ProductModel = "AYANEO KUN";
+
+ // https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
+ nTDP = new double[] { 15, 15, 20 };
+ cTDP = new double[] { 3, 54 };
+ GfxClock = new double[] { 100, 2700 };
+ CpuClock = 5100;
+
+ GyrometerAxis = new Vector3(1.0f, 1.0f, 1.0f);
+ GyrometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'X' },
+ { 'Y', 'Z' },
+ { 'Z', 'Y' }
+ };
+
+ AccelerometerAxis = new Vector3(1.0f, 1.0f, 1.0f);
+ AccelerometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'X' },
+ { 'Y', 'Z' },
+ { 'Z', 'Y' }
+ };
+
+ // device specific capacities
+ Capabilities = DeviceCapabilities.FanControl;
+ Capabilities |= DeviceCapabilities.DynamicLighting;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
+
+ ECDetails = new ECDetails
+ {
+ AddressFanControl = 0x44A,
+ AddressFanDuty = 0x44B,
+ AddressStatusCommandPort = 0x4E,
+ AddressDataPort = 0x4F,
+ FanValueMin = 0,
+ FanValueMax = 100
+ };
+
+ OEMChords.Add(new DeviceChord("Custom Key Big",
+ new List { KeyCode.RControlKey, KeyCode.LWin, KeyCode.F17 },
+ new List { KeyCode.F17, KeyCode.LWin, KeyCode.RControlKey },
+ false, ButtonFlags.OEM1
+ ));
+
+ OEMChords.Add(new DeviceChord("Custom Key Small",
+ new List { KeyCode.LWin, KeyCode.D },
+ new List { KeyCode.LWin, KeyCode.D },
+ false, ButtonFlags.OEM2
+ ));
+
+ OEMChords.Add(new DeviceChord("Custom Key Top Left",
+ new List { KeyCode.RControlKey, KeyCode.LWin, KeyCode.F15 },
+ new List { KeyCode.F15, KeyCode.LWin, KeyCode.RControlKey },
+ false, ButtonFlags.OEM3
+ ));
+
+ OEMChords.Add(new DeviceChord("Custom Key Top Right",
+ new List { KeyCode.RControlKey, KeyCode.LWin, KeyCode.F16 },
+ new List { KeyCode.F16, KeyCode.LWin, KeyCode.RControlKey },
+
+ false, ButtonFlags.OEM4
+ ));
+
+ OEMChords.Add(new DeviceChord("T",
+ new List { KeyCode.RControlKey, KeyCode.LWin, KeyCode.F18 },
+ new List { KeyCode.F18, KeyCode.LWin, KeyCode.RControlKey },
+ false, ButtonFlags.OEM5
+ ));
+
+ OEMChords.Add(new DeviceChord("Guide",
+ new List { KeyCode.LButton, KeyCode.XButton2 },
+ new List { KeyCode.LButton, KeyCode.XButton2 },
+ false, ButtonFlags.OEM6
+ ));
+
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\uE003";
+ case ButtonFlags.OEM2:
+ return "\u220B";
+ case ButtonFlags.OEM3:
+ return "\u2209";
+ case ButtonFlags.OEM4:
+ return "\u220A";
+ case ButtonFlags.OEM5:
+ return "\u0054";
+ case ButtonFlags.OEM6:
+ return "\uE001";
+ }
+
+ return defaultGlyph;
+ }
+
+ public override bool SetLedStatus(bool status)
+ {
+ if (status)
+ {
+ SetLEDGroupEnable(LEDGroup.AYAButton);
+ SetLEDGroupColor(LEDGroup.AYAButton, AYA_ZONES, color);
+
+ SetLEDGroupEnable(LEDGroup.JoystickBoth);
+ SetLEDGroupColor(LEDGroup.JoystickBoth, STICK_ZONES, color);
+ }
+ else
+ {
+ SetLEDGroupDisable(LEDGroup.AYAButton);
+ SetLEDGroupDisable(LEDGroup.JoystickBoth);
+ }
+ return true;
+ }
+
+ public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
+ {
+ if (!DynamicLightingCapabilities.HasFlag(level))
+ return false;
+
+ color = MainColor;
+
+ switch (level)
+ {
+ case LEDLevel.SolidColor:
+ SetLEDGroupColor(LEDGroup.AYAButton, AYA_ZONES, color);
+ SetLEDGroupColor(LEDGroup.JoystickBoth, STICK_ZONES, color);
+ break;
+ }
+
+ return true;
+ }
+
+ private void SetLEDGroupEnable(LEDGroup group)
+ {
+ SendLEDCommand((byte)group, 2, 0x80); // This seems to determine the time between color transitions, 0x80 being a very good balance
+ }
+
+ private void SetLEDGroupDisable(LEDGroup group)
+ {
+ SendLEDCommand((byte)group, 2, 0xc0);
+ }
+
+ private void SetLEDGroupColor(LEDGroup group, byte[] zones, Color color)
+ {
+ foreach (byte zone in zones)
+ {
+ byte[] colorValues = GetColorValues(group, zone, color);
+ for (byte colorComponentIndex = 0; colorComponentIndex < colorValues.Length; colorComponentIndex++)
+ {
+ byte zoneColorComponent = (byte)(zone * 3 + colorComponentIndex); // Indicates which Zone and which color component
+ byte colorComponentValueBrightness = (byte)(colorValues[colorComponentIndex] * 192 / byte.MaxValue); // Convert 0-255 to 0-100
+ SendLEDCommand((byte)group, zoneColorComponent, colorComponentValueBrightness);
+ }
+ }
+ }
+
+ private void SendLEDCommand(byte group, byte command, byte argument)
+ {
+ using (new ScopedLock(updateLock))
+ {
+ ECRAMWrite(0x6d, group);
+ ECRAMWrite(0xb1, command);
+ ECRAMWrite(0xb2, argument);
+ ECRAMWrite(0xbf, 0x10);
+ Thread.Sleep(5); // Sleep here to give the controller enough time. AYASpace does this as well.
+ ECRAMWrite(0xbf, 0xfe);
+ }
+ }
+
+ // Get remapped RGB color values for the specific zone
+ // 1: R -> G, G -> R, B -> B
+ // 2: R -> G, G -> B, B -> R
+ // 3: R -> B, G -> R, B -> G
+ // 4: R -> B, G -> G, B -> R
+ // 4 (AYA): R -> B, G -> R, B -> G
+ private byte[] GetColorValues(LEDGroup group, byte zone, Color color)
+ {
+ if (zone == 1) return new byte[] { color.G, color.R, color.B };
+ if (zone == 2) return new byte[] { color.G, color.B, color.R };
+ if (zone == 3 || group == LEDGroup.AYAButton) return new byte[] { color.B, color.R, color.G };
+ if (zone == 4) return new byte[] { color.B, color.G, color.R };
+
+ // Just return the default
+ return new byte[] { color.R, color.G, color.B };
+ }
+}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/AYANEO/AYANEONEXT.cs b/HandheldCompanion/Devices/AYANEO/AYANEONEXT.cs
index 0933991f6..640e082c3 100644
--- a/HandheldCompanion/Devices/AYANEO/AYANEONEXT.cs
+++ b/HandheldCompanion/Devices/AYANEO/AYANEONEXT.cs
@@ -17,7 +17,7 @@ public AYANEONEXT()
// https://www.amd.com/fr/products/apu/amd-ryzen-7-5825u
nTDP = new double[] { 15, 15, 20 };
cTDP = new double[] { 10, 25 };
- GfxClock = new double[] { 100, 2000 };
+ GfxClock = new double[] { 100, 2000 };
CpuClock = 4500;
GyrometerAxisSwap = new SortedDictionary
@@ -45,8 +45,8 @@ public AYANEONEXT()
new List { KeyCode.LWin, KeyCode.D },
false, ButtonFlags.OEM2
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/Ayn/AynLoki.cs b/HandheldCompanion/Devices/Ayn/AynLoki.cs
index 5d08a4311..79c22e215 100644
--- a/HandheldCompanion/Devices/Ayn/AynLoki.cs
+++ b/HandheldCompanion/Devices/Ayn/AynLoki.cs
@@ -1,176 +1,177 @@
-using HandheldCompanion.Inputs;
-using System;
-using System.Collections.Generic;
-using System.Numerics;
-using System.Windows.Media;
-using WindowsInput.Events;
-using static HandheldCompanion.Utils.DeviceUtils;
-namespace HandheldCompanion.Devices;
-
-public class AynLoki : IDevice
-{
- // Fan Control Mode.
- // 0 Manual Mode
- // 1 Automatic mode
- // 2 User Defined Mode
- private enum FanControlMode
- {
- Manual = 0,
- Automatic = 1,
- User = 2,
- }
-
- public AynLoki()
- {
- // Ayn Loki device generic settings
- ProductIllustration = "device_ayn_loki";
- ProductModel = "AynLoki";
-
- GyrometerAxis = new Vector3(1.0f, 1.0f, -1.0f);
- GyrometerAxisSwap = new SortedDictionary
- {
- { 'X', 'Y' },
- { 'Y', 'Z' },
- { 'Z', 'X' }
- };
-
- AccelerometerAxis = new Vector3(1.0f, -1.0f, -1.0f);
- AccelerometerAxisSwap = new SortedDictionary
- {
- { 'X', 'X' },
- { 'Y', 'Z' },
- { 'Z', 'Y' }
- };
-
- // device specific capacities
- Capabilities |= DeviceCapabilities.FanControl;
- Capabilities |= DeviceCapabilities.DynamicLighting;
-
- OEMChords.Add(new DeviceChord("Guide",
- new List { KeyCode.LButton, KeyCode.XButton2 },
- new List { KeyCode.LButton, KeyCode.XButton2 },
- false, ButtonFlags.OEM1
- ));
-
- OEMChords.Add(new DeviceChord("LCC",
- new List { KeyCode.LControl, KeyCode.LShift, KeyCode.LMenu, KeyCode.T },
- new List { KeyCode.T, KeyCode.LMenu, KeyCode.LShift, KeyCode.LControl },
- false, ButtonFlags.OEM2
- ));
- }
-
- public override void SetFanControl(bool enable, int mode)
- {
- //LogManager.LogDebug("AynLoki Set Fan Control {0}", enable);
-
- // Define the ACPI memory address for fan control mode
- byte ACPI_FanMode_Address = 0x10;
-
- // Determine the fan control mode based enable
- byte controlValue = enable ? (byte)FanControlMode.Manual : (byte)FanControlMode.Automatic;
-
- // Update the fan control mode
- ECRAMWrite(ACPI_FanMode_Address, controlValue);
- }
-
- public override void SetFanDuty(double percent)
- {
- //LogManager.LogDebug("AynLoki Set Fan Control Speed {0}%", percent);
-
- // Fan control PWM value, range 0-128 (0 speed - 128 speed max)
- byte ACPI_FanPWMDutyCycle_Address = 0x11;
-
- // Convert 0-100 percentage to 0-128 range
- byte fanSpeedSetpoint = (byte)(percent * 1.28);
-
- // Ensure the value is within the valid range
- fanSpeedSetpoint = Math.Min((byte)128, Math.Max((byte)0, fanSpeedSetpoint));
-
- // Set the requested fan speed
- ECRAMWrite(ACPI_FanPWMDutyCycle_Address, fanSpeedSetpoint);
- }
-
- public override float ReadFanDuty()
- {
- // Todo, untested and unverified
-
- // Define ACPI memory addresses for fan speed data
- byte ACPI_FanSpeed_5_Address = 0x20;
- byte ACPI_FanTempe_5_Address = 0x21;
-
- // Initialize the fan speed percentage
- int fanSpeedPercentageActual = 0;
-
- // Read the two bytes from memory (assumed to represent fan speed)
- uint data1 = ECRamReadByte(ACPI_FanSpeed_5_Address);
- uint data2 = ECRamReadByte(ACPI_FanTempe_5_Address);
-
- //LogManager.LogDebug("AynLoki ReadFanDuty data1 {0} data2 {1}", data1, data2);
-
- // Combine the two bytes into a 16-bit integer (fanSpeed)
- short fanSpeed = (short)((data2 << 8) | data1);
-
- // Assign the fan speed as a percentage to fanSpeedPercentageActual
- fanSpeedPercentageActual = fanSpeed;
-
- //LogManager.LogDebug("AynLoki ReadFanDuty percentage actual {0}", fanSpeedPercentageActual);
-
- return fanSpeedPercentageActual;
- }
-
- public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
- {
- //LogManager.LogDebug("AynLoki Set LED color");
-
- // Set LED color
- byte PWM_R_Address = 0xB0; // PWM Red Duty cycle, range 0x00-0xFF
- byte PWM_G_Address = 0xB1; // PWM Green Duty cycle, range 0x00-0xFF
- byte PWM_B_Address = 0xB2; // PWM Blue Duty cycle, range 0x00-0xFF
- byte LED_Control_mode_Address = 0xB3;
- byte LED_Control_CompletedValue = 0x00;
- byte LED_Control_Save = 0xAA; // Update request
- byte LED_Control_RGB_Idle = 0x55; // This is in Ayn example code, not used in HC.
-
- /*
- 0x00, EC writes 0x00 to notify Host that the operation has been completed
-
- 0xAA, Host writes 0xAA to inform EC that PWM_RGB needs to be updated.
-
- Interaction logic: when 0xB3 is 0, Host can update the three values of PWM_RGB,
- after updating, write 0xB3 to 0xAA to inform EC, after EC finished operation,
- write 0xB3 to 0x01, Host write 0x01, that is, enter into auto-breathing.
- */
-
- // Todo, this ec write might not be required, code example and documentation from Ayn conflict
- ECRAMWrite(LED_Control_mode_Address, LED_Control_Save);
-
- uint LED_Control_Mode_Value = ECRamReadByte(LED_Control_mode_Address);
-
- if (LED_Control_Mode_Value == LED_Control_CompletedValue)
- {
- // Update RGB addresses with respective values
- ECRAMWrite(PWM_R_Address, MainColor.R);
- ECRAMWrite(PWM_G_Address, MainColor.G);
- ECRAMWrite(PWM_B_Address, MainColor.B);
-
- ECRAMWrite(LED_Control_mode_Address, LED_Control_Save);
-
- //LogManager.LogDebug("AynLoki Set LED write memory done");
- }
-
- return true;
- }
-
- public override string GetGlyph(ButtonFlags button)
- {
- switch (button)
- {
- case ButtonFlags.OEM1:
- return "\u220C";
- case ButtonFlags.OEM2:
- return "\u220D";
- }
-
- return defaultGlyph;
- }
+using HandheldCompanion.Inputs;
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Windows.Media;
+using WindowsInput.Events;
+using static HandheldCompanion.Utils.DeviceUtils;
+namespace HandheldCompanion.Devices;
+
+public class AynLoki : IDevice
+{
+ // Fan Control Mode.
+ // 0 Manual Mode
+ // 1 Automatic mode
+ // 2 User Defined Mode
+ private enum FanControlMode
+ {
+ Manual = 0,
+ Automatic = 1,
+ User = 2,
+ }
+
+ public AynLoki()
+ {
+ // Ayn Loki device generic settings
+ ProductIllustration = "device_ayn_loki";
+ ProductModel = "AynLoki";
+
+ GyrometerAxis = new Vector3(1.0f, 1.0f, -1.0f);
+ GyrometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'Y' },
+ { 'Y', 'Z' },
+ { 'Z', 'X' }
+ };
+
+ AccelerometerAxis = new Vector3(1.0f, -1.0f, -1.0f);
+ AccelerometerAxisSwap = new SortedDictionary
+ {
+ { 'X', 'X' },
+ { 'Y', 'Z' },
+ { 'Z', 'Y' }
+ };
+
+ // device specific capacities
+ Capabilities |= DeviceCapabilities.FanControl;
+ Capabilities |= DeviceCapabilities.DynamicLighting;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
+
+ OEMChords.Add(new DeviceChord("Guide",
+ new List { KeyCode.LButton, KeyCode.XButton2 },
+ new List { KeyCode.LButton, KeyCode.XButton2 },
+ false, ButtonFlags.OEM1
+ ));
+
+ OEMChords.Add(new DeviceChord("LCC",
+ new List { KeyCode.LControl, KeyCode.LShift, KeyCode.LMenu, KeyCode.T },
+ new List { KeyCode.T, KeyCode.LMenu, KeyCode.LShift, KeyCode.LControl },
+ false, ButtonFlags.OEM2
+ ));
+ }
+
+ public override void SetFanControl(bool enable, int mode)
+ {
+ //LogManager.LogDebug("AynLoki Set Fan Control {0}", enable);
+
+ // Define the ACPI memory address for fan control mode
+ byte ACPI_FanMode_Address = 0x10;
+
+ // Determine the fan control mode based enable
+ byte controlValue = enable ? (byte)FanControlMode.Manual : (byte)FanControlMode.Automatic;
+
+ // Update the fan control mode
+ ECRAMWrite(ACPI_FanMode_Address, controlValue);
+ }
+
+ public override void SetFanDuty(double percent)
+ {
+ //LogManager.LogDebug("AynLoki Set Fan Control Speed {0}%", percent);
+
+ // Fan control PWM value, range 0-128 (0 speed - 128 speed max)
+ byte ACPI_FanPWMDutyCycle_Address = 0x11;
+
+ // Convert 0-100 percentage to 0-128 range
+ byte fanSpeedSetpoint = (byte)(percent * 1.28);
+
+ // Ensure the value is within the valid range
+ fanSpeedSetpoint = Math.Min((byte)128, Math.Max((byte)0, fanSpeedSetpoint));
+
+ // Set the requested fan speed
+ ECRAMWrite(ACPI_FanPWMDutyCycle_Address, fanSpeedSetpoint);
+ }
+
+ public override float ReadFanDuty()
+ {
+ // Todo, untested and unverified
+
+ // Define ACPI memory addresses for fan speed data
+ byte ACPI_FanSpeed_5_Address = 0x20;
+ byte ACPI_FanTempe_5_Address = 0x21;
+
+ // Initialize the fan speed percentage
+ int fanSpeedPercentageActual = 0;
+
+ // Read the two bytes from memory (assumed to represent fan speed)
+ uint data1 = ECRamReadByte(ACPI_FanSpeed_5_Address);
+ uint data2 = ECRamReadByte(ACPI_FanTempe_5_Address);
+
+ //LogManager.LogDebug("AynLoki ReadFanDuty data1 {0} data2 {1}", data1, data2);
+
+ // Combine the two bytes into a 16-bit integer (fanSpeed)
+ short fanSpeed = (short)((data2 << 8) | data1);
+
+ // Assign the fan speed as a percentage to fanSpeedPercentageActual
+ fanSpeedPercentageActual = fanSpeed;
+
+ //LogManager.LogDebug("AynLoki ReadFanDuty percentage actual {0}", fanSpeedPercentageActual);
+
+ return fanSpeedPercentageActual;
+ }
+
+ public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed)
+ {
+ //LogManager.LogDebug("AynLoki Set LED color");
+
+ // Set LED color
+ byte PWM_R_Address = 0xB0; // PWM Red Duty cycle, range 0x00-0xFF
+ byte PWM_G_Address = 0xB1; // PWM Green Duty cycle, range 0x00-0xFF
+ byte PWM_B_Address = 0xB2; // PWM Blue Duty cycle, range 0x00-0xFF
+ byte LED_Control_mode_Address = 0xB3;
+ byte LED_Control_CompletedValue = 0x00;
+ byte LED_Control_Save = 0xAA; // Update request
+ byte LED_Control_RGB_Idle = 0x55; // This is in Ayn example code, not used in HC.
+
+ /*
+ 0x00, EC writes 0x00 to notify Host that the operation has been completed
+
+ 0xAA, Host writes 0xAA to inform EC that PWM_RGB needs to be updated.
+
+ Interaction logic: when 0xB3 is 0, Host can update the three values of PWM_RGB,
+ after updating, write 0xB3 to 0xAA to inform EC, after EC finished operation,
+ write 0xB3 to 0x01, Host write 0x01, that is, enter into auto-breathing.
+ */
+
+ // Todo, this ec write might not be required, code example and documentation from Ayn conflict
+ ECRAMWrite(LED_Control_mode_Address, LED_Control_Save);
+
+ uint LED_Control_Mode_Value = ECRamReadByte(LED_Control_mode_Address);
+
+ if (LED_Control_Mode_Value == LED_Control_CompletedValue)
+ {
+ // Update RGB addresses with respective values
+ ECRAMWrite(PWM_R_Address, MainColor.R);
+ ECRAMWrite(PWM_G_Address, MainColor.G);
+ ECRAMWrite(PWM_B_Address, MainColor.B);
+
+ ECRAMWrite(LED_Control_mode_Address, LED_Control_Save);
+
+ //LogManager.LogDebug("AynLoki Set LED write memory done");
+ }
+
+ return true;
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\u220C";
+ case ButtonFlags.OEM2:
+ return "\u220D";
+ }
+
+ return defaultGlyph;
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/CNCDan/NUCDeck.cs b/HandheldCompanion/Devices/CNCDan/NUCDeck.cs
index 6165367c4..cfc47acca 100644
--- a/HandheldCompanion/Devices/CNCDan/NUCDeck.cs
+++ b/HandheldCompanion/Devices/CNCDan/NUCDeck.cs
@@ -13,6 +13,6 @@ public NUCDeck()
cTDP = new double[] { 9, 15 };
GfxClock = new double[] { 300, 950 };
CpuClock = 3400;
- }
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/GPD/GPDWin3.cs b/HandheldCompanion/Devices/GPD/GPDWin3.cs
index 00408b1eb..1d57fad14 100644
--- a/HandheldCompanion/Devices/GPD/GPDWin3.cs
+++ b/HandheldCompanion/Devices/GPD/GPDWin3.cs
@@ -14,7 +14,7 @@ public GPDWin3()
// https://www.intel.com/content/www/us/en/products/sku/217187/intel-core-i71195g7-processor-12m-cache-up-to-5-00-ghz/specifications.html
nTDP = new double[] { 20, 20, 25 };
cTDP = new double[] { 7, 25 };
- GfxClock = new double[] { 100, 1400 };
+ GfxClock = new double[] { 100, 1400 };
CpuClock = 5000;
// note, need to manually configured in GPD app
@@ -29,8 +29,8 @@ public GPDWin3()
new List { KeyCode.F12, KeyCode.R },
false, ButtonFlags.OEM2
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/GPD/GPDWin4-2023-7640U.cs b/HandheldCompanion/Devices/GPD/GPDWin4-2023-7640U.cs
index d40511759..7f6b1925e 100644
--- a/HandheldCompanion/Devices/GPD/GPDWin4-2023-7640U.cs
+++ b/HandheldCompanion/Devices/GPD/GPDWin4-2023-7640U.cs
@@ -5,7 +5,7 @@ public class GPDWin4_2023_7640U : GPDWin4_2023_7840U
public GPDWin4_2023_7640U()
{
// https://www.amd.com/en/products/apu/amd-ryzen-5-7640u
- GfxClock = new double[] { 200, 2600 };
- CpuClock = 4900;
+ GfxClock = new double[] { 200, 2600 };
+ CpuClock = 4900;
}
}
diff --git a/HandheldCompanion/Devices/GPD/GPDWin4-2023-7840U.cs b/HandheldCompanion/Devices/GPD/GPDWin4-2023-7840U.cs
index 2f8010c47..78e6c4504 100644
--- a/HandheldCompanion/Devices/GPD/GPDWin4-2023-7840U.cs
+++ b/HandheldCompanion/Devices/GPD/GPDWin4-2023-7840U.cs
@@ -15,7 +15,7 @@ public GPDWin4_2023_7840U()
// https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
nTDP = new double[] { 15, 15, 28 };
cTDP = new double[] { 5, 30 };
- GfxClock = new double[] { 200, 2700 };
+ GfxClock = new double[] { 200, 2700 };
CpuClock = 5100;
// device specific capacities
@@ -66,8 +66,8 @@ public GPDWin4_2023_7840U()
new List { KeyCode.F12, KeyCode.R },
false, ButtonFlags.OEM3
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/GPD/GPDWin4.cs b/HandheldCompanion/Devices/GPD/GPDWin4.cs
index f01c099a9..a6fbba664 100644
--- a/HandheldCompanion/Devices/GPD/GPDWin4.cs
+++ b/HandheldCompanion/Devices/GPD/GPDWin4.cs
@@ -17,7 +17,7 @@ public GPDWin4()
// https://www.amd.com/fr/products/apu/amd-ryzen-7-6800u
nTDP = new double[] { 15, 15, 28 };
cTDP = new double[] { 5, 28 };
- GfxClock = new double[] { 100, 2200 };
+ GfxClock = new double[] { 100, 2200 };
CpuClock = 4700;
// device specific capacities
@@ -67,8 +67,8 @@ public GPDWin4()
new List { KeyCode.F12, KeyCode.R },
false, ButtonFlags.OEM3
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/GPD/GPDWinMax2.cs b/HandheldCompanion/Devices/GPD/GPDWinMax2.cs
index 48a3a2a84..87b47ffb4 100644
--- a/HandheldCompanion/Devices/GPD/GPDWinMax2.cs
+++ b/HandheldCompanion/Devices/GPD/GPDWinMax2.cs
@@ -43,6 +43,19 @@ public GPDWinMax2()
new List { KeyCode.F12, KeyCode.R },
false, ButtonFlags.OEM3
));
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM2:
+ return "\u220E";
+ case ButtonFlags.OEM3:
+ return "\u220F";
+ }
+
+ return defaultGlyph;
}
public override string GetGlyph(ButtonFlags button)
diff --git a/HandheldCompanion/Devices/IDevice.cs b/HandheldCompanion/Devices/IDevice.cs
index c078753c3..5c78e32fa 100644
--- a/HandheldCompanion/Devices/IDevice.cs
+++ b/HandheldCompanion/Devices/IDevice.cs
@@ -1,862 +1,867 @@
-using HandheldCompanion.Controls;
-using HandheldCompanion.Inputs;
-using HandheldCompanion.Managers;
-using HandheldCompanion.Misc;
-using HandheldCompanion.Sensors;
-using HandheldCompanion.Utils;
-using HidLibrary;
-using Inkore.UI.WPF.Modern.Controls;
-using LibreHardwareMonitor.Hardware.Motherboard;
-using Nefarius.Utilities.DeviceManagement.PnP;
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Linq;
-using System.Numerics;
-using System.Threading;
-using System.Windows.Media;
-using Windows.Devices.Sensors;
-using WindowsInput.Events;
-using static HandheldCompanion.OneEuroFilter;
-using static HandheldCompanion.OpenLibSys;
-using static HandheldCompanion.Utils.DeviceUtils;
-
-namespace HandheldCompanion.Devices;
-
-[Flags]
-public enum DeviceCapabilities : ushort
-{
- None = 0,
- InternalSensor = 1,
- ExternalSensor = 2,
- FanControl = 4,
- DynamicLighting = 8,
- DynamicLightingBrightness = 16
-}
-
-public struct ECDetails
-{
- // Todo, remove comments
- // ADDR_PORT="0x4e" <-- AddressStatusCommandPort should be called address port??
- // DATA_PORT="0x4f" <-- AddressDataPort should be called data port??
-
- // Ayaneo LED control calls them EC_Data and EC_SC
- //private const uint EC_DATA = 0x62; // Data Port
- //private const uint EC_SC = 0x66; // Status/Command Port
-
- public ushort AddressStatusCommandPort; // Address of the register, In EC communication, the registry address specifies the type of data or command you want to access.
- public ushort AddressDataPort; // Address where the data needs to go to, When interacting with the EC, the data address is where you send or receive the actual data or commands you want to communicate with the EC.
- public ushort AddressFanControl; // Never used?
- public ushort AddressFanDuty; // Never used?
-
- // https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/12_ACPI_Embedded_Controller_Interface_Specification/embedded-controller-register-descriptions.html
- // The embedded controller contains three registers at two address locations: EC_SC and EC_DATA.
- // EC_SC Status Command Register
- // EC_DATA Data register
-
- public short FanValueMin;
- public short FanValueMax;
-}
-
-public abstract class IDevice
-{
- public delegate void KeyPressedEventHandler(ButtonFlags button);
- public delegate void KeyReleasedEventHandler(ButtonFlags button);
- public delegate void PowerStatusChangedEventHandler(IDevice device);
-
- private static OpenLibSys openLibSys;
- protected LockObject updateLock = new();
-
- private static IDevice device;
-
- protected ushort _vid, _pid;
- public Dictionary hidDevices = new();
-
- public Vector3 AccelerometerAxis = new(1.0f, 1.0f, 1.0f);
-
- public SortedDictionary AccelerometerAxisSwap = new()
- {
- { 'X', 'X' },
- { 'Y', 'Y' },
- { 'Z', 'Z' }
- };
-
- public Vector3 GyrometerAxis = new(1.0f, 1.0f, 1.0f);
-
- public SortedDictionary GyrometerAxisSwap = new()
- {
- { 'X', 'X' },
- { 'Y', 'Y' },
- { 'Z', 'Z' }
- };
-
- public DeviceCapabilities Capabilities = DeviceCapabilities.None;
- public LEDLevel DynamicLightingCapabilities = LEDLevel.SolidColor;
-
- protected const byte EC_OBF = 0x01; // Output Buffer Full
- protected const byte EC_IBF = 0x02; // Input Buffer Full
- protected const byte EC_DATA = 0x62; // Data Port
- protected const byte EC_SC = 0x66; // Status/Command Port
- protected const byte RD_EC = 0x80; // Read Embedded Controller
- protected const byte WR_EC = 0x81; // Write Embedded Controller
-
- // device configurable TDP (down, up)
- public double[] cTDP = { 10, 25 };
-
- // device GfxClock frequency limits
- public double[] GfxClock = { 100, 1800 };
- public uint CpuClock = 6000;
-
- // device nominal TDP (slow, fast)
- public double[] nTDP = { 15, 15, 20 };
-
- // device maximum operating temperature
- public double Tjmax = 100;
-
- // power profile(s)
- // we might want to create an array instead
- public PowerProfile powerProfileQuiet;
- public PowerProfile powerProfileBalanced = new(Properties.Resources.PowerProfileDefaultName, Properties.Resources.PowerProfileDefaultDescription)
- {
- Default = true,
- Guid = PowerMode.BetterPerformance,
- OSPowerMode = PowerMode.BetterPerformance,
- };
- public PowerProfile powerProfileCool;
-
- public List fanPresets = new()
- {
- // 00, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100�C
- { new double[] { 20, 20, 20, 20, 20, 25, 30, 40, 70, 70, 100 } }, // Quiet
- { new double[] { 20, 20, 20, 30, 40, 50, 70, 80, 90, 100, 100 } }, // Default
- { new double[] { 40, 40, 40, 40, 40, 50, 70, 80, 90, 100, 100 } }, // Aggressive
- };
-
- // trigger specific settings
- public List OEMChords = new();
-
- // filter settings
- public OneEuroSettings oneEuroSettings = new(0.002d, 0.008d);
-
- // UI
- protected FontFamily GlyphFontFamily = new("PromptFont");
- protected const string defaultGlyph = "\u2753";
-
- public ECDetails ECDetails;
-
- public string ExternalSensorName = string.Empty;
- public string InternalSensorName = string.Empty;
-
- public string ProductIllustration = "device_generic";
- public string ProductModel = "default";
-
- // minimum delay before trying to emulate a virtual controller on system resume (milliseconds)
- public short ResumeDelay = 1000;
-
- // key press delay to use for certain scenarios
- public short KeyPressDelay = 20;
-
- protected USBDeviceInfo sensor = new();
-
- public IDevice()
- {
- }
-
- public IEnumerable OEMButtons => OEMChords.SelectMany(a => a.state.Buttons).Distinct();
-
- public virtual bool IsOpen => openLibSys is not null;
-
- public virtual bool IsSupported => true;
-
- public Layout DefaultLayout { get; set; } = LayoutTemplate.DefaultLayout.Layout;
-
- public event KeyPressedEventHandler KeyPressed;
- public event KeyReleasedEventHandler KeyReleased;
- public event PowerStatusChangedEventHandler PowerStatusChanged;
-
- public string ManufacturerName = string.Empty;
- public string ProductName = string.Empty;
- public string SystemName = string.Empty;
- public string Version = string.Empty;
- public string Processor = string.Empty;
- public int NumberOfCores = 0;
-
- public static IDevice GetDefault()
- {
- if (device is not null)
- return device;
-
- MotherboardInfo.UpdateMotherboard();
-
- var ManufacturerName = MotherboardInfo.Manufacturer.ToUpper();
- var ProductName = MotherboardInfo.Product;
- var SystemName = MotherboardInfo.SystemName;
- var Version = MotherboardInfo.Version;
- var Processor = MotherboardInfo.ProcessorName;
- var NumberOfCores = MotherboardInfo.NumberOfCores;
-
- switch (ManufacturerName)
- {
- case "AYN":
- {
- switch (ProductName)
- {
- case "Loki MiniPro":
- device = new LokiMiniPro();
- break;
- case "Loki Zero":
- device = new LokiZero();
- break;
- case "Loki Max":
- switch (Processor)
- {
- case "AMD Ryzen 5 6600U with Radeon Graphics":
- device = new LokiMax6600U();
- break;
- case "AMD Ryzen 7 6800U with Radeon Graphics":
- device = new LokiMax6800U();
- break;
- }
- break;
- }
- }
- break;
-
- case "AOKZOE":
- {
- switch (ProductName)
- {
- case "AOKZOE A1 AR07":
- device = new AOKZOEA1();
- break;
- case "AOKZOE A1 Pro":
- device = new AOKZOEA1Pro();
- break;
- }
- }
- break;
-
- case "AYADEVICE":
- case "AYANEO":
- {
- switch (ProductName)
- {
- case "AIR":
- device = new AYANEOAIR();
- break;
- case "AIR Pro":
- device = new AYANEOAIRPro();
- break;
- case "AIR 1S":
- device = new AYANEOAIR1S();
- break;
- case "AIR Lite":
- device = new AYANEOAIRLite();
- break;
- case "AYA NEO FOUNDER":
- case "AYANEO 2021":
- device = new AYANEO2021();
- break;
- case "AYANEO 2021 Pro":
- case "AYANEO 2021 Pro Retro Power":
- device = new AYANEO2021Pro();
- break;
- case "NEXT Pro":
- case "NEXT Advance":
- case "NEXT":
- device = new AYANEONEXT();
- break;
- case "AYANEO 2":
- case "GEEK":
- device = new AYANEO2();
- break;
- case "AB05-AMD":
- device = new AYANEOAIRPlusAMD();
- break;
- case "AB05-Mendocino":
- device = new AYANEOAIRPlusAMDMendocino();
- break;
- case "AB05-Intel":
- device = new AYANEOAIRPlusIntel();
- break;
- case "AYANEO 2S":
- case "GEEK 1S":
- device = new AYANEO2S();
- break;
- }
- }
- break;
-
- case "CNCDAN":
- {
- switch (ProductName)
- {
- case "NucDeckRev1.0":
- device = new NUCDeck();
- break;
- }
- }
- break;
-
- case "GPD":
- {
- switch (ProductName)
- {
- case "WIN2":
- device = new GPDWin2();
- break;
- case "G1618-03":
- device = new GPDWin3();
- break;
- case "G1618-04":
- switch (Processor)
- {
- case "AMD Ryzen 7 6800U with Radeon Graphics":
- device = new GPDWin4();
- break;
- case "AMD Ryzen 5 7640U w/ Radeon 760M Graphics":
- device = new GPDWin4_2023_7640U();
- break;
- case "AMD Ryzen 7 7840U w/ Radeon 780M Graphics":
- device = new GPDWin4_2023_7840U();
- break;
- }
- break;
- case "G1619-03":
- device = new GPDWinMax2Intel();
- break;
- case "G1619-04":
- device = new GPDWinMax2AMD();
- break;
- }
- }
- break;
-
- case "ONE-NETBOOK TECHNOLOGY CO., LTD.":
- case "ONE-NETBOOK":
- {
- switch (ProductName)
- {
- case "ONEXPLAYER F1":
- {
- switch (Version)
- {
- default:
- case "Default string":
- device = new OneXPlayerOneXFly();
- break;
- }
- break;
- }
- case "ONE XPLAYER":
- case "ONEXPLAYER Mini Pro":
- {
- switch (Version)
- {
- default:
- case "V01":
- device = new OneXPlayerMiniAMD();
- break;
- case "1002-C":
- device = new OneXPlayerMiniIntel();
- break;
- case "V03":
- device = new OneXPlayerMiniPro();
- break;
- }
- break;
- }
- case "ONEXPLAYER mini A07":
- device = new OneXPlayerMiniAMD();
- break;
- case "ONEXPLAYER 2 ARP23":
- {
- switch (Version)
- {
- default:
- case "Ver.1.0":
- device = new OneXPlayer2();
- break;
- }
- break;
- }
- case "ONEXPLAYER 2 PRO ARP23P":
- case "ONEXPLAYER 2 PRO ARP23P EVA-01":
- switch (Version)
- {
- default:
- case "Version 1.0":
- device = new OneXPlayer2Pro();
- break;
- }
- break;
- }
- }
- break;
-
- case "ASUSTEK COMPUTER INC.":
- {
- switch (ProductName)
- {
- // Todo, figure out if theres a diff between Z1 and Z1 extreme versions
- case "RC71L":
- device = new ROGAlly();
- break;
- }
- }
- break;
-
- case "VALVE":
- {
- switch (ProductName)
- {
- case "Jupiter":
- case "Galileo":
- device = new SteamDeck();
- break;
- }
- }
- break;
-
- case "LENOVO":
- {
- switch (ProductName)
- {
- case "LNVNB161216":
- device = new LegionGo();
- break;
- }
- }
- break;
- }
-
- LogManager.LogInformation("{0} from {1}", ProductName, ManufacturerName);
-
- if (device is null)
- {
- device = new DefaultDevice();
- LogManager.LogWarning("Device not yet supported. The behavior of the application will be unpredictable");
- }
-
- // get the actual handheld device
- device.ManufacturerName = ManufacturerName;
- device.ProductName = ProductName;
-
- return device;
- }
-
- public bool HasMotionSensor()
- {
- return Capabilities.HasFlag(DeviceCapabilities.InternalSensor) || Capabilities.HasFlag(DeviceCapabilities.ExternalSensor);
- }
-
- public virtual bool Open()
- {
- if (openLibSys != null)
- return true;
-
- try
- {
- // initialize OpenLibSys
- openLibSys = new OpenLibSys();
-
- // Check support library sutatus
- var status = openLibSys.GetStatus();
- switch (status)
- {
- case (uint)OlsStatus.NO_ERROR:
- break;
- default:
- LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", status);
- return false;
- }
-
- // Check WinRing0 status
- var dllstatus = (OlsDllStatus)openLibSys.GetDllStatus();
- switch (dllstatus)
- {
- case (uint)OlsDllStatus.OLS_DLL_NO_ERROR:
- break;
- default:
- LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", dllstatus);
- return false;
- }
- }
- catch (Exception ex)
- {
- LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", ex.Message);
- Close();
- return false;
- }
-
- return true;
- }
-
- public virtual void Close()
- {
- if (openLibSys is null)
- return;
-
- SetFanControl(false);
-
- openLibSys.Dispose();
- openLibSys = null;
- }
-
- public virtual bool IsReady()
- {
- return true;
- }
-
- public virtual void SetKeyPressDelay(HIDmode controllerMode)
- {
- switch (controllerMode)
- {
- default:
- KeyPressDelay = 20;
- break;
- }
- }
-
- public void PullSensors()
- {
- Gyrometer? gyrometer = Gyrometer.GetDefault();
- Accelerometer? accelerometer = Accelerometer.GetDefault();
-
- if (gyrometer is not null && accelerometer is not null)
- {
- // check sensor
- var DeviceId = CommonUtils.Between(gyrometer.DeviceId, @"\\?\", @"#{").Replace(@"#", @"\");
- sensor = DeviceUtils.GetUSBDevice(DeviceId);
- if (sensor is not null)
- InternalSensorName = sensor.Name;
-
- Capabilities |= DeviceCapabilities.InternalSensor;
- }
- else if (Capabilities.HasFlag(DeviceCapabilities.InternalSensor))
- {
- Capabilities &= ~DeviceCapabilities.InternalSensor;
- }
-
- SerialUSBIMU? USB = SerialUSBIMU.GetDefault();
- if (USB is not null)
- {
- ExternalSensorName = USB.GetName();
-
- Capabilities |= DeviceCapabilities.ExternalSensor;
- }
- else if (Capabilities.HasFlag(DeviceCapabilities.ExternalSensor))
- {
- Capabilities &= ~DeviceCapabilities.ExternalSensor;
- }
- }
-
- public bool RestartSensor()
- {
- if (sensor is null)
- return false;
-
- return PnPUtil.RestartDevice(sensor.DeviceId);
- }
-
- public virtual void SetFanDuty(double percent)
- {
- if (ECDetails.AddressFanDuty == 0)
- return;
-
- if (!IsOpen)
- return;
-
- var duty = percent * (ECDetails.FanValueMax - ECDetails.FanValueMin) / 100 + ECDetails.FanValueMin;
- var data = Convert.ToByte(duty);
-
- ECRamDirectWrite(ECDetails.AddressFanDuty, ECDetails, data);
- }
-
- public virtual void SetFanControl(bool enable, int mode = 0)
- {
- if (ECDetails.AddressFanControl == 0)
- return;
-
- if (!IsOpen)
- return;
-
- var data = Convert.ToByte(enable);
- ECRamDirectWrite(ECDetails.AddressFanControl, ECDetails, data);
- }
-
- public virtual float ReadFanDuty()
- {
- if (ECDetails.AddressFanControl == 0)
- return 0;
-
- // todo: implement me
- return 0;
- }
-
- public virtual bool SetLedStatus(bool status)
- {
- return true;
- }
-
- public virtual bool SetLedBrightness(int brightness)
- {
- return true;
- }
-
- public virtual bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed = 100)
- {
- return true;
- }
-
- [Obsolete("ECRamReadByte is deprecated, please use ECRamReadByte with ECDetails instead.")]
- public virtual byte ECRamReadByte(ushort address)
- {
- try
- {
- return openLibSys.ReadIoPortByte(address);
- }
- catch (Exception ex)
- {
- LogManager.LogError("Couldn't read byte from address {0} using OpenLibSys. ErrorCode: {1}", address,
- ex.Message);
- return 0;
- }
- }
-
- [Obsolete("ECRamWriteByte is deprecated, please use ECRamDirectWrite with ECDetails instead.")]
- public virtual bool ECRamWriteByte(ushort address, byte data)
- {
- try
- {
- openLibSys.WriteIoPortByte(address, data);
- return true;
- }
- catch (Exception ex)
- {
- LogManager.LogError("Couldn't write byte to address {0} using OpenLibSys. ErrorCode: {1}", address,
- ex.Message);
- return false;
- }
- }
-
- public virtual byte ECRamReadByte(ushort address, ECDetails details)
- {
- var addr_upper = (byte)((address >> 8) & byte.MaxValue);
- var addr_lower = (byte)(address & byte.MaxValue);
-
- try
- {
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x11);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
- openLibSys.WriteIoPortByte(details.AddressDataPort, addr_upper);
-
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x10);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
- openLibSys.WriteIoPortByte(details.AddressDataPort, addr_lower);
-
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x12);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
-
- return openLibSys.ReadIoPortByte(details.AddressDataPort);
- }
- catch (Exception ex)
- {
- LogManager.LogError("Couldn't read to port using OpenLibSys. ErrorCode: {0}", ex.Message);
- return 0;
- }
- }
-
- public virtual bool ECRamDirectWrite(ushort address, ECDetails details, byte data)
- {
- byte addr_upper = (byte)((address >> 8) & byte.MaxValue);
- byte addr_lower = (byte)(address & byte.MaxValue);
-
- try
- {
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x11);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
- openLibSys.WriteIoPortByte(details.AddressDataPort, addr_upper);
-
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x10);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
- openLibSys.WriteIoPortByte(details.AddressDataPort, addr_lower);
-
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
- openLibSys.WriteIoPortByte(details.AddressDataPort, 0x12);
- openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
- openLibSys.WriteIoPortByte(details.AddressDataPort, data);
- return true;
- }
- catch (Exception ex)
- {
- LogManager.LogError("Couldn't write to port using OpenLibSys. ErrorCode: {0}", ex.Message);
- return false;
- }
- }
-
- protected void ECRAMWrite(byte address, byte data)
- {
- SendECCommand(WR_EC);
- SendECData(address);
- SendECData(data);
- }
-
- protected void SendECCommand(byte command)
- {
- if (IsECReady())
- ECRamWriteByte(EC_SC, command);
- }
-
- protected void SendECData(byte data)
- {
- if (IsECReady())
- ECRamWriteByte(EC_DATA, data);
- }
-
- protected bool IsECReady()
- {
- DateTime timeout = DateTime.Now.Add(TimeSpan.FromMilliseconds(50));
- while (DateTime.Now < timeout && (ECRamReadByte(EC_SC) & EC_IBF) != 0x0)
- Thread.Sleep(1);
-
- if (DateTime.Now <= timeout)
- return true;
-
- return false;
- }
-
- protected void KeyPress(ButtonFlags button)
- {
- KeyPressed?.Invoke(button);
- }
-
- protected void KeyRelease(ButtonFlags button)
- {
- KeyReleased?.Invoke(button);
- }
-
- public bool HasKey()
- {
- foreach (DeviceChord pair in OEMChords.Where(a => !a.silenced))
- {
- IEnumerable chords = pair.chords.SelectMany(chord => chord.Value);
- if (chords.Any())
- return true;
- }
-
- return false;
- }
-
- protected void ResumeDevices()
- {
- List successes = new();
-
- StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices");
-
- if (deviceInstanceIds is null)
- deviceInstanceIds = new();
-
- foreach (string InstanceId in deviceInstanceIds)
- {
- if (PnPUtil.EnableDevice(InstanceId))
- successes.Add(InstanceId);
- }
-
- foreach (string InstanceId in successes)
- deviceInstanceIds.Remove(InstanceId);
-
- SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds);
- }
-
- protected bool SuspendDevice(string InterfaceId)
- {
- PnPDevice pnPDevice = PnPDevice.GetDeviceByInterfaceId(InterfaceId);
- if (pnPDevice is not null)
- {
- StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices");
-
- if (deviceInstanceIds is null)
- deviceInstanceIds = new();
-
- if (!deviceInstanceIds.Contains(pnPDevice.InstanceId))
- deviceInstanceIds.Add(pnPDevice.InstanceId);
-
- SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds);
-
- return PnPUtil.DisableDevice(pnPDevice.InstanceId);
- }
-
- return false;
- }
-
- protected void PowerStatusChange(IDevice device)
- {
- PowerStatusChanged?.Invoke(device);
- }
-
- public static IEnumerable GetHidDevices(int vendorId, int deviceId, int minFeatures = 1)
- {
- HidDevice[] HidDeviceList = HidDevices.Enumerate(vendorId, new int[] { deviceId }).ToArray();
- foreach (HidDevice device in HidDeviceList)
- if (device.IsConnected && device.Capabilities.FeatureReportByteLength >= minFeatures)
- yield return device;
- }
-
- public string GetButtonName(ButtonFlags button)
- {
- return EnumUtils.GetDescriptionFromEnumValue(button, GetType().Name);
- }
-
- public FontIcon GetFontIcon(ButtonFlags button, int FontIconSize = 14)
- {
- var FontIcon = new FontIcon
- {
- Glyph = GetGlyph(button),
- FontSize = FontIconSize,
- Foreground = null,
- };
-
- if (FontIcon.Glyph is not null)
- {
- FontIcon.FontFamily = GlyphFontFamily;
- FontIcon.FontSize = 28;
- }
-
- return FontIcon;
- }
-
- public virtual string GetGlyph(ButtonFlags button)
- {
- switch (button)
- {
- case ButtonFlags.OEM1:
- return "\u2780";
- case ButtonFlags.OEM2:
- return "\u2781";
- case ButtonFlags.OEM3:
- return "\u2782";
- case ButtonFlags.OEM4:
- return "\u2783";
- case ButtonFlags.OEM5:
- return "\u2784";
- case ButtonFlags.OEM6:
- return "\u2785";
- case ButtonFlags.OEM7:
- return "\u2786";
- case ButtonFlags.OEM8:
- return "\u2787";
- case ButtonFlags.OEM9:
- return "\u2788";
- case ButtonFlags.OEM10:
- return "\u2789";
- }
-
- return defaultGlyph;
- }
+using HandheldCompanion.Controls;
+using HandheldCompanion.Inputs;
+using HandheldCompanion.Managers;
+using HandheldCompanion.Misc;
+using HandheldCompanion.Sensors;
+using HandheldCompanion.Utils;
+using HidLibrary;
+using iNKORE.UI.WPF.Modern.Controls;
+using LibreHardwareMonitor.Hardware.Motherboard;
+using Nefarius.Utilities.DeviceManagement.PnP;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Numerics;
+using System.Threading;
+using System.Windows.Media;
+using Windows.Devices.Sensors;
+using WindowsInput.Events;
+using static HandheldCompanion.OneEuroFilter;
+using static HandheldCompanion.OpenLibSys;
+using static HandheldCompanion.Utils.DeviceUtils;
+
+namespace HandheldCompanion.Devices;
+
+[Flags]
+public enum DeviceCapabilities : ushort
+{
+ None = 0,
+ InternalSensor = 1,
+ ExternalSensor = 2,
+ FanControl = 4,
+ DynamicLighting = 8,
+ DynamicLightingBrightness = 16,
+ DynamicLightingSecondLEDColor = 32,
+}
+
+public struct ECDetails
+{
+ // Todo, remove comments
+ // ADDR_PORT="0x4e" <-- AddressStatusCommandPort should be called address port??
+ // DATA_PORT="0x4f" <-- AddressDataPort should be called data port??
+
+ // Ayaneo LED control calls them EC_Data and EC_SC
+ //private const uint EC_DATA = 0x62; // Data Port
+ //private const uint EC_SC = 0x66; // Status/Command Port
+
+ public ushort AddressStatusCommandPort; // Address of the register, In EC communication, the registry address specifies the type of data or command you want to access.
+ public ushort AddressDataPort; // Address where the data needs to go to, When interacting with the EC, the data address is where you send or receive the actual data or commands you want to communicate with the EC.
+ public ushort AddressFanControl; // Never used?
+ public ushort AddressFanDuty; // Never used?
+
+ // https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/12_ACPI_Embedded_Controller_Interface_Specification/embedded-controller-register-descriptions.html
+ // The embedded controller contains three registers at two address locations: EC_SC and EC_DATA.
+ // EC_SC Status Command Register
+ // EC_DATA Data register
+
+ public short FanValueMin;
+ public short FanValueMax;
+}
+
+public abstract class IDevice
+{
+ public delegate void KeyPressedEventHandler(ButtonFlags button);
+ public delegate void KeyReleasedEventHandler(ButtonFlags button);
+ public delegate void PowerStatusChangedEventHandler(IDevice device);
+
+ private static OpenLibSys openLibSys;
+ protected LockObject updateLock = new();
+
+ private static IDevice device;
+
+ protected ushort _vid, _pid;
+ public Dictionary hidDevices = new();
+
+ public Vector3 AccelerometerAxis = new(1.0f, 1.0f, 1.0f);
+
+ public SortedDictionary AccelerometerAxisSwap = new()
+ {
+ { 'X', 'X' },
+ { 'Y', 'Y' },
+ { 'Z', 'Z' }
+ };
+
+ public Vector3 GyrometerAxis = new(1.0f, 1.0f, 1.0f);
+
+ public SortedDictionary GyrometerAxisSwap = new()
+ {
+ { 'X', 'X' },
+ { 'Y', 'Y' },
+ { 'Z', 'Z' }
+ };
+
+ public DeviceCapabilities Capabilities = DeviceCapabilities.None;
+ public LEDLevel DynamicLightingCapabilities = LEDLevel.SolidColor;
+
+ protected const byte EC_OBF = 0x01; // Output Buffer Full
+ protected const byte EC_IBF = 0x02; // Input Buffer Full
+ protected const byte EC_DATA = 0x62; // Data Port
+ protected const byte EC_SC = 0x66; // Status/Command Port
+ protected const byte RD_EC = 0x80; // Read Embedded Controller
+ protected const byte WR_EC = 0x81; // Write Embedded Controller
+
+ // device configurable TDP (down, up)
+ public double[] cTDP = { 10, 25 };
+
+ // device GfxClock frequency limits
+ public double[] GfxClock = { 100, 1800 };
+ public uint CpuClock = 6000;
+
+ // device nominal TDP (slow, fast)
+ public double[] nTDP = { 15, 15, 20 };
+
+ // device maximum operating temperature
+ public double Tjmax = 95;
+
+ // power profile(s)
+ public List DevicePowerProfiles = new List()
+ {
+ // Default profile
+ new(Properties.Resources.PowerProfileDefaultName, Properties.Resources.PowerProfileDefaultDescription)
+ {
+ Default = true,
+ Guid = Guid.Empty,
+ OSPowerMode = OSPowerMode.BetterPerformance
+ }
+ };
+
+ public List fanPresets = new()
+ {
+ // 00, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100�C
+ { new double[] { 20, 20, 20, 20, 20, 25, 30, 40, 70, 70, 100 } }, // Quiet
+ { new double[] { 20, 20, 20, 30, 40, 50, 70, 80, 90, 100, 100 } }, // Default
+ { new double[] { 40, 40, 40, 40, 40, 50, 70, 80, 90, 100, 100 } }, // Aggressive
+ };
+
+ // trigger specific settings
+ public List OEMChords = new();
+
+ // filter settings
+ public OneEuroSettings oneEuroSettings = new(0.002d, 0.008d);
+
+ // UI
+ protected FontFamily GlyphFontFamily = new("PromptFont");
+ protected const string defaultGlyph = "\u2753";
+
+ public ECDetails ECDetails;
+
+ public string ExternalSensorName = string.Empty;
+ public string InternalSensorName = string.Empty;
+
+ public string ProductIllustration = "device_generic";
+ public string ProductModel = "default";
+
+ // minimum delay before trying to emulate a virtual controller on system resume (milliseconds)
+ public short ResumeDelay = 1000;
+
+ // key press delay to use for certain scenarios
+ public short KeyPressDelay = 20;
+
+ protected USBDeviceInfo sensor = new();
+
+ public IDevice()
+ {
+ }
+
+ public IEnumerable OEMButtons => OEMChords.SelectMany(a => a.state.Buttons).Distinct();
+
+ public virtual bool IsOpen => openLibSys is not null;
+
+ public virtual bool IsSupported => true;
+
+ public Layout DefaultLayout { get; set; } = LayoutTemplate.DefaultLayout.Layout;
+
+ public event KeyPressedEventHandler KeyPressed;
+ public event KeyReleasedEventHandler KeyReleased;
+ public event PowerStatusChangedEventHandler PowerStatusChanged;
+
+ public string ManufacturerName = string.Empty;
+ public string ProductName = string.Empty;
+ public string SystemName = string.Empty;
+ public string Version = string.Empty;
+ public string Processor = string.Empty;
+ public int NumberOfCores = 0;
+
+ public static IDevice GetDefault()
+ {
+ if (device is not null)
+ return device;
+
+ MotherboardInfo.UpdateMotherboard();
+
+ var ManufacturerName = MotherboardInfo.Manufacturer.ToUpper();
+ var ProductName = MotherboardInfo.Product;
+ var SystemName = MotherboardInfo.SystemName;
+ var Version = MotherboardInfo.Version;
+ var Processor = MotherboardInfo.ProcessorName;
+ var NumberOfCores = MotherboardInfo.NumberOfCores;
+
+ switch (ManufacturerName)
+ {
+ case "AYN":
+ {
+ switch (ProductName)
+ {
+ case "Loki MiniPro":
+ device = new LokiMiniPro();
+ break;
+ case "Loki Zero":
+ device = new LokiZero();
+ break;
+ case "Loki Max":
+ switch (Processor)
+ {
+ case "AMD Ryzen 5 6600U with Radeon Graphics":
+ device = new LokiMax6600U();
+ break;
+ case "AMD Ryzen 7 6800U with Radeon Graphics":
+ device = new LokiMax6800U();
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case "AOKZOE":
+ {
+ switch (ProductName)
+ {
+ case "AOKZOE A1 AR07":
+ device = new AOKZOEA1();
+ break;
+ case "AOKZOE A1 Pro":
+ device = new AOKZOEA1Pro();
+ break;
+ }
+ }
+ break;
+
+ case "AYADEVICE":
+ case "AYANEO":
+ {
+ switch (ProductName)
+ {
+ case "AIR":
+ device = new AYANEOAIR();
+ break;
+ case "AIR Pro":
+ device = new AYANEOAIRPro();
+ break;
+ case "AIR 1S":
+ device = new AYANEOAIR1S();
+ break;
+ case "AIR Lite":
+ device = new AYANEOAIRLite();
+ break;
+ case "AYA NEO FOUNDER":
+ case "AYANEO 2021":
+ device = new AYANEO2021();
+ break;
+ case "AYANEO 2021 Pro":
+ case "AYANEO 2021 Pro Retro Power":
+ device = new AYANEO2021Pro();
+ break;
+ case "KUN":
+ device = new AYANEOKUN();
+ break;
+ case "NEXT Pro":
+ case "NEXT Advance":
+ case "NEXT":
+ device = new AYANEONEXT();
+ break;
+ case "AYANEO 2":
+ case "GEEK":
+ device = new AYANEO2();
+ break;
+ case "AB05-AMD":
+ device = new AYANEOAIRPlusAMD();
+ break;
+ case "AB05-Mendocino":
+ device = new AYANEOAIRPlusAMDMendocino();
+ break;
+ case "AB05-Intel":
+ device = new AYANEOAIRPlusIntel();
+ break;
+ case "AYANEO 2S":
+ case "GEEK 1S":
+ device = new AYANEO2S();
+ break;
+ }
+ }
+ break;
+
+ case "CNCDAN":
+ {
+ switch (ProductName)
+ {
+ case "NucDeckRev1.0":
+ device = new NUCDeck();
+ break;
+ }
+ }
+ break;
+
+ case "GPD":
+ {
+ switch (ProductName)
+ {
+ case "WIN2":
+ device = new GPDWin2();
+ break;
+ case "G1618-03":
+ device = new GPDWin3();
+ break;
+ case "G1618-04":
+ switch (Processor)
+ {
+ case "AMD Ryzen 7 6800U with Radeon Graphics":
+ device = new GPDWin4();
+ break;
+ case "AMD Ryzen 5 7640U w/ Radeon 760M Graphics":
+ device = new GPDWin4_2023_7640U();
+ break;
+ case "AMD Ryzen 7 7840U w/ Radeon 780M Graphics":
+ device = new GPDWin4_2023_7840U();
+ break;
+ }
+ break;
+ case "G1619-03":
+ device = new GPDWinMax2Intel();
+ break;
+ case "G1619-04":
+ device = new GPDWinMax2AMD();
+ break;
+ }
+ }
+ break;
+
+ case "ONE-NETBOOK TECHNOLOGY CO., LTD.":
+ case "ONE-NETBOOK":
+ {
+ switch (ProductName)
+ {
+ case "ONEXPLAYER F1":
+ {
+ switch (Version)
+ {
+ default:
+ case "Default string":
+ device = new OneXPlayerOneXFly();
+ break;
+ }
+ break;
+ }
+ case "ONE XPLAYER":
+ case "ONEXPLAYER Mini Pro":
+ {
+ switch (Version)
+ {
+ default:
+ case "V01":
+ device = new OneXPlayerMiniAMD();
+ break;
+ case "1002-C":
+ device = new OneXPlayerMiniIntel();
+ break;
+ case "V03":
+ device = new OneXPlayerMiniPro();
+ break;
+ }
+ break;
+ }
+ case "ONEXPLAYER mini A07":
+ device = new OneXPlayerMiniAMD();
+ break;
+ case "ONEXPLAYER 2 ARP23":
+ {
+ switch (Version)
+ {
+ default:
+ case "Ver.1.0":
+ device = new OneXPlayer2();
+ break;
+ }
+ break;
+ }
+ case "ONEXPLAYER 2 PRO ARP23P":
+ case "ONEXPLAYER 2 PRO ARP23P EVA-01":
+ switch (Version)
+ {
+ default:
+ case "Version 1.0":
+ device = new OneXPlayer2Pro();
+ break;
+ }
+ break;
+ }
+ }
+ break;
+
+ case "ASUSTEK COMPUTER INC.":
+ {
+ switch (ProductName)
+ {
+ // Todo, figure out if theres a diff between Z1 and Z1 extreme versions
+ case "RC71L":
+ device = new ROGAlly();
+ break;
+ }
+ }
+ break;
+
+ case "VALVE":
+ {
+ switch (ProductName)
+ {
+ case "Jupiter":
+ case "Galileo":
+ device = new SteamDeck();
+ break;
+ }
+ }
+ break;
+
+ case "LENOVO":
+ {
+ switch (ProductName)
+ {
+ case "LNVNB161216":
+ device = new LegionGo();
+ break;
+ }
+ }
+ break;
+ }
+
+ LogManager.LogInformation("{0} from {1}", ProductName, ManufacturerName);
+
+ if (device is null)
+ {
+ device = new DefaultDevice();
+ LogManager.LogWarning("Device not yet supported. The behavior of the application will be unpredictable");
+ }
+
+ // get the actual handheld device
+ device.ManufacturerName = ManufacturerName;
+ device.ProductName = ProductName;
+
+ return device;
+ }
+
+ public bool HasMotionSensor()
+ {
+ return Capabilities.HasFlag(DeviceCapabilities.InternalSensor) || Capabilities.HasFlag(DeviceCapabilities.ExternalSensor);
+ }
+
+ public virtual bool Open()
+ {
+ if (openLibSys != null)
+ return true;
+
+ try
+ {
+ // initialize OpenLibSys
+ openLibSys = new OpenLibSys();
+
+ // Check support library sutatus
+ var status = openLibSys.GetStatus();
+ switch (status)
+ {
+ case (uint)OlsStatus.NO_ERROR:
+ break;
+ default:
+ LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", status);
+ return false;
+ }
+
+ // Check WinRing0 status
+ var dllstatus = (OlsDllStatus)openLibSys.GetDllStatus();
+ switch (dllstatus)
+ {
+ case (uint)OlsDllStatus.OLS_DLL_NO_ERROR:
+ break;
+ default:
+ LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", dllstatus);
+ return false;
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.LogError("Couldn't initialize OpenLibSys. ErrorCode: {0}", ex.Message);
+ Close();
+ return false;
+ }
+
+ return true;
+ }
+
+ public virtual void Close()
+ {
+ if (openLibSys is null)
+ return;
+
+ SetFanControl(false);
+
+ openLibSys.Dispose();
+ openLibSys = null;
+ }
+
+ public virtual bool IsReady()
+ {
+ return true;
+ }
+
+ public virtual void SetKeyPressDelay(HIDmode controllerMode)
+ {
+ switch (controllerMode)
+ {
+ default:
+ KeyPressDelay = 20;
+ break;
+ }
+ }
+
+ public void PullSensors()
+ {
+ Gyrometer? gyrometer = Gyrometer.GetDefault();
+ Accelerometer? accelerometer = Accelerometer.GetDefault();
+
+ if (gyrometer is not null && accelerometer is not null)
+ {
+ // check sensor
+ var DeviceId = CommonUtils.Between(gyrometer.DeviceId, @"\\?\", @"#{").Replace(@"#", @"\");
+ sensor = DeviceUtils.GetUSBDevice(DeviceId);
+ if (sensor is not null)
+ InternalSensorName = sensor.Name;
+
+ Capabilities |= DeviceCapabilities.InternalSensor;
+ }
+ else if (Capabilities.HasFlag(DeviceCapabilities.InternalSensor))
+ {
+ Capabilities &= ~DeviceCapabilities.InternalSensor;
+ }
+
+ SerialUSBIMU? USB = SerialUSBIMU.GetDefault();
+ if (USB is not null)
+ {
+ ExternalSensorName = USB.GetName();
+
+ Capabilities |= DeviceCapabilities.ExternalSensor;
+ }
+ else if (Capabilities.HasFlag(DeviceCapabilities.ExternalSensor))
+ {
+ Capabilities &= ~DeviceCapabilities.ExternalSensor;
+ }
+ }
+
+ public bool RestartSensor()
+ {
+ if (sensor is null)
+ return false;
+
+ return PnPUtil.RestartDevice(sensor.DeviceId);
+ }
+
+ public virtual void SetFanDuty(double percent)
+ {
+ if (ECDetails.AddressFanDuty == 0)
+ return;
+
+ if (!IsOpen)
+ return;
+
+ var duty = percent * (ECDetails.FanValueMax - ECDetails.FanValueMin) / 100 + ECDetails.FanValueMin;
+ var data = Convert.ToByte(duty);
+
+ ECRamDirectWrite(ECDetails.AddressFanDuty, ECDetails, data);
+ }
+
+ public virtual void SetFanControl(bool enable, int mode = 0)
+ {
+ if (ECDetails.AddressFanControl == 0)
+ return;
+
+ if (!IsOpen)
+ return;
+
+ var data = Convert.ToByte(enable);
+ ECRamDirectWrite(ECDetails.AddressFanControl, ECDetails, data);
+ }
+
+ public virtual float ReadFanDuty()
+ {
+ if (ECDetails.AddressFanControl == 0)
+ return 0;
+
+ // todo: implement me
+ return 0;
+ }
+
+ public virtual bool SetLedStatus(bool status)
+ {
+ return true;
+ }
+
+ public virtual bool SetLedBrightness(int brightness)
+ {
+ return true;
+ }
+
+ public virtual bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed = 100)
+ {
+ return true;
+ }
+
+ [Obsolete("ECRamReadByte is deprecated, please use ECRamReadByte with ECDetails instead.")]
+ public virtual byte ECRamReadByte(ushort address)
+ {
+ try
+ {
+ return openLibSys.ReadIoPortByte(address);
+ }
+ catch (Exception ex)
+ {
+ LogManager.LogError("Couldn't read byte from address {0} using OpenLibSys. ErrorCode: {1}", address,
+ ex.Message);
+ return 0;
+ }
+ }
+
+ [Obsolete("ECRamWriteByte is deprecated, please use ECRamDirectWrite with ECDetails instead.")]
+ public virtual bool ECRamWriteByte(ushort address, byte data)
+ {
+ try
+ {
+ openLibSys.WriteIoPortByte(address, data);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.LogError("Couldn't write byte to address {0} using OpenLibSys. ErrorCode: {1}", address,
+ ex.Message);
+ return false;
+ }
+ }
+
+ public virtual byte ECRamReadByte(ushort address, ECDetails details)
+ {
+ var addr_upper = (byte)((address >> 8) & byte.MaxValue);
+ var addr_lower = (byte)(address & byte.MaxValue);
+
+ try
+ {
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x11);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, addr_upper);
+
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x10);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, addr_lower);
+
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x12);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+
+ return openLibSys.ReadIoPortByte(details.AddressDataPort);
+ }
+ catch (Exception ex)
+ {
+ LogManager.LogError("Couldn't read to port using OpenLibSys. ErrorCode: {0}", ex.Message);
+ return 0;
+ }
+ }
+
+ public virtual bool ECRamDirectWrite(ushort address, ECDetails details, byte data)
+ {
+ byte addr_upper = (byte)((address >> 8) & byte.MaxValue);
+ byte addr_lower = (byte)(address & byte.MaxValue);
+
+ try
+ {
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x11);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, addr_upper);
+
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x10);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, addr_lower);
+
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2E);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, 0x12);
+ openLibSys.WriteIoPortByte(details.AddressStatusCommandPort, 0x2F);
+ openLibSys.WriteIoPortByte(details.AddressDataPort, data);
+ return true;
+ }
+ catch (Exception ex)
+ {
+ LogManager.LogError("Couldn't write to port using OpenLibSys. ErrorCode: {0}", ex.Message);
+ return false;
+ }
+ }
+
+ protected void ECRAMWrite(byte address, byte data)
+ {
+ SendECCommand(WR_EC);
+ SendECData(address);
+ SendECData(data);
+ }
+
+ protected void SendECCommand(byte command)
+ {
+ if (IsECReady())
+ ECRamWriteByte(EC_SC, command);
+ }
+
+ protected void SendECData(byte data)
+ {
+ if (IsECReady())
+ ECRamWriteByte(EC_DATA, data);
+ }
+
+ protected bool IsECReady()
+ {
+ DateTime timeout = DateTime.Now.Add(TimeSpan.FromMilliseconds(50));
+ while (DateTime.Now < timeout && (ECRamReadByte(EC_SC) & EC_IBF) != 0x0)
+ Thread.Sleep(1);
+
+ if (DateTime.Now <= timeout)
+ return true;
+
+ return false;
+ }
+
+ protected void KeyPress(ButtonFlags button)
+ {
+ KeyPressed?.Invoke(button);
+ }
+
+ protected void KeyRelease(ButtonFlags button)
+ {
+ KeyReleased?.Invoke(button);
+ }
+
+ public bool HasKey()
+ {
+ foreach (DeviceChord pair in OEMChords.Where(a => !a.silenced))
+ {
+ IEnumerable chords = pair.chords.SelectMany(chord => chord.Value);
+ if (chords.Any())
+ return true;
+ }
+
+ return false;
+ }
+
+ protected void ResumeDevices()
+ {
+ List successes = new();
+
+ StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices");
+
+ if (deviceInstanceIds is null)
+ deviceInstanceIds = new();
+
+ foreach (string InstanceId in deviceInstanceIds)
+ {
+ if (PnPUtil.EnableDevice(InstanceId))
+ successes.Add(InstanceId);
+ }
+
+ foreach (string InstanceId in successes)
+ deviceInstanceIds.Remove(InstanceId);
+
+ SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds);
+ }
+
+ protected bool SuspendDevice(string InterfaceId)
+ {
+ PnPDevice pnPDevice = PnPDevice.GetDeviceByInterfaceId(InterfaceId);
+ if (pnPDevice is not null)
+ {
+ StringCollection deviceInstanceIds = SettingsManager.GetStringCollection("SuspendedDevices");
+
+ if (deviceInstanceIds is null)
+ deviceInstanceIds = new();
+
+ if (!deviceInstanceIds.Contains(pnPDevice.InstanceId))
+ deviceInstanceIds.Add(pnPDevice.InstanceId);
+
+ SettingsManager.SetProperty("SuspendedDevices", deviceInstanceIds);
+
+ return PnPUtil.DisableDevice(pnPDevice.InstanceId);
+ }
+
+ return false;
+ }
+
+ protected void PowerStatusChange(IDevice device)
+ {
+ PowerStatusChanged?.Invoke(device);
+ }
+
+ public static IEnumerable GetHidDevices(int vendorId, int deviceId, int minFeatures = 1)
+ {
+ HidDevice[] HidDeviceList = HidDevices.Enumerate(vendorId, new int[] { deviceId }).ToArray();
+ foreach (HidDevice device in HidDeviceList)
+ if (device.IsConnected && device.Capabilities.FeatureReportByteLength >= minFeatures)
+ yield return device;
+ }
+
+ public string GetButtonName(ButtonFlags button)
+ {
+ return EnumUtils.GetDescriptionFromEnumValue(button, GetType().Name);
+ }
+
+ public FontIcon GetFontIcon(ButtonFlags button, int FontIconSize = 14)
+ {
+ var FontIcon = new FontIcon
+ {
+ Glyph = GetGlyph(button),
+ FontSize = FontIconSize,
+ Foreground = null,
+ };
+
+ if (FontIcon.Glyph is not null)
+ {
+ FontIcon.FontFamily = GlyphFontFamily;
+ FontIcon.FontSize = 28;
+ }
+
+ return FontIcon;
+ }
+
+ public virtual string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\u2780";
+ case ButtonFlags.OEM2:
+ return "\u2781";
+ case ButtonFlags.OEM3:
+ return "\u2782";
+ case ButtonFlags.OEM4:
+ return "\u2783";
+ case ButtonFlags.OEM5:
+ return "\u2784";
+ case ButtonFlags.OEM6:
+ return "\u2785";
+ case ButtonFlags.OEM7:
+ return "\u2786";
+ case ButtonFlags.OEM8:
+ return "\u2787";
+ case ButtonFlags.OEM9:
+ return "\u2788";
+ case ButtonFlags.OEM10:
+ return "\u2789";
+ }
+
+ return defaultGlyph;
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/Lenovo/LegionGo.cs b/HandheldCompanion/Devices/Lenovo/LegionGo.cs
index 889ca662c..49076e93f 100644
--- a/HandheldCompanion/Devices/Lenovo/LegionGo.cs
+++ b/HandheldCompanion/Devices/Lenovo/LegionGo.cs
@@ -76,31 +76,45 @@ public LegionGo()
// dynamic lighting capacities
DynamicLightingCapabilities |= LEDLevel.SolidColor;
- DynamicLightingCapabilities |= LEDLevel.Ambilight;
+ DynamicLightingCapabilities |= LEDLevel.Breathing;
+ DynamicLightingCapabilities |= LEDLevel.Rainbow;
+ DynamicLightingCapabilities |= LEDLevel.Wheel;
- powerProfileQuiet = new(Properties.Resources.PowerProfileSilentName, Properties.Resources.PowerProfileSilentDescription)
+ // Legion Go - Quiet
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileLegionGoQuietName, Properties.Resources.PowerProfileLegionGoQuietDescription)
{
Default = true,
- OSPowerMode = PowerMode.BetterBattery,
- OEMPowerMode = (int)LegionMode.Quiet,
- Guid = PowerMode.BetterBattery
- };
+ DeviceDefault = true,
+ OSPowerMode = OSPowerMode.BetterBattery,
+ OEMPowerMode = (int) LegionMode.Quiet,
+ Guid = new("961cc777-2547-4f9d-8174-7d86181b8a7a"),
+ TDPOverrideEnabled = true,
+ TDPOverrideValues = new[] { 8.0d, 8.0d, 8.0d }
+ });
- powerProfileBalanced = new(Properties.Resources.PowerProfilePerformanceName, Properties.Resources.PowerProfilePerformanceDescription)
+ // Legion Go - Balanced
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileLegionGoBalancedName, Properties.Resources.PowerProfileLegionGoBalancedDescription)
{
Default = true,
- OSPowerMode = PowerMode.BetterPerformance,
+ DeviceDefault = true,
+ OSPowerMode = OSPowerMode.BetterPerformance,
OEMPowerMode = (int)LegionMode.Balanced,
- Guid = PowerMode.BetterPerformance
- };
+ Guid = new("3af9B8d9-7c97-431d-ad78-34a8bfea439f"),
+ TDPOverrideEnabled = true,
+ TDPOverrideValues = new[] { 15.0d, 15.0d, 15.0d }
+ });
- powerProfileCool = new(Properties.Resources.PowerProfileTurboName, Properties.Resources.PowerProfileTurboDescription)
+ // Legion Go - Performance
+ DevicePowerProfiles.Add(new(Properties.Resources.PowerProfileLegionGoPerformanceName, Properties.Resources.PowerProfileLegionGoPerformanceDescription)
{
Default = true,
- OSPowerMode = PowerMode.BestPerformance,
+ DeviceDefault = true,
+ OSPowerMode = OSPowerMode.BestPerformance,
OEMPowerMode = (int)LegionMode.Performance,
- Guid = PowerMode.BestPerformance
- };
+ Guid = new("ded574b5-45a0-4f42-8737-46345c09c238"),
+ TDPOverrideEnabled = true,
+ TDPOverrideValues = new[] { 20.0d, 20.0d, 20.0d }
+ });
PowerProfileManager.Applied += PowerProfileManager_Applied;
@@ -327,20 +341,60 @@ public override bool SetLedStatus(bool status)
}
public override bool SetLedColor(Color MainColor, Color SecondaryColor, LEDLevel level, int speed = 100)
+ {
+ // Speed is inverted for Legion Go
+ lightProfileL.speed = 100 - speed;
+ lightProfileR.speed = 100 - speed;
+
+ // 1 - solid color
+ // 2 - breathing
+ // 3 - rainbow
+ // 4 - spiral rainbow
+ switch (level)
+ {
+ case LEDLevel.Breathing:
+ {
+ lightProfileL.effect = 2;
+ lightProfileR.effect = 2;
+ SetLightProfileColors(MainColor, MainColor);
+ }
+ break;
+ case LEDLevel.Rainbow:
+ {
+ lightProfileL.effect = 3;
+ lightProfileR.effect = 3;
+ }
+ break;
+ case LEDLevel.Wheel:
+ {
+ lightProfileL.effect = 4;
+ lightProfileR.effect = 4;
+ }
+ break;
+ default:
+ {
+ lightProfileL.effect = 1;
+ lightProfileR.effect = 1;
+ SetLightProfileColors(MainColor, MainColor);
+ }
+ break;
+ }
+
+ SetLightingEffectProfileID(3, lightProfileL);
+ SetLightingEffectProfileID(4, lightProfileR);
+
+ return true;
+ }
+
+ private void SetLightProfileColors(Color MainColor, Color SecondaryColor)
{
lightProfileL.r = MainColor.R;
lightProfileL.g = MainColor.G;
lightProfileL.b = MainColor.B;
- lightProfileL.speed = speed;
- SetLightingEffectProfileID(3, lightProfileL);
lightProfileR.r = SecondaryColor.R;
lightProfileR.g = SecondaryColor.G;
lightProfileR.b = SecondaryColor.B;
- lightProfileR.speed = speed;
- SetLightingEffectProfileID(4, lightProfileR);
-
- return true;
}
public override string GetGlyph(ButtonFlags button)
diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayer2.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayer2.cs
index 15285a906..52688979a 100644
--- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayer2.cs
+++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayer2.cs
@@ -17,7 +17,7 @@ public OneXPlayer2() : base()
// https://www.amd.com/en/products/apu/amd-ryzen-7-6800u
this.nTDP = new double[] { 15, 15, 20 };
this.cTDP = new double[] { 4, 28 };
- this.GfxClock = new double[] { 100, 2200 };
+ this.GfxClock = new double[] { 100, 2200 };
this.CpuClock = 4700;
GyrometerAxis = new Vector3(-1.0f, 1.0f, -1.0f);
@@ -56,16 +56,17 @@ public OneXPlayer2() : base()
new List() { KeyCode.LWin, KeyCode.LMenu, KeyCode.LControl },
false, ButtonFlags.OEM2
));
- }
- public override string GetGlyph(ButtonFlags button)
- {
- switch (button)
- {
- case ButtonFlags.OEM2:
- return "\u2211";
- }
-
- return defaultGlyph;
+ }
+
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM2:
+ return "\u2211";
+ }
+
+ return defaultGlyph;
}
public override bool Open()
diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMini.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMini.cs
index be83d6a00..7ac4f79a0 100644
--- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMini.cs
+++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMini.cs
@@ -57,6 +57,20 @@ public OneXPlayerMini()
new List { KeyCode.LWin, KeyCode.D },
false, ButtonFlags.OEM3
));
+ }
+ public override string GetGlyph(ButtonFlags button)
+ {
+ switch (button)
+ {
+ case ButtonFlags.OEM1:
+ return "\u2219";
+ case ButtonFlags.OEM2:
+ return "\u2210";
+ case ButtonFlags.OEM3:
+ return "\u2218";
+ }
+
+ return defaultGlyph;
}
public override string GetGlyph(ButtonFlags button)
{
diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMiniPro.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMiniPro.cs
index 6e21b0226..709d934b6 100644
--- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMiniPro.cs
+++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerMiniPro.cs
@@ -13,7 +13,7 @@ public OneXPlayerMiniPro()
// https://www.amd.com/en/products/apu/amd-ryzen-7-6800u
nTDP = new double[] { 15, 15, 20 };
cTDP = new double[] { 4, 28 };
- GfxClock = new double[] { 100, 2200 };
+ GfxClock = new double[] { 100, 2200 };
CpuClock = 4700;
AccelerometerAxis = new Vector3(-1.0f, 1.0f, 1.0f);
@@ -37,8 +37,8 @@ public OneXPlayerMiniPro()
new List { KeyCode.LWin, KeyCode.D },
false, ButtonFlags.OEM3
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerOneXFly.cs b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerOneXFly.cs
index f462cd74c..f304c87c0 100644
--- a/HandheldCompanion/Devices/OneXPlayer/OneXPlayerOneXFly.cs
+++ b/HandheldCompanion/Devices/OneXPlayer/OneXPlayerOneXFly.cs
@@ -1,11 +1,11 @@
using HandheldCompanion.Inputs;
using HandheldCompanion.Managers;
-using HidLibrary;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Windows.Media;
-using WindowsInput.Events;
+using HidLibrary;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Media;
+using WindowsInput.Events;
namespace HandheldCompanion.Devices;
using static HandheldCompanion.Utils.DeviceUtils;
@@ -17,14 +17,14 @@ public OneXPlayerOneXFly()
{
// device specific settings
ProductIllustration = "device_onexplayer_onexfly";
- ProductModel = "ONEXPLAYEROneXFly";
-
- // https://www.amd.com/en/products/apu/amd-ryzen-z1
- // https://www.amd.com/en/products/apu/amd-ryzen-z1-extreme
- // https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
+ ProductModel = "ONEXPLAYEROneXFly";
+
+ // https://www.amd.com/en/products/apu/amd-ryzen-z1
+ // https://www.amd.com/en/products/apu/amd-ryzen-z1-extreme
+ // https://www.amd.com/en/products/apu/amd-ryzen-7-7840u
nTDP = new double[] { 15, 15, 20 };
cTDP = new double[] { 5, 30 };
- GfxClock = new double[] { 100, 2700 };
+ GfxClock = new double[] { 100, 2700 };
CpuClock = 5100;
GyrometerAxisSwap = new SortedDictionary
@@ -39,14 +39,14 @@ public OneXPlayerOneXFly()
{ 'X', 'X' },
{ 'Y', 'Z' },
{ 'Z', 'Y' }
- };
-
- // device specific capacities
- Capabilities = DeviceCapabilities.FanControl;
- Capabilities |= DeviceCapabilities.DynamicLighting;
- DynamicLightingCapabilities |= LEDLevel.SolidColor;
- DynamicLightingCapabilities |= LEDLevel.Rainbow;
- Capabilities |= DeviceCapabilities.DynamicLightingBrightness;
+ };
+
+ // device specific capacities
+ Capabilities = DeviceCapabilities.FanControl;
+ Capabilities |= DeviceCapabilities.DynamicLighting;
+ Capabilities |= DeviceCapabilities.DynamicLightingBrightness;
+ DynamicLightingCapabilities |= LEDLevel.SolidColor;
+ DynamicLightingCapabilities |= LEDLevel.Rainbow;
ECDetails = new ECDetails
{
@@ -56,12 +56,12 @@ public OneXPlayerOneXFly()
AddressDataPort = 0x4F,
FanValueMin = 11,
FanValueMax = 255
- };
-
- // LED HID Device
- _vid = 0x1A2C;
- _pid = 0xB001;
-
+ };
+
+ // LED HID Device
+ _vid = 0x1A2C;
+ _pid = 0xB001;
+
OEMChords.Add(new DeviceChord("Turbo",
new List { KeyCode.LControl, KeyCode.LWin, KeyCode.LMenu },
new List { KeyCode.LMenu, KeyCode.LWin, KeyCode.LControl },
@@ -105,172 +105,172 @@ public override string GetGlyph(ButtonFlags button)
return "\u2210";
case ButtonFlags.OEM3:
return "\u2219";
- case ButtonFlags.OEM4:
- return "\u2212";
- case ButtonFlags.OEM5:
+ case ButtonFlags.OEM4:
+ return "\u2212";
+ case ButtonFlags.OEM5:
return "\u2213";
}
return defaultGlyph;
- }
-
- public override bool Open()
- {
- var success = base.Open();
- if (!success)
- return false;
-
- // allow OneX turbo button to pass key inputs
- LogManager.LogInformation("Unlocked {0} OEM button", ButtonFlags.OEM1);
-
- ECRamDirectWrite(0x4F1, ECDetails, 0x40);
-
- return (ECRamReadByte(0x4F1, ECDetails) == 0x40);
- }
-
- public override void Close()
- {
- LogManager.LogInformation("Locked {0} OEM button", ButtonFlags.OEM1);
- ECRamDirectWrite(0x4F1, ECDetails, 0x00);
- base.Close();
- }
-
- public override bool IsReady()
- {
- // Prepare list for all HID devices
- HidDevice[] HidDeviceList = HidDevices.Enumerate(_vid, new int[] { _pid }).ToArray();
-
- // Check every HID device to find LED device
- foreach (HidDevice device in HidDeviceList)
- {
- // OneXFly device for LED control does not support a FeatureReport, hardcoded to match the Interface Number
- if (device.IsConnected && device.DevicePath.Contains("&mi_00"))
- {
- hidDevice = device;
- return true;
- }
- }
-
- return false;
- }
-
- public override bool SetLedBrightness(int brightness)
- {
- // OneXFly brightness range is: 0 - 4 range, 0 is off, convert from 0 - 100 % range
- brightness = (int)Math.Round(brightness / 20.0);
-
- // Check if device is availible
- if (hidDevice is null || !hidDevice.IsConnected)
- return false;
-
- // Define the HID message for setting brightness.
- byte[] msg = { 0x00, 0x07, 0xFF, 0xFD, 0x01, 0x05, (byte)brightness };
-
- // Write the HID message to set the LED brightness.
- hidDevice.Write(msg);
-
- return true;
- }
-
- public override bool SetLedColor(Color mainColor, Color secondaryColor, LEDLevel level, int speed = 100)
- {
- if (!DynamicLightingCapabilities.HasFlag(level))
- return false;
-
- // Data message consists of a prefix, LED option, RGB data, and closing byte (0x00)
- byte[] prefix = { 0x00, 0x07, 0xFF };
- byte[] LEDOption = { 0x00 };
- byte[] rgbData = { 0x00 };
-
- // Perform functions and command build-up based on LED level
- switch (level)
- {
- case LEDLevel.SolidColor:
- // Find nearest possible color due to RGB limitations of the device
- Color ledColor = FindClosestColor(mainColor);
-
- LEDOption = new byte[] { 0xFE };
-
- // RGB data repeats 20 times, fill accordingly
- rgbData = Enumerable.Repeat(new[] { ledColor.R, ledColor.G, ledColor.B }, 20)
- .SelectMany(colorBytes => colorBytes)
- .ToArray();
- break;
-
- case LEDLevel.Rainbow:
- // OneXConsole "Flowing Light" effect as a rainbow effect
- LEDOption = new byte[] { 0x03 };
-
- // RGB data empty, repeats 60 times, fill accordingly
- rgbData = Enumerable.Repeat((byte)0x00, 60).ToArray();
- break;
-
- default:
- return false;
- }
-
- // Check if device is availible
- if (hidDevice is null || !hidDevice.IsConnected)
- return false;
-
- // Combine prefix, LED Option, RGB data, and closing byte (0x00)
- byte[] msg = prefix.Concat(LEDOption).Concat(rgbData).Concat(new byte[] { 0x00 }).ToArray();
-
- // Write the HID message to set the RGB color effect
- hidDevice.Write(msg);
-
- return true;
- }
-
- static Color FindClosestColor(Color inputColor)
- {
- // Predefined colors that work on the device
- Color[] predefinedColors = new Color[]
- {
- Color.FromRgb(255, 0, 0), // Red (255,0,0)
- Color.FromRgb(255, 82, 0), // Orange (255, 165, 0)
- Color.FromRgb(255, 255, 0), // Yellow (255, 255, 0)
- Color.FromRgb(130, 255, 0), // Lime Green (50, 205, 50)
- Color.FromRgb(0, 255, 0), // Green (0, 128, 0)
- Color.FromRgb(0, 255, 110), // Turquoise (Cyan) (0, 255, 255)
- Color.FromRgb(0, 255, 255), // Teal (0, 128, 128)
- Color.FromRgb(130, 255, 255), // Blue (? ? ?)
- Color.FromRgb(0, 0, 255), // Dark Blue (? ? ?)
- Color.FromRgb(122, 0, 255), // Purple (Violet) (128, 0, 128)
- Color.FromRgb(255, 0, 255), // Pink (255, 182, 193)
- Color.FromRgb(255, 0, 129), // Magenta (255, 0, 255)
- };
-
- // Initialize with the first color
- Color closestColor = predefinedColors[0];
- double minDistance = CalculateDistance(inputColor, closestColor);
-
- // Iterate through predefined colors to find the closest one
- foreach (var predefinedColor in predefinedColors)
- {
- double distance = CalculateDistance(inputColor, predefinedColor);
-
- // Update closest color if a closer one is found
- if (distance < minDistance)
- {
- minDistance = distance;
- closestColor = predefinedColor;
- }
- }
-
- // Return the closest predefined color
- return closestColor;
- }
-
- static double CalculateDistance(Color color1, Color color2)
- {
- // Helper method to calculate the Euclidean distance between two colors
-
- int deltaR = color2.R - color1.R;
- int deltaG = color2.G - color1.G;
- int deltaB = color2.B - color1.B;
-
- // Euclidean distance formula
- return Math.Sqrt(deltaR * deltaR + deltaG * deltaG + deltaB * deltaB);
- }
+ }
+
+ public override bool Open()
+ {
+ var success = base.Open();
+ if (!success)
+ return false;
+
+ // allow OneX turbo button to pass key inputs
+ LogManager.LogInformation("Unlocked {0} OEM button", ButtonFlags.OEM1);
+
+ ECRamDirectWrite(0x4F1, ECDetails, 0x40);
+
+ return (ECRamReadByte(0x4F1, ECDetails) == 0x40);
+ }
+
+ public override void Close()
+ {
+ LogManager.LogInformation("Locked {0} OEM button", ButtonFlags.OEM1);
+ ECRamDirectWrite(0x4F1, ECDetails, 0x00);
+ base.Close();
+ }
+
+ public override bool IsReady()
+ {
+ // Prepare list for all HID devices
+ HidDevice[] HidDeviceList = HidDevices.Enumerate(_vid, new int[] { _pid }).ToArray();
+
+ // Check every HID device to find LED device
+ foreach (HidDevice device in HidDeviceList)
+ {
+ // OneXFly device for LED control does not support a FeatureReport, hardcoded to match the Interface Number
+ if (device.IsConnected && device.DevicePath.Contains("&mi_00"))
+ {
+ hidDevice = device;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public override bool SetLedBrightness(int brightness)
+ {
+ // OneXFly brightness range is: 0 - 4 range, 0 is off, convert from 0 - 100 % range
+ brightness = (int)Math.Round(brightness / 20.0);
+
+ // Check if device is availible
+ if (hidDevice is null || !hidDevice.IsConnected)
+ return false;
+
+ // Define the HID message for setting brightness.
+ byte[] msg = { 0x00, 0x07, 0xFF, 0xFD, 0x01, 0x05, (byte)brightness };
+
+ // Write the HID message to set the LED brightness.
+ hidDevice.Write(msg);
+
+ return true;
+ }
+
+ public override bool SetLedColor(Color mainColor, Color secondaryColor, LEDLevel level, int speed = 100)
+ {
+ if (!DynamicLightingCapabilities.HasFlag(level))
+ return false;
+
+ // Data message consists of a prefix, LED option, RGB data, and closing byte (0x00)
+ byte[] prefix = { 0x00, 0x07, 0xFF };
+ byte[] LEDOption = { 0x00 };
+ byte[] rgbData = { 0x00 };
+
+ // Perform functions and command build-up based on LED level
+ switch (level)
+ {
+ case LEDLevel.SolidColor:
+ // Find nearest possible color due to RGB limitations of the device
+ Color ledColor = FindClosestColor(mainColor);
+
+ LEDOption = new byte[] { 0xFE };
+
+ // RGB data repeats 20 times, fill accordingly
+ rgbData = Enumerable.Repeat(new[] { ledColor.R, ledColor.G, ledColor.B }, 20)
+ .SelectMany(colorBytes => colorBytes)
+ .ToArray();
+ break;
+
+ case LEDLevel.Rainbow:
+ // OneXConsole "Flowing Light" effect as a rainbow effect
+ LEDOption = new byte[] { 0x03 };
+
+ // RGB data empty, repeats 60 times, fill accordingly
+ rgbData = Enumerable.Repeat((byte)0x00, 60).ToArray();
+ break;
+
+ default:
+ return false;
+ }
+
+ // Check if device is availible
+ if (hidDevice is null || !hidDevice.IsConnected)
+ return false;
+
+ // Combine prefix, LED Option, RGB data, and closing byte (0x00)
+ byte[] msg = prefix.Concat(LEDOption).Concat(rgbData).Concat(new byte[] { 0x00 }).ToArray();
+
+ // Write the HID message to set the RGB color effect
+ hidDevice.Write(msg);
+
+ return true;
+ }
+
+ static Color FindClosestColor(Color inputColor)
+ {
+ // Predefined colors that work on the device
+ Color[] predefinedColors = new Color[]
+ {
+ Color.FromRgb(255, 0, 0), // Red (255,0,0)
+ Color.FromRgb(255, 82, 0), // Orange (255, 165, 0)
+ Color.FromRgb(255, 255, 0), // Yellow (255, 255, 0)
+ Color.FromRgb(130, 255, 0), // Lime Green (50, 205, 50)
+ Color.FromRgb(0, 255, 0), // Green (0, 128, 0)
+ Color.FromRgb(0, 255, 110), // Turquoise (Cyan) (0, 255, 255)
+ Color.FromRgb(0, 255, 255), // Teal (0, 128, 128)
+ Color.FromRgb(130, 255, 255), // Blue (? ? ?)
+ Color.FromRgb(0, 0, 255), // Dark Blue (? ? ?)
+ Color.FromRgb(122, 0, 255), // Purple (Violet) (128, 0, 128)
+ Color.FromRgb(255, 0, 255), // Pink (255, 182, 193)
+ Color.FromRgb(255, 0, 129), // Magenta (255, 0, 255)
+ };
+
+ // Initialize with the first color
+ Color closestColor = predefinedColors[0];
+ double minDistance = CalculateDistance(inputColor, closestColor);
+
+ // Iterate through predefined colors to find the closest one
+ foreach (var predefinedColor in predefinedColors)
+ {
+ double distance = CalculateDistance(inputColor, predefinedColor);
+
+ // Update closest color if a closer one is found
+ if (distance < minDistance)
+ {
+ minDistance = distance;
+ closestColor = predefinedColor;
+ }
+ }
+
+ // Return the closest predefined color
+ return closestColor;
+ }
+
+ static double CalculateDistance(Color color1, Color color2)
+ {
+ // Helper method to calculate the Euclidean distance between two colors
+
+ int deltaR = color2.R - color1.R;
+ int deltaG = color2.G - color1.G;
+ int deltaB = color2.B - color1.B;
+
+ // Euclidean distance formula
+ return Math.Sqrt(deltaR * deltaR + deltaG * deltaG + deltaB * deltaB);
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Devices/Valve/SteamDeck.cs b/HandheldCompanion/Devices/Valve/SteamDeck.cs
index 5af187486..82866112d 100644
--- a/HandheldCompanion/Devices/Valve/SteamDeck.cs
+++ b/HandheldCompanion/Devices/Valve/SteamDeck.cs
@@ -27,13 +27,27 @@ public class SteamDeck : IDevice
private static readonly IntPtr PDFV = new(0xFE700C00 + 0x4C);
private static readonly IntPtr XBID = new(0xFE700300 + 0xBD);
private static readonly IntPtr PDCT = new(0xFE700C00 + 0x01);
+
+ /*
+ * SteamDeck LCD:
+ * F7A0107 (PD ver: 0xB030)
+ * F7A0110 (PD ver: 0xB030)
+ * F7A0113 (PD ver: 0xB030)
+ * F7A0115 (PD ver: 0xB030)
+ * F7A0116 (PD ver: 0xB030)
+ * F7A0119 (PD ver: 0xB030)
+ *
+ * SteamDeck OLED:
+ * F7G0107 (PD ver: 0x1050)
+ */
public static readonly ushort[] SupportedFirmwares =
{
// Steam Deck - LCD version
0xB030,
// Steam Deck - OLED version
- 0x1030,
+ 0x1050, // BIOS 107
+ 0x1030, // BIOS 105
0x1010,
};
@@ -70,15 +84,15 @@ public SteamDeck()
cTDP = new double[] { 4, 15 };
// https://www.techpowerup.com/gpu-specs/steam-deck-gpu.c3897
- GfxClock = new double[] { 200, 1600 };
+ GfxClock = new double[] { 200, 1600 };
CpuClock = 3500;
OEMChords.Add(new DeviceChord("...",
new List(), new List(),
false, ButtonFlags.OEM1
));
- }
-
+ }
+
public override string GetGlyph(ButtonFlags button)
{
switch (button)
diff --git a/HandheldCompanion/HandheldCompanion.csproj b/HandheldCompanion/HandheldCompanion.csproj
index f221723e8..3b10e4848 100644
--- a/HandheldCompanion/HandheldCompanion.csproj
+++ b/HandheldCompanion/HandheldCompanion.csproj
@@ -12,7 +12,7 @@
HandheldCompanion.App
$(SolutionDir)bin\$(Configuration)
Resources\icon.ico
- 0.19.1.8
+ 0.20.3.0
app.manifest
AnyCPU;x64;x86
true
@@ -42,13 +42,6 @@
pdbonly
true
-
-
-
-
-
-
-
@@ -71,6 +64,7 @@
+
@@ -111,6 +105,7 @@
+
@@ -148,12 +143,13 @@
-
+
+
-
-
-
+
+
+
@@ -172,8 +168,8 @@
-
-
+
+
@@ -224,7 +220,10 @@
-
+
+ PreserveNewest
+
+
PreserveNewest
@@ -2286,12 +2285,6 @@
..\Resources\HidLibrary.dll
-
- ..\Resources\Inkore.UI.WPF.Modern.dll
-
-
- ..\Resources\Inkore.UI.WPF.Modern.Controls.dll
-
..\Resources\Microsoft.Win32.TaskScheduler.dll
@@ -2310,9 +2303,6 @@
$(DefaultXamlRuntime)
-
- $(DefaultXamlRuntime)
-
$(DefaultXamlRuntime)
diff --git a/HandheldCompanion/Helpers/VangoghGPU.cs b/HandheldCompanion/Helpers/VangoghGPU.cs
index 3f358c8c8..d04ba8521 100644
--- a/HandheldCompanion/Helpers/VangoghGPU.cs
+++ b/HandheldCompanion/Helpers/VangoghGPU.cs
@@ -10,12 +10,19 @@ internal class VangoghGPU : IDisposable
{
public static readonly Device[] SupportedDevices =
{
- // SteamDeck
+ // SteamDeck LCD
new Device("AMD Custom GPU 0405", 0x80300000, 0x8037ffff, new uint[] { 0x43F3900, 0x43F3C05, 0x43F3E00 }),
+ // SteamDeck OLED
+ // BIOS 105
+ new Device("AMD Custom GPU 0932", 0x80600000, 0x8067ffff, new uint[] { 0x063F0E00 }),
+ // BIOS 107
+ new Device("AMD Custom GPU 0932", 0x80500000, 0x8057ffff, new uint[] { 0x063F0F00 }),
+
// SteamDeck unofficial APU drivers
// https://sourceforge.net/projects/amernimezone/files/Release%20Polaris-Vega-Navi/AMD%20SOC%20Driver%20Variant/
new Device("AMD Radeon 670M", 0x80300000, 0x8037ffff, new uint[] { 0x43F3900, 0x43F3C05, 0x43F3E00 }),
+ new Device("AMD Radeon RX 670 Graphics", 0x80300000, 0x8037ffff, new uint[] { 0x43F3900, 0x43F3C05, 0x43F3E00 }),
};
private static Device? DetectedDevice;
diff --git a/HandheldCompanion/Managers/ControllerManager.cs b/HandheldCompanion/Managers/ControllerManager.cs
index aeb63fdd1..a10bfb901 100644
--- a/HandheldCompanion/Managers/ControllerManager.cs
+++ b/HandheldCompanion/Managers/ControllerManager.cs
@@ -5,6 +5,7 @@
using HandheldCompanion.Utils;
using HandheldCompanion.Views;
using HandheldCompanion.Views.Classes;
+using HandheldCompanion.Views.Pages;
using Nefarius.Utilities.DeviceManagement.Drivers;
using Nefarius.Utilities.DeviceManagement.Extensions;
using Nefarius.Utilities.DeviceManagement.PnP;
@@ -608,6 +609,8 @@ private static async void HidDeviceRemoved(PnPDetails details, DeviceEventArgs o
// unplug controller, if needed
if (GetTargetController()?.GetContainerInstancePath() == details.baseContainerDeviceInstanceId)
ClearTargetController();
+ else
+ controller.Unplug();
// controller was unplugged
Controllers.TryRemove(details.baseContainerDeviceInstanceId, out _);
@@ -843,6 +846,8 @@ private static async void XUsbDeviceRemoved(PnPDetails details, DeviceEventArgs
// controller is current target
if (targetController?.GetContainerInstancePath() == details.baseContainerDeviceInstanceId)
ClearTargetController();
+ else
+ controller.Unplug();
}
LogManager.LogDebug("XInput controller {0} unplugged", controller.ToString());
@@ -862,7 +867,6 @@ private static void ClearTargetController()
{
targetController.InputsUpdated -= UpdateInputs;
targetController.SetLightColor(0, 0, 0);
- targetController.Cleanup();
targetController.Unplug();
targetController = null;
@@ -1100,7 +1104,17 @@ private static void UpdateInputs(ControllerState controllerState)
internal static IController GetEmulatedController()
{
- var HIDmode = (HIDmode)SettingsManager.GetInt("HIDmode", true);
+ // get HIDmode for the selected profile (could be different than HIDmode in settings if profile has HIDmode)
+ HIDmode HIDmode = HIDmode.NoController;
+
+ // if profile is selected, get its HIDmode
+ if (ProfilesPage.selectedProfile != null)
+ HIDmode = ProfilesPage.selectedProfile.HID;
+
+ // if profile HID is NotSelected, use HIDmode from settings
+ if (HIDmode == HIDmode.NotSelected)
+ HIDmode = (HIDmode)SettingsManager.GetInt("HIDmode", true);
+
switch (HIDmode)
{
default:
diff --git a/HandheldCompanion/Managers/Desktop/DesktopScreen.cs b/HandheldCompanion/Managers/Desktop/DesktopScreen.cs
index 6a58e37ac..3f37fc492 100644
--- a/HandheldCompanion/Managers/Desktop/DesktopScreen.cs
+++ b/HandheldCompanion/Managers/Desktop/DesktopScreen.cs
@@ -8,7 +8,7 @@ namespace HandheldCompanion.Managers.Desktop;
public class ScreenResolution
{
- public SortedDictionary Frequencies;
+ public SortedList Frequencies;
public int Height;
public int Width;
public int BitsPerPel;
@@ -18,7 +18,7 @@ public ScreenResolution(int dmPelsWidth, int dmPelsHeight, int bitsPerPel)
Width = dmPelsWidth;
Height = dmPelsHeight;
BitsPerPel = bitsPerPel;
- Frequencies = new SortedDictionary(Comparer.Create((x, y) => y.CompareTo(x)));
+ Frequencies = new(Comparer.Create((x, y) => y.CompareTo(x)));
}
public override string ToString()
@@ -27,44 +27,41 @@ public override string ToString()
}
}
-public enum Frequency
+public class ScreenFramelimit
{
- Quarter = 0,
- Third = 1,
- Half = 2,
- Full = 3
-}
-
-public class ScreenFrequency
-{
- private readonly SortedDictionary Frequencies = new();
+ public int index;
+ public int limit;
- public ScreenFrequency(int frequency)
+ public ScreenFramelimit(int index, int limit)
{
- Frequencies[Frequency.Quarter] = Math.Round(frequency / 4.0d, 1);
- Frequencies[Frequency.Third] = Math.Round(frequency / 3.0d, 1);
- Frequencies[Frequency.Half] = Math.Round(frequency / 2.0d, 1);
- Frequencies[Frequency.Full] = frequency;
+ this.index = index;
+ this.limit = limit;
}
- public double GetValue(Frequency frequency)
+ public override string ToString()
{
- return Frequencies[frequency];
+ if (limit == 0)
+ return "Disabled";
+
+ return $"{limit} FPS";
}
+}
- public override string ToString()
+public class ScreenDivider
+{
+ public int divider;
+ public ScreenResolution resolution;
+
+ public ScreenDivider(int divider, ScreenResolution resolution)
{
- return $"{Frequencies[Frequency.Full]} Hz";
+ this.divider = divider;
+ this.resolution = resolution;
}
- public override bool Equals(object obj)
+ // todo: localize me
+ public override string ToString()
{
- if (obj is ScreenFrequency frequency)
- foreach (var freq in (Frequency[])Enum.GetValues(typeof(Frequency)))
- if (Frequencies[freq] != frequency.Frequencies[freq])
- return false;
-
- return true;
+ return $"1/{divider} ({resolution.Width}x{resolution.Height})";
}
}
@@ -131,17 +128,19 @@ public class DesktopScreen
{
public Display devMode;
public Screen PrimaryScreen;
- public List resolutions;
+ public List screenResolutions = new();
+ public List screenDividers = new();
+
+ private static Dictionary> _cachedFrameLimits = new();
public DesktopScreen(Screen primaryScreen)
{
PrimaryScreen = primaryScreen;
- resolutions = new List();
}
public bool HasResolution(ScreenResolution resolution)
{
- return resolutions.Count(a => a.Width == resolution.Width && a.Height == resolution.Height) > 0;
+ return screenResolutions.Count(a => a.Width == resolution.Width && a.Height == resolution.Height) > 0;
}
public ScreenResolution GetResolution(int dmPelsWidth, int dmPelsHeight)
@@ -167,16 +166,97 @@ public ScreenResolution GetResolution(int dmPelsWidth, int dmPelsHeight)
}
*/
- return resolutions.FirstOrDefault(a => a.Width == width && a.Height == height);
+ return screenResolutions.FirstOrDefault(a => a.Width == width && a.Height == height);
+ }
+
+ public int GetCurrentFrequency()
+ {
+ return devMode.dmDisplayFrequency;
+ }
+
+ // A function that takes a screen frequency int value and returns a list of integer values that are the quotient of the frequency and the closest divisor
+ public List GetFramelimits()
+ {
+ // A list to store the quotients
+ List Limits = [new(0,0)]; // (Comparer.Create((x, y) => y.CompareTo(x)));
+
+ // A variable to store the divider value, rounded to nearest even number
+ int divider = 1;
+ int dmDisplayFrequency = RoundToEven(devMode.dmDisplayFrequency);
+
+ if (_cachedFrameLimits.ContainsKey(dmDisplayFrequency)) { return _cachedFrameLimits[dmDisplayFrequency]; }
+
+ int lowestFPS = dmDisplayFrequency;
+
+ HashSet fpsLimits = new();
+
+ // A loop to find the lowest possible fps limit option and limits from division
+ do
+ {
+ // If the frequency is divisible by the divider, add the quotient to the list
+ if (dmDisplayFrequency % divider == 0)
+ {
+ int frequency = dmDisplayFrequency / divider;
+ if (frequency < 20)
+ {
+ break;
+ }
+ fpsLimits.Add(frequency);
+ lowestFPS = frequency;
+ }
+
+ // Increase the divider by 1
+ divider++;
+ } while (true);
+
+ // loop to fill all possible fps limit options from lowest fps limit (e.g. getting 40FPS dor 60Hz)
+ int nrOptions = dmDisplayFrequency / lowestFPS;
+ for (int i = 1; i < nrOptions; i++)
+ {
+ fpsLimits.Add(lowestFPS * i);
+ }
+
+ // Fill limits
+
+ var orderedFpsLimits = fpsLimits.OrderByDescending(f => f);
+
+ for (int i = 0; i < orderedFpsLimits.Count(); i++)
+ {
+ Limits.Add(new(i+1, orderedFpsLimits.ElementAt(i)));
+ }
+
+ _cachedFrameLimits.Add(dmDisplayFrequency, Limits);
+ // Return the list of quotients
+ return Limits;
+ }
+
+ public ScreenFramelimit GetClosest(int fps)
+ {
+ List limits = GetFramelimits();
+
+ ScreenFramelimit? fpsInLimits = limits.FirstOrDefault(l => l.limit == fps);
+ if (fpsInLimits is not null) { return fpsInLimits; }
+
+ var diffs = GetFramelimits().Select(limit => (Math.Abs(fps - limit.limit), limit))
+ .OrderBy(g => g.Item1).ThenBy(g => g.limit.limit).ToList();
+
+ var lowestDiff = diffs.First().Item1;
+ var lowestDiffs = diffs.Where(d => d.Item1 == lowestDiff);
+
+ return lowestDiffs.Last().limit;
}
- public ScreenFrequency GetFrequency()
+ // A function that takes an int as a parameter and returns the closest multiple of 10
+ private int RoundToEven(int num)
{
- return new ScreenFrequency(devMode.dmDisplayFrequency);
+ if (num % 2 == 0)
+ return num;
+
+ return num + 1;
}
public void SortResolutions()
{
- resolutions = resolutions.OrderByDescending(a => a.Width).ThenByDescending(b => b.Height).ToList();
+ screenResolutions = screenResolutions.OrderByDescending(a => a.Width).ThenByDescending(b => b.Height).ToList();
}
}
\ No newline at end of file
diff --git a/HandheldCompanion/Managers/DynamicLightingManager.cs b/HandheldCompanion/Managers/DynamicLightingManager.cs
index d63f176fb..747228bbb 100644
--- a/HandheldCompanion/Managers/DynamicLightingManager.cs
+++ b/HandheldCompanion/Managers/DynamicLightingManager.cs
@@ -131,7 +131,6 @@ private static void InitializeDirect3DDevice()
else
{
// Handle other exceptions here
- throw;
}
}
}
@@ -153,6 +152,7 @@ private static void SettingsManager_SettingValueChanged(string name, object valu
case "LEDSecondColor":
case "LEDSettingsLevel":
case "LEDSpeed":
+ case "LEDUseSecondColor":
RequestUpdate();
break;
@@ -190,6 +190,7 @@ private static void UpdateLED()
// Get colors
Color LEDMainColor = SettingsManager.GetColor("LEDMainColor");
Color LEDSecondColor = SettingsManager.GetColor("LEDSecondColor");
+ bool useSecondColor = SettingsManager.GetBoolean("LEDUseSecondColor");
switch (LEDSettingsLevel)
{
@@ -199,7 +200,7 @@ private static void UpdateLED()
{
StopAmbilight();
- MainWindow.CurrentDevice.SetLedColor(LEDMainColor, LEDMainColor, LEDSettingsLevel, LEDSpeed);
+ MainWindow.CurrentDevice.SetLedColor(LEDMainColor, useSecondColor ? LEDSecondColor : LEDMainColor, LEDSettingsLevel, LEDSpeed);
}
break;
@@ -272,7 +273,7 @@ private static void ambilightThreadLoop(object? obj)
Color averageColorRight = rightLedTracker.CalculateAverageColor();
// Only send HID update instruction if the color is different
- if (averageColorLeft != previousColorLeft && averageColorRight != previousColorRight)
+ if (averageColorLeft != previousColorLeft || averageColorRight != previousColorRight)
{
// Change LED colors of the device
MainWindow.CurrentDevice.SetLedColor(averageColorLeft, averageColorRight, LEDLevel.Ambilight);
diff --git a/HandheldCompanion/Managers/GamepadFocusManager.cs b/HandheldCompanion/Managers/GamepadFocusManager.cs
index b1ea5af8e..6fad8e708 100644
--- a/HandheldCompanion/Managers/GamepadFocusManager.cs
+++ b/HandheldCompanion/Managers/GamepadFocusManager.cs
@@ -5,17 +5,18 @@
using HandheldCompanion.Views;
using HandheldCompanion.Views.Classes;
using HandheldCompanion.Views.Windows;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Navigation;
using System.Xml.Linq;
-using Frame = Inkore.UI.WPF.Modern.Controls.Frame;
+using Frame = iNKORE.UI.WPF.Modern.Controls.Frame;
using Page = System.Windows.Controls.Page;
using Timer = System.Timers.Timer;
@@ -208,6 +209,7 @@ private void _gamepadFrame_PageRendered(object? sender, System.Timers.ElapsedEve
case "quickperformance":
case "quickprofiles":
case "quicksuspender":
+ case "quickoverlay":
_goingForward = true;
break;
}
@@ -252,11 +254,24 @@ public void Focus(Control control)
if (control is null)
return;
+ // set tooltip on focus
+ ToolTipService.SetShowsToolTipOnKeyboardFocus(control, true);
+
+ // set tooltip initial delay
+ string controlType = control.GetType().Name;
+ switch (controlType)
+ {
+ case "Slider":
+ ToolTipService.SetInitialShowDelay(control, 0);
+ break;
+ default:
+ ToolTipService.SetInitialShowDelay(control, 250);
+ break;
+ }
+
// set focus to control
Keyboard.Focus(control);
control.Focus();
-
- ToolTipService.SetShowsToolTipOnKeyboardFocus(control, true);
control.BringIntoView();
}
@@ -348,6 +363,12 @@ public Control FocusedElement(GamepadWindow window)
return null;
}
+
+ // declare a DateTime variable to store the last time the function was called
+ private DateTime lastCallTime;
+
+ // declare a DateTime variable to store the last time the button state changed
+ private DateTime lastChangeTime;
private void InputsUpdated(ControllerState controllerState)
{
@@ -358,10 +379,41 @@ private void InputsUpdated(ControllerState controllerState)
if (InputsManager.IsListening)
return;
- if (controllerState.ButtonState.Equals(prevButtonState))
- return;
+ // get the current time
+ DateTime currentTime = DateTime.Now;
- prevButtonState = controllerState.ButtonState.Clone() as ButtonState;
+ // check if the button state is equal to the previous button state
+ if (controllerState.ButtonState.Equals(prevButtonState))
+ {
+ if (controllerState.ButtonState.Buttons.Any())
+ {
+ // check if the button state has been the same for at least 600ms
+ if ((currentTime - lastChangeTime).TotalMilliseconds >= 600)
+ {
+ // check if the function has been called within the last 120ms
+ if ((currentTime - lastCallTime).TotalMilliseconds >= 120)
+ {
+ // update the last call time
+ lastCallTime = currentTime;
+ }
+ else
+ {
+ return;
+ }
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+ else
+ {
+ // update the last change time and the last call time
+ lastChangeTime = currentTime;
+ lastCallTime = currentTime;
+ prevButtonState = controllerState.ButtonState.Clone() as ButtonState;
+ }
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
@@ -458,6 +510,7 @@ private void InputsUpdated(ControllerState controllerState)
case "quickperformance":
case "quickprofiles":
case "quicksuspender":
+ case "quickoverlay":
{
// set state
_goingBack = true;
@@ -495,6 +548,7 @@ private void InputsUpdated(ControllerState controllerState)
case "quickperformance":
case "quickprofiles":
case "quicksuspender":
+ case "quickoverlay":
{
// set state
_goingBack = true;
diff --git a/HandheldCompanion/Managers/Hotkeys/Hotkey.cs b/HandheldCompanion/Managers/Hotkeys/Hotkey.cs
index cc0cf7334..08f567b71 100644
--- a/HandheldCompanion/Managers/Hotkeys/Hotkey.cs
+++ b/HandheldCompanion/Managers/Hotkeys/Hotkey.cs
@@ -2,14 +2,14 @@
using HandheldCompanion.Controls;
using HandheldCompanion.Properties;
using HandheldCompanion.Views;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Newtonsoft.Json;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
-using System.Windows.Media.Animation;
+using System.Windows.Media.Animation;
using static HandheldCompanion.Managers.InputsHotkey;
using static HandheldCompanion.Managers.InputsManager;
@@ -47,14 +47,14 @@ public Hotkey()
};
quickControl.QuickButton.Click += async (e, sender) =>
- {
- // special case HIDmode switch hotkey
- // required here in order to (immediatly) disable hotkey while HIDmode is being changed to avoid duplicates
- // this takes care of repeated button clicks
- if (this.inputsHotkey.Listener == "shortcutChangeHIDMode")
- {
- this.IsEnabled = false;
- }
+ {
+ // special case HIDmode switch hotkey
+ // required here in order to (immediatly) disable hotkey while HIDmode is being changed to avoid duplicates
+ // this takes care of repeated button clicks
+ if (this.inputsHotkey.Listener == "shortcutChangeHIDMode")
+ {
+ this.IsEnabled = false;
+ }
// workaround for gamepad navigation
await Task.Delay(100);
@@ -302,32 +302,32 @@ public void DrawInput()
foreach (var button in inputsChord.State.Buttons)
{
- UIElement? label = null;
- var fontIcon = new FontIcon();
-
- switch (button)
- {
- case Inputs.ButtonFlags.OEM1:
- case Inputs.ButtonFlags.OEM2:
- case Inputs.ButtonFlags.OEM3:
- case Inputs.ButtonFlags.OEM4:
- case Inputs.ButtonFlags.OEM5:
- case Inputs.ButtonFlags.OEM6:
- case Inputs.ButtonFlags.OEM7:
- case Inputs.ButtonFlags.OEM8:
- case Inputs.ButtonFlags.OEM9:
- case Inputs.ButtonFlags.OEM10:
- {
- //
- fontIcon = MainWindow.CurrentDevice.GetFontIcon(button);
- }
- break;
- default:
- {
- fontIcon = controller.GetFontIcon(button);
- }
- break;
- }
+ UIElement? label = null;
+ var fontIcon = new FontIcon();
+
+ switch (button)
+ {
+ case Inputs.ButtonFlags.OEM1:
+ case Inputs.ButtonFlags.OEM2:
+ case Inputs.ButtonFlags.OEM3:
+ case Inputs.ButtonFlags.OEM4:
+ case Inputs.ButtonFlags.OEM5:
+ case Inputs.ButtonFlags.OEM6:
+ case Inputs.ButtonFlags.OEM7:
+ case Inputs.ButtonFlags.OEM8:
+ case Inputs.ButtonFlags.OEM9:
+ case Inputs.ButtonFlags.OEM10:
+ {
+ //
+ fontIcon = MainWindow.CurrentDevice.GetFontIcon(button);
+ }
+ break;
+ default:
+ {
+ fontIcon = controller.GetFontIcon(button);
+ }
+ break;
+ }
// display only one label, default one is not enough
if (fontIcon.Glyph != IController.defaultGlyph)
diff --git a/HandheldCompanion/Managers/Hotkeys/InputsHotkey.cs b/HandheldCompanion/Managers/Hotkeys/InputsHotkey.cs
index 4c94d52f9..0003205c1 100644
--- a/HandheldCompanion/Managers/Hotkeys/InputsHotkey.cs
+++ b/HandheldCompanion/Managers/Hotkeys/InputsHotkey.cs
@@ -14,9 +14,10 @@ public enum InputsHotkeyType : ushort
Quicktools = 1,
Windows = 2,
HC = 3,
- Device = 4,
- Custom = 5,
- Embedded = 6
+ Profiles = 4,
+ Device = 5,
+ Custom = 6,
+ Embedded = 7
}
public static SortedDictionary InputsHotkeys = new()
@@ -32,7 +33,12 @@ public enum InputsHotkeyType : ushort
new InputsHotkey(InputsHotkeyType.Overlay, "\uEDA4", "overlayTrackpads", "Segoe Fluent Icons", 20, false,
true, null, string.Empty)
},
-
+ {
+ 03,
+ new InputsHotkey(InputsHotkeyType.Overlay, "\uE78B", "OnScreenDisplayToggle", "Segoe Fluent Icons", 20, false,
+ true, null, string.Empty, false, true)
+ },
+
// Quicktools hotkeys
{
10,
@@ -119,6 +125,20 @@ public enum InputsHotkeyType : ushort
true, null, string.Empty, true, false)
},
+ // Profiles hotkeys
+ {
+ 33,
+ new InputsHotkey(InputsHotkeyType.Profiles, "\uE81E", "previousSubProfile", "Segoe Fluent Icons", 20, false,
+ true, null, string.Empty, false, false)
+ },
+ {
+ 34,
+ new InputsHotkey(InputsHotkeyType.Profiles, "\uE81E", "nextSubProfile", "Segoe Fluent Icons", 20, false,
+ true, null, string.Empty, false, false)
+ },
+
+
+
// Device specific hotkeys
{
41,
diff --git a/HandheldCompanion/Managers/HotkeysManager.cs b/HandheldCompanion/Managers/HotkeysManager.cs
index 60db88d58..7b8894788 100644
--- a/HandheldCompanion/Managers/HotkeysManager.cs
+++ b/HandheldCompanion/Managers/HotkeysManager.cs
@@ -6,7 +6,7 @@
using HandheldCompanion.Simulators;
using HandheldCompanion.Utils;
using HandheldCompanion.Views;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -445,7 +445,7 @@ public static void TriggerRaised(string listener, InputsChord input, InputsHotke
if (sProcess is null || sProcess.Filter != ProcessEx.ProcessFilter.Allowed)
break;
- if (sProcess.IsSuspended())
+ if (sProcess.IsSuspended)
ProcessManager.ResumeProcess(sProcess);
else
ProcessManager.SuspendProcess(fProcess);
@@ -454,6 +454,25 @@ public static void TriggerRaised(string listener, InputsChord input, InputsHotke
case "shortcutKillApp":
if (fProcess is not null) fProcess.Process.Kill();
break;
+ case "OnScreenDisplayToggle":
+ {
+ // check current OSD level
+ // .. if 0 (disabled) -> set OSD level to LastOnScreenDisplayLevel
+ // .. else (enabled) -> set OSD level to 0
+ int currentOSDLevel = SettingsManager.GetInt("OnScreenDisplayLevel");
+ int lastOSDLevel = SettingsManager.GetInt("LastOnScreenDisplayLevel");
+
+ switch (currentOSDLevel)
+ {
+ case 0:
+ SettingsManager.SetProperty("OnScreenDisplayLevel", lastOSDLevel);
+ break;
+ default:
+ SettingsManager.SetProperty("OnScreenDisplayLevel", 0);
+ break;
+ }
+ }
+ break;
case "OnScreenDisplayLevel":
{
var value = !SettingsManager.GetBoolean(listener);
@@ -488,6 +507,18 @@ public static void TriggerRaised(string listener, InputsChord input, InputsHotke
break;
}
+ // Profiles
+ case "previousSubProfile":
+ {
+ ProfileManager.CycleSubProfiles(true);
+ break;
+ }
+ case "nextSubProfile":
+ {
+ ProfileManager.CycleSubProfiles(false);
+ break;
+ }
+
default:
KeyboardSimulator.KeyPress(input.OutputKeys.ToArray());
break;
diff --git a/HandheldCompanion/Managers/LayoutManager.cs b/HandheldCompanion/Managers/LayoutManager.cs
index c84928001..d075be267 100644
--- a/HandheldCompanion/Managers/LayoutManager.cs
+++ b/HandheldCompanion/Managers/LayoutManager.cs
@@ -9,6 +9,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Numerics;
using System.Threading.Tasks;
using System.Windows;
@@ -310,7 +311,7 @@ public static ControllerState MapController(ControllerState controllerState)
// except the main gyroscope state that's not re-mappable (6 values)
outputState.GyroState = controllerState.GyroState;
- foreach (var buttonState in controllerState.ButtonState.State)
+ foreach (KeyValuePair buttonState in controllerState.ButtonState.State)
{
ButtonFlags button = buttonState.Key;
bool value = buttonState.Value;
@@ -319,9 +320,10 @@ public static ControllerState MapController(ControllerState controllerState)
if (!currentLayout.ButtonLayout.TryGetValue(button, out List actions))
continue;
- foreach (var action in actions)
+ List sortedActions = actions.OrderByDescending(a => (int)a.pressType).ToList();
+ foreach (IActions action in sortedActions)
{
- switch (action.ActionType)
+ switch (action.actionType)
{
// button to button
case ActionType.Button:
@@ -350,10 +352,58 @@ public static ControllerState MapController(ControllerState controllerState)
}
break;
}
+
+ switch (action.actionState)
+ {
+ case ActionState.Aborted:
+ case ActionState.Stopped:
+ foreach (IActions action2 in sortedActions)
+ {
+ if (action2 == action)
+ continue;
+
+ if (!action2.Interruptable)
+ continue;
+
+ if (action2.actionState == ActionState.Succeed)
+ continue;
+
+ if (action2.actionState != ActionState.Stopped && action2.actionState != ActionState.Aborted)
+ action2.actionState = ActionState.Stopped;
+ }
+
+ if (action.actionState == ActionState.Aborted)
+ {
+ int idx = sortedActions.IndexOf(action);
+ if (idx < sortedActions.Count)
+ {
+ IActions nAction = sortedActions[idx + 1]; // next action
+ if (nAction.Interruptable)
+ nAction.actionState = ActionState.Forced;
+ }
+ }
+ break;
+
+ case ActionState.Running:
+ foreach (IActions action2 in sortedActions)
+ {
+ if (action2 == action)
+ continue;
+
+ if (!action2.Interruptable)
+ continue;
+
+ if (action2.actionState == ActionState.Succeed)
+ continue;
+
+ action2.actionState = ActionState.Suspended;
+ }
+ break;
+ }
}
}
- foreach (var axisLayout in currentLayout.AxisLayout)
+ foreach (KeyValuePair axisLayout in currentLayout.AxisLayout)
{
AxisLayoutFlags flags = axisLayout.Key;
@@ -371,7 +421,7 @@ public static ControllerState MapController(ControllerState controllerState)
if (action is null)
continue;
- switch (action.ActionType)
+ switch (action.actionType)
{
case ActionType.Joystick:
{
@@ -436,7 +486,7 @@ public static ControllerState MapController(ControllerState controllerState)
if (action is null)
continue;
- switch (action.ActionType)
+ switch (action.actionType)
{
case ActionType.Joystick:
{
diff --git a/HandheldCompanion/Managers/Manager.cs b/HandheldCompanion/Managers/Manager.cs
deleted file mode 100644
index 66b08c0a0..000000000
--- a/HandheldCompanion/Managers/Manager.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace HandheldCompanion.Managers;
-
-public abstract class Manager
-{
- public delegate void InitializedEventHandler();
-
- public bool IsEnabled { get; set; }
- public bool IsInitialized { get; set; }
- protected string InstallPath { get; set; }
-
- public event InitializedEventHandler Initialized;
-
- public virtual void Start()
- {
- IsInitialized = true;
- Initialized?.Invoke();
-
- LogManager.LogInformation("{0} has started", ToString());
- }
-
- public virtual void Stop()
- {
- IsInitialized = false;
-
- LogManager.LogInformation("{0} has stopped", ToString());
- }
-}
\ No newline at end of file
diff --git a/HandheldCompanion/Managers/MotionManager.cs b/HandheldCompanion/Managers/MotionManager.cs
index c8cf697db..ca140bd72 100644
--- a/HandheldCompanion/Managers/MotionManager.cs
+++ b/HandheldCompanion/Managers/MotionManager.cs
@@ -175,7 +175,7 @@ private static void CalculateMotion(ControllerState controllerState)
(gyroAction.MotionMode == MotionMode.On && !controllerState.ButtonState.ContainsTrue(gyroAction.MotionTrigger)) ||
(gyroAction.MotionMode == MotionMode.Toggle && gyroAction.MotionToggleStatus);
- bool MotionMapped = action?.ActionType != ActionType.Disabled;
+ bool MotionMapped = action?.actionType != ActionType.Disabled;
// update sensorFusion, only when needed
if (MotionMapped && MotionTriggered && (gyroAction.MotionInput == MotionInput.PlayerSpace ||
diff --git a/HandheldCompanion/Managers/OSDManager.cs b/HandheldCompanion/Managers/OSDManager.cs
index 2e7e5022b..f5ed370e5 100644
--- a/HandheldCompanion/Managers/OSDManager.cs
+++ b/HandheldCompanion/Managers/OSDManager.cs
@@ -5,7 +5,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
-using static HandheldCompanion.Platforms.HWiNFO;
namespace HandheldCompanion.Managers;
@@ -98,29 +97,6 @@ public static void Start()
RefreshTimer.Start();
}
- private static uint OSDIndex(this OSD? osd)
- {
- if (osd is null)
- return uint.MaxValue;
-
- var osdSlot = typeof(OSD).GetField("m_osdSlot",
- BindingFlags.NonPublic | BindingFlags.Instance);
- var value = osdSlot.GetValue(osd);
- if (value is null)
- return uint.MaxValue;
-
- return (uint)value;
- }
-
- private static uint OSDIndex(string name)
- {
- var entries = OSD.GetOSDEntries().ToList();
- for (var i = 0; i < entries.Count(); i++)
- if (entries[i].Owner == name)
- return (uint)i;
- return 0;
- }
-
private static void UpdateOSD()
{
if (OverlayLevel == 0)
@@ -151,9 +127,7 @@ private static void UpdateOSD()
public static string Draw(int processId)
{
- SensorElement sensor;
Content = new List();
-
switch (OverlayLevel)
{
default:
@@ -184,39 +158,27 @@ public static string Draw(int processId)
case 2: // Extended
{
- PlatformManager.HWiNFO.ReaffirmRunningProcess();
-
OverlayRow row1 = new();
- OverlayEntry BATTentry = new("BATT", "C5");
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.BatteryChargeLevel,
- out sensor))
- BATTentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.BatteryRemainingCapacity,
- out sensor))
- BATTentry.elements.Add(new OverlayEntryElement(sensor));
- row1.entries.Add(BATTentry);
-
OverlayEntry GPUentry = new("GPU", "C1");
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUUsage, out sensor))
- GPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUPower, out sensor))
- GPUentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(GPUentry, PlatformManager.LibreHardwareMonitor.GPULoad, "%");
+ AddElementIfNotNull(GPUentry, PlatformManager.LibreHardwareMonitor.GPUPower, "W");
row1.entries.Add(GPUentry);
OverlayEntry CPUentry = new("CPU", "C2");
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.CPUUsage, out sensor))
- CPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.CPUPower, out sensor))
- CPUentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(CPUentry, PlatformManager.LibreHardwareMonitor.CPULoad, "%");
+ AddElementIfNotNull(CPUentry, PlatformManager.LibreHardwareMonitor.CPUPower, "W");
row1.entries.Add(CPUentry);
OverlayEntry RAMentry = new("RAM", "C3");
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.PhysicalMemoryUsage,
- out sensor))
- RAMentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(RAMentry, PlatformManager.LibreHardwareMonitor.MemoryLoad, "%");
row1.entries.Add(RAMentry);
+ OverlayEntry BATTentry = new("BATT", "C5");
+ AddElementIfNotNull(BATTentry, PlatformManager.LibreHardwareMonitor.BatteryLevel, "%");
+ AddElementIfNotNull(BATTentry, PlatformManager.LibreHardwareMonitor.BatteryTimeSpan, "min");
+ row1.entries.Add(BATTentry);
+
OverlayEntry FPSentry = new("", "C6");
FPSentry.elements.Add(new OverlayEntryElement
{
@@ -237,8 +199,6 @@ public static string Draw(int processId)
case 3: // Full
{
- PlatformManager.HWiNFO.ReaffirmRunningProcess();
-
OverlayRow row1 = new();
OverlayRow row2 = new();
OverlayRow row3 = new();
@@ -247,44 +207,29 @@ public static string Draw(int processId)
OverlayRow row6 = new();
OverlayEntry GPUentry = new("GPU", "C1", true);
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUUsage, out sensor))
- GPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUPower, out sensor))
- GPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUTemperature, out sensor))
- GPUentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(GPUentry, PlatformManager.LibreHardwareMonitor.GPULoad, "%");
+ AddElementIfNotNull(GPUentry, PlatformManager.LibreHardwareMonitor.GPUPower, "W");
+ AddElementIfNotNull(GPUentry, PlatformManager.LibreHardwareMonitor.GPUTemperatur, "C");
row1.entries.Add(GPUentry);
OverlayEntry CPUentry = new("CPU", "C2", true);
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.CPUUsage, out sensor))
- CPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.CPUPower, out sensor))
- CPUentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.CPUTemperature, out sensor))
- CPUentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(CPUentry, PlatformManager.LibreHardwareMonitor.CPULoad, "%");
+ AddElementIfNotNull(CPUentry, PlatformManager.LibreHardwareMonitor.CPUPower, "W");
+ AddElementIfNotNull(CPUentry, PlatformManager.LibreHardwareMonitor.CPUTemperatur, "C");
row2.entries.Add(CPUentry);
OverlayEntry RAMentry = new("RAM", "C3", true);
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.PhysicalMemoryUsage,
- out sensor))
- RAMentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(RAMentry, PlatformManager.LibreHardwareMonitor.MemoryLoad, "%");
row3.entries.Add(RAMentry);
OverlayEntry VRAMentry = new("VRAM", "C4", true);
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.GPUMemoryUsage, out sensor))
- VRAMentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(VRAMentry, PlatformManager.LibreHardwareMonitor.VRAMLoad, "%");
row4.entries.Add(VRAMentry);
OverlayEntry BATTentry = new("BATT", "C5", true);
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.BatteryChargeLevel,
- out sensor))
- BATTentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.BatteryRemainingCapacity,
- out sensor))
- BATTentry.elements.Add(new OverlayEntryElement(sensor));
- if (PlatformManager.HWiNFO.MonitoredSensors.TryGetValue(SensorElementType.BatteryRemainingTime,
- out sensor))
- BATTentry.elements.Add(new OverlayEntryElement(sensor));
+ AddElementIfNotNull(BATTentry, PlatformManager.LibreHardwareMonitor.BatteryLevel, "%");
+ AddElementIfNotNull(BATTentry, PlatformManager.LibreHardwareMonitor.BatteryPower, "W");
+ AddElementIfNotNull(BATTentry, PlatformManager.LibreHardwareMonitor.BatteryTimeSpan, "min");
row5.entries.Add(BATTentry);
OverlayEntry FPSentry = new("", "C6");
@@ -339,6 +284,14 @@ public static void Stop()
LogManager.LogInformation("{0} has stopped", "OSDManager");
}
+ private static void AddElementIfNotNull(OverlayEntry entry, float? value, String unit)
+ {
+ if (value is not null)
+ {
+ entry.elements.Add(new OverlayEntryElement((float)value, unit));
+ }
+ }
+
private static void SettingsManager_SettingValueChanged(string name, object value)
{
switch (name)
@@ -347,8 +300,14 @@ private static void SettingsManager_SettingValueChanged(string name, object valu
{
OverlayLevel = Convert.ToInt16(value);
+ // set OSD toggle hotkey state
+ SettingsManager.SetProperty("OnScreenDisplayToggle", Convert.ToBoolean(value));
+
if (OverlayLevel > 0)
{
+ // set lastOSDLevel to be used in OSD toggle hotkey
+ SettingsManager.SetProperty("LastOnScreenDisplayLevel", value);
+
if (OverlayLevel == 4)
{
// No need to update OSD in External
@@ -408,10 +367,10 @@ public override string ToString()
return string.Format("{0:00}{1}", Value, SzUnit);
}
- public OverlayEntryElement(SensorElement sensor)
+ public OverlayEntryElement(float value, String unit)
{
- Value = string.Format("{0:00}", sensor.Value);
- SzUnit = sensor.szUnit;
+ Value = string.Format("{0:00}", value);
+ SzUnit = unit;
}
}
diff --git a/HandheldCompanion/Managers/PerformanceManager.cs b/HandheldCompanion/Managers/PerformanceManager.cs
index 810290e21..c3f327292 100644
--- a/HandheldCompanion/Managers/PerformanceManager.cs
+++ b/HandheldCompanion/Managers/PerformanceManager.cs
@@ -1,3 +1,4 @@
+using HandheldCompanion.Controls;
using HandheldCompanion.Misc;
using HandheldCompanion.Processors;
using HandheldCompanion.Views;
@@ -11,7 +12,7 @@
namespace HandheldCompanion.Managers;
-public static class PowerMode
+public static class OSPowerMode
{
///
/// Better Battery mode.
@@ -30,59 +31,64 @@ public static class PowerMode
public static Guid BestPerformance = new("ded574b5-45a0-4f42-8737-46345c09c238");
}
-public class PerformanceManager : Manager
+public static class PerformanceManager
{
private const short INTERVAL_DEFAULT = 3000; // default interval between value scans
private const short INTERVAL_AUTO = 1010; // default interval between value scans
private const short INTERVAL_DEGRADED = 5000; // degraded interval between value scans
public static int MaxDegreeOfParallelism = 4;
- public static readonly Guid[] PowerModes = new Guid[3] { PowerMode.BetterBattery, PowerMode.BetterPerformance, PowerMode.BestPerformance };
+ public static readonly Guid[] PowerModes = new Guid[3] { OSPowerMode.BetterBattery, OSPowerMode.BetterPerformance, OSPowerMode.BestPerformance };
- private readonly Timer autoWatchdog;
- private readonly Timer cpuWatchdog;
- private readonly Timer gfxWatchdog;
- private readonly Timer powerWatchdog;
+ private static readonly Timer autoWatchdog;
+ private static readonly Timer cpuWatchdog;
+ private static readonly Timer gfxWatchdog;
+ private static readonly Timer powerWatchdog;
- private bool autoLock;
- private bool cpuLock;
- private bool gfxLock;
- private bool powerLock;
+ private static bool autoLock;
+ private static bool cpuLock;
+ private static bool gfxLock;
+ private static bool powerLock;
// AutoTDP
- private double AutoTDP;
- private double AutoTDPPrev;
- private bool AutoTDPFirstRun = true;
- private int AutoTDPFPSSetpointMetCounter;
- private int AutoTDPFPSSmallDipCounter;
- private double AutoTDPMax;
- private double TDPMax;
- private double TDPMin;
- private int AutoTDPProcessId;
- private double AutoTDPTargetFPS;
- private bool cpuWatchdogPendingStop;
- private uint currentEPP = 50;
- private int currentCoreCount;
- private double CurrentGfxClock;
+ private static double AutoTDP;
+ private static double AutoTDPPrev;
+ private static bool AutoTDPFirstRun = true;
+ private static int AutoTDPFPSSetpointMetCounter;
+ private static int AutoTDPFPSSmallDipCounter;
+ private static double AutoTDPMax;
+ private static double TDPMax;
+ private static double TDPMin;
+ private static int AutoTDPProcessId;
+ private static double AutoTDPTargetFPS;
+ private static bool cpuWatchdogPendingStop;
+ private static uint currentEPP = 50;
+ private static int currentCoreCount;
+ private static double CurrentGfxClock;
// powercfg
- private bool currentPerfBoostMode;
- private Guid currentPowerMode = new("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
- private readonly double[] CurrentTDP = new double[5]; // used to store current TDP
+ private static bool currentPerfBoostMode;
+ private static Guid currentPowerMode = new("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
+ private static readonly double[] CurrentTDP = new double[5]; // used to store current TDP
// GPU limits
- private double FallbackGfxClock;
- private readonly double[] FPSHistory = new double[6];
- private bool gfxWatchdogPendingStop;
+ private static double FallbackGfxClock;
+ private static readonly double[] FPSHistory = new double[6];
+ private static bool gfxWatchdogPendingStop;
- private Processor processor = new();
- private double ProcessValueFPSPrevious;
- private double StoredGfxClock;
+ private static Processor processor = new();
+ private static double ProcessValueFPSPrevious;
+ private static double StoredGfxClock;
// TDP limits
- private readonly double[] StoredTDP = new double[3]; // used to store TDP
+ private static readonly double[] StoredTDP = new double[3]; // used to store TDP
- public PerformanceManager()
+ private static bool IsInitialized;
+
+ public static event InitializedEventHandler Initialized;
+ public delegate void InitializedEventHandler();
+
+ static PerformanceManager()
{
// initialize timer(s)
powerWatchdog = new Timer { Interval = INTERVAL_DEFAULT, AutoReset = true, Enabled = false };
@@ -97,26 +103,29 @@ public PerformanceManager()
autoWatchdog = new Timer { Interval = INTERVAL_AUTO, AutoReset = true, Enabled = false };
autoWatchdog.Elapsed += AutoTDPWatchdog_Elapsed;
+ // manage events
ProfileManager.Applied += ProfileManager_Applied;
ProfileManager.Discarded += ProfileManager_Discarded;
-
+ ProfileManager.Updated += ProfileManager_Updated;
PowerProfileManager.Applied += PowerProfileManager_Applied;
PowerProfileManager.Discarded += PowerProfileManager_Discarded;
-
- PlatformManager.HWiNFO.PowerLimitChanged += HWiNFO_PowerLimitChanged;
- PlatformManager.HWiNFO.GPUFrequencyChanged += HWiNFO_GPUFrequencyChanged;
-
+ PlatformManager.LibreHardwareMonitor.GPUClockChanged += LibreHardwareMonitor_GPUClockChanged;
PlatformManager.RTSS.Hooked += RTSS_Hooked;
PlatformManager.RTSS.Unhooked += RTSS_Unhooked;
-
- // initialize settings
SettingsManager.SettingValueChanged += SettingsManagerOnSettingValueChanged;
+ HotkeysManager.CommandExecuted += HotkeysManager_CommandExecuted;
+
+ // move me
+ SystemManager.StateChanged_RSR += SystemManager_StateChanged_RSR;
+ SystemManager.StateChanged_IntegerScaling += SystemManager_StateChanged_IntegerScaling;
+ SystemManager.StateChanged_ImageSharpening += SystemManager_StateChanged_ImageSharpening;
+ SystemManager.StateChanged_GPUScaling += SystemManager_StateChanged_GPUScaling;
currentCoreCount = Environment.ProcessorCount;
MaxDegreeOfParallelism = Convert.ToInt32(Environment.ProcessorCount / 2);
}
- private void SettingsManagerOnSettingValueChanged(string name, object value)
+ private static void SettingsManagerOnSettingValueChanged(string name, object value)
{
switch (name)
{
@@ -136,40 +145,190 @@ private void SettingsManagerOnSettingValueChanged(string name, object value)
}
}
- private void ProfileManager_Applied(Profile profile, UpdateSource source)
+ private static void HotkeysManager_CommandExecuted(string listener)
+ {
+ PowerProfile powerProfile = PowerProfileManager.GetCurrent();
+ if (powerProfile is null)
+ return;
+
+ switch (listener)
+ {
+ case "increaseTDP":
+ {
+ if (powerProfile.TDPOverrideEnabled)
+ return;
+
+ for (int idx = (int)PowerType.Slow; idx <= (int)PowerType.Fast; idx++)
+ powerProfile.TDPOverrideValues[idx] = Math.Min(TDPMax, powerProfile.TDPOverrideValues[idx] + 1);
+
+ PowerProfileManager.UpdateOrCreateProfile(powerProfile, UpdateSource.Background);
+ }
+ break;
+ case "decreaseTDP":
+ {
+ if (powerProfile.TDPOverrideEnabled)
+ return;
+
+ for (int idx = (int)PowerType.Slow; idx <= (int)PowerType.Fast; idx++)
+ powerProfile.TDPOverrideValues[idx] = Math.Max(TDPMin, powerProfile.TDPOverrideValues[idx] - 1);
+
+ PowerProfileManager.UpdateOrCreateProfile(powerProfile, UpdateSource.Background);
+ }
+ break;
+ }
+ }
+
+ private static void ProfileManager_Applied(Profile profile, UpdateSource source)
{
- // apply profile define RSR
try
{
- if (profile.RSREnabled)
+ // apply profile GPU Scaling
+ // apply profile scaling mode
+ if (profile.GPUScaling)
+ {
+ ADLXWrapper.SetGPUScaling(true);
+
+ var scalingMode = profile.ScalingMode;
+
+ // RSR + ScalingMode.Center not supported (stop applying center if it's somehow on a profile)
+ // Technically shouldn't occur and be stopped from UI, but could potentially be possible from older versions
+ if (profile.ScalingMode == 2 && profile.RSREnabled)
+ scalingMode = 1;
+
+ ADLXWrapper.SetScalingMode(scalingMode);
+
+ // apply profile RSR
+ if (profile.RSREnabled)
+ {
+ // mutually exclusive
+ ADLXWrapper.SetIntegerScaling(false);
+ ADLXWrapper.SetImageSharpening(false);
+
+ ADLXWrapper.SetRSR(true);
+ ADLXWrapper.SetRSRSharpness(profile.RSRSharpness);
+ }
+ else if (ADLXWrapper.GetRSR())
+ {
+ ADLXWrapper.SetRSR(false);
+ ADLXWrapper.SetRSRSharpness(20);
+ }
+
+ // apply profile Integer Scaling
+ if (profile.IntegerScalingEnabled)
+ {
+ // mutually exclusive
+ ADLXWrapper.SetRSR(false);
+
+ ADLXWrapper.SetIntegerScaling(true);
+ }
+ else if (ADLXWrapper.GetIntegerScaling())
+ {
+ ADLXWrapper.SetIntegerScaling(false);
+ }
+ }
+ else if (ADLXWrapper.GetGPUScaling())
{
- ADLXBackend.SetRSR(true);
- ADLXBackend.SetRSRSharpness(profile.RSRSharpness);
+ ADLXWrapper.SetGPUScaling(false);
+ }
+
+ // apply profile image sharpening
+ if (profile.RISEnabled)
+ {
+ // mutually exclusive
+ ADLXWrapper.SetRSR(false);
+
+ ADLXWrapper.SetImageSharpening(profile.RISEnabled);
+ ADLXWrapper.SetImageSharpeningSharpness(profile.RISSharpness);
}
- else if (ADLXBackend.GetRSRState() == 1)
+ else if (ADLXWrapper.GetImageSharpening())
{
- ADLXBackend.SetRSR(false);
- ADLXBackend.SetRSRSharpness(20);
+ ADLXWrapper.SetImageSharpening(false);
}
}
catch { }
}
- private void ProfileManager_Discarded(Profile profile)
+ private static void ProfileManager_Discarded(Profile profile)
{
try
{
+ // restore default GPU Scaling
+ if (profile.GPUScaling && ADLXWrapper.GetGPUScaling())
+ {
+ ADLXWrapper.SetGPUScaling(false);
+ }
+
// restore default RSR
- if (profile.RSREnabled)
+ if (profile.RSREnabled && ADLXWrapper.GetRSR())
{
- ADLXBackend.SetRSR(false);
- ADLXBackend.SetRSRSharpness(20);
+ ADLXWrapper.SetRSR(false);
+ ADLXWrapper.SetRSRSharpness(20);
+ }
+
+ // restore default integer scaling
+ if (profile.IntegerScalingEnabled && ADLXWrapper.GetIntegerScaling())
+ {
+ ADLXWrapper.SetIntegerScaling(false);
+ }
+
+ // restore default image sharpening
+ if (profile.RISEnabled && ADLXWrapper.GetImageSharpening())
+ {
+ ADLXWrapper.SetImageSharpening(false);
}
}
catch { }
}
+
+ // todo: moveme
+ private static void ProfileManager_Updated(Profile profile, UpdateSource source, bool isCurrent)
+ {
+ ProcessEx.SetAppCompatFlag(profile.Path, ProcessEx.DisabledMaximizedWindowedValue, !profile.FullScreenOptimization);
+ ProcessEx.SetAppCompatFlag(profile.Path, ProcessEx.HighDPIAwareValue, !profile.HighDPIAware);
+ }
+
+ private static void SystemManager_StateChanged_RSR(bool Supported, bool Enabled, int Sharpness)
+ {
+ Profile profile = ProfileManager.GetCurrent();
+ if (Enabled != profile.RSREnabled)
+ ADLXWrapper.SetRSR(profile.RSREnabled);
+ if (Sharpness != profile.RSRSharpness)
+ ADLXWrapper.SetRSRSharpness(profile.RSRSharpness);
+ }
- private void PowerProfileManager_Applied(PowerProfile profile, UpdateSource source)
+ private static void SystemManager_StateChanged_GPUScaling(bool Supported, bool Enabled, int Mode)
+ {
+ Profile profile = ProfileManager.GetCurrent();
+ if (Enabled != profile.GPUScaling)
+ ADLXWrapper.SetGPUScaling(profile.GPUScaling);
+ if (Mode != profile.ScalingMode)
+ {
+ // RSR + ScalingMode.Center not supported (stop applying center if it's somehow on a profile)
+ // Technically shouldn't occur and be stopped from UI, but could potentially be possible from older versions
+ if (profile.ScalingMode == 2 && profile.RSREnabled)
+ return;
+
+ ADLXWrapper.SetScalingMode(profile.ScalingMode);
+ }
+ }
+
+ private static void SystemManager_StateChanged_IntegerScaling(bool Supported, bool Enabled)
+ {
+ Profile profile = ProfileManager.GetCurrent();
+ if (Enabled != profile.IntegerScalingEnabled)
+ ADLXWrapper.SetIntegerScaling(profile.IntegerScalingEnabled);
+ }
+
+ private static void SystemManager_StateChanged_ImageSharpening(bool Enabled, int Sharpness)
+ {
+ Profile profile = ProfileManager.GetCurrent();
+ if (Enabled != profile.RISEnabled)
+ ADLXWrapper.SetImageSharpening(profile.RISEnabled);
+ if (Sharpness != profile.RISSharpness)
+ ADLXWrapper.SetImageSharpeningSharpness(Sharpness);
+ }
+
+ private static void PowerProfileManager_Applied(PowerProfile profile, UpdateSource source)
{
// apply profile defined TDP
if (profile.TDPOverrideEnabled && profile.TDPOverrideValues is not null)
@@ -273,7 +432,7 @@ private void PowerProfileManager_Applied(PowerProfile profile, UpdateSource sour
RequestPowerMode(profile.OSPowerMode);
}
- private void PowerProfileManager_Discarded(PowerProfile profile)
+ private static void PowerProfileManager_Discarded(PowerProfile profile)
{
// restore default TDP
if (profile.TDPOverrideEnabled)
@@ -322,38 +481,38 @@ private void PowerProfileManager_Discarded(PowerProfile profile)
RequestPerfBoostMode(false);
}
- // restore PowerMode.BetterPerformance
- RequestPowerMode(PowerMode.BetterPerformance);
+ // restore OSPowerMode.BetterPerformance
+ RequestPowerMode(OSPowerMode.BetterPerformance);
}
- private void RestoreTDP(bool immediate)
+ private static void RestoreTDP(bool immediate)
{
for (PowerType pType = PowerType.Slow; pType <= PowerType.Fast; pType++)
RequestTDP(pType, MainWindow.CurrentDevice.cTDP[1], immediate);
}
- private void RestoreCPUClock(bool immediate)
+ private static void RestoreCPUClock(bool immediate)
{
uint maxClock = MotherboardInfo.ProcessorMaxTurboSpeed;
RequestCPUClock(maxClock);
}
- private void RestoreGPUClock(bool immediate)
+ private static void RestoreGPUClock(bool immediate)
{
RequestGPUClock(255 * 50, immediate);
}
- private void RTSS_Hooked(AppEntry appEntry)
+ private static void RTSS_Hooked(AppEntry appEntry)
{
AutoTDPProcessId = appEntry.ProcessId;
}
- private void RTSS_Unhooked(int processId)
+ private static void RTSS_Unhooked(int processId)
{
AutoTDPProcessId = 0;
}
- private void AutoTDPWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
+ private static void AutoTDPWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
{
// We don't have any hooked process
if (AutoTDPProcessId == 0)
@@ -404,7 +563,7 @@ private void AutoTDPWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
}
}
- private double AutoTDPDipper(double FPSActual, double FPSSetpoint)
+ private static double AutoTDPDipper(double FPSActual, double FPSSetpoint)
{
// Dipper
// Add small positive "error" if actual and target FPS are similar for a duration
@@ -447,7 +606,7 @@ private double AutoTDPDipper(double FPSActual, double FPSSetpoint)
return Modifier;
}
- private double AutoTDPDamper(double FPSActual)
+ private static double AutoTDPDamper(double FPSActual)
{
// (PI)D derivative control component to dampen FPS fluctuations
if (double.IsNaN(ProcessValueFPSPrevious)) ProcessValueFPSPrevious = FPSActual;
@@ -463,7 +622,7 @@ private double AutoTDPDamper(double FPSActual)
return TDPDamping;
}
- private void powerWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
+ private static void powerWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
{
if (!powerLock)
{
@@ -506,7 +665,7 @@ private void powerWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
}
}
- private async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
+ private static async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
{
if (processor is null || !processor.IsInitialized)
return;
@@ -520,7 +679,7 @@ private async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
var MSRdone = false;
// read current values and (re)apply requested TDP if needed
- foreach (var type in (PowerType[])Enum.GetValues(typeof(PowerType)))
+ foreach (PowerType type in (PowerType[])Enum.GetValues(typeof(PowerType)))
{
var idx = (int)type;
@@ -533,7 +692,7 @@ private async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
if (processor is AMDProcessor)
{
// AMD reduces TDP by 10% when OS power mode is set to Best power efficiency
- if (currentPowerMode == PowerMode.BetterBattery)
+ if (currentPowerMode == OSPowerMode.BetterBattery)
TDP = (int)Math.Truncate(TDP * 0.9);
}
else if (processor is IntelProcessor)
@@ -563,8 +722,8 @@ private async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
// processor specific
if (processor is IntelProcessor)
{
- var TDPslow = (int)StoredTDP[(int)PowerType.Slow];
- var TDPfast = (int)StoredTDP[(int)PowerType.Fast];
+ int TDPslow = (int)StoredTDP[(int)PowerType.Slow];
+ int TDPfast = (int)StoredTDP[(int)PowerType.Fast];
// only request an update if current limit is different than stored
if (CurrentTDP[(int)PowerType.MsrSlow] != TDPslow ||
@@ -593,7 +752,7 @@ private async void cpuWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
}
}
- private void gfxWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
+ private static void gfxWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
{
if (processor is null || !processor.IsInitialized)
return;
@@ -651,45 +810,45 @@ private void gfxWatchdog_Elapsed(object? sender, ElapsedEventArgs e)
}
}
- internal void StartGPUWatchdog()
+ private static void StartGPUWatchdog()
{
gfxWatchdogPendingStop = false;
gfxWatchdog.Interval = INTERVAL_DEFAULT;
gfxWatchdog.Start();
}
- internal void StopGPUWatchdog(bool immediate = false)
+ private static void StopGPUWatchdog(bool immediate = false)
{
gfxWatchdogPendingStop = true;
if (immediate)
gfxWatchdog.Stop();
}
- internal void StartTDPWatchdog()
+ private static void StartTDPWatchdog()
{
cpuWatchdogPendingStop = false;
cpuWatchdog.Interval = INTERVAL_DEFAULT;
cpuWatchdog.Start();
}
- internal void StopTDPWatchdog(bool immediate = false)
+ private static void StopTDPWatchdog(bool immediate = false)
{
cpuWatchdogPendingStop = true;
if (immediate)
cpuWatchdog.Stop();
}
- internal void StartAutoTDPWatchdog()
+ private static void StartAutoTDPWatchdog()
{
autoWatchdog.Start();
}
- internal void StopAutoTDPWatchdog(bool immediate = false)
+ private static void StopAutoTDPWatchdog(bool immediate = false)
{
autoWatchdog.Stop();
}
- public void RequestTDP(PowerType type, double value, bool immediate = false)
+ private static void RequestTDP(PowerType type, double value, bool immediate = false)
{
if (processor is null || !processor.IsInitialized)
return;
@@ -698,7 +857,7 @@ public void RequestTDP(PowerType type, double value, bool immediate = false)
value = Math.Min(TDPMax, Math.Max(TDPMin, value));
// update value read by timer
- var idx = (int)type;
+ int idx = (int)type;
StoredTDP[idx] = value;
// immediately apply
@@ -706,12 +865,12 @@ public void RequestTDP(PowerType type, double value, bool immediate = false)
processor.SetTDPLimit((PowerType)idx, value, immediate);
}
- public async void RequestTDP(double[] values, bool immediate = false)
+ private static async void RequestTDP(double[] values, bool immediate = false)
{
if (processor is null || !processor.IsInitialized)
return;
- for (var idx = (int)PowerType.Slow; idx <= (int)PowerType.Fast; idx++)
+ for (int idx = (int)PowerType.Slow; idx <= (int)PowerType.Fast; idx++)
{
// make sure we're not trying to run below or above specs
values[idx] = Math.Min(TDPMax, Math.Max(TDPMin, values[idx]));
@@ -728,7 +887,7 @@ public async void RequestTDP(double[] values, bool immediate = false)
}
}
- public void RequestGPUClock(double value, bool immediate = false)
+ private static void RequestGPUClock(double value, bool immediate = false)
{
if (processor is null || !processor.IsInitialized)
return;
@@ -741,7 +900,7 @@ public void RequestGPUClock(double value, bool immediate = false)
processor.SetGPUClock(value);
}
- public void RequestPowerMode(Guid guid)
+ private static void RequestPowerMode(Guid guid)
{
currentPowerMode = guid;
LogManager.LogDebug("User requested power scheme: {0}", currentPowerMode);
@@ -750,7 +909,7 @@ public void RequestPowerMode(Guid guid)
LogManager.LogWarning("Failed to set requested power scheme: {0}", currentPowerMode);
}
- public void RequestEPP(uint EPPOverrideValue)
+ private static void RequestEPP(uint EPPOverrideValue)
{
currentEPP = EPPOverrideValue;
@@ -777,7 +936,7 @@ public void RequestEPP(uint EPPOverrideValue)
LogManager.LogWarning("Failed to set requested EPP");
}
- public void RequestCPUCoreCount(int CoreCount)
+ private static void RequestCPUCoreCount(int CoreCount)
{
currentCoreCount = CoreCount;
@@ -811,7 +970,7 @@ public void RequestCPUCoreCount(int CoreCount)
LogManager.LogWarning("Failed to set requested CPMAXCORES");
}
- public void RequestPerfBoostMode(bool value)
+ private static void RequestPerfBoostMode(bool value)
{
currentPerfBoostMode = value;
@@ -821,7 +980,7 @@ public void RequestPerfBoostMode(bool value)
LogManager.LogDebug("User requested perfboostmode: {0}", value);
}
- private void RequestCPUClock(uint cpuClock)
+ private static void RequestCPUClock(uint cpuClock)
{
double maxClock = MotherboardInfo.ProcessorMaxTurboSpeed;
@@ -843,7 +1002,7 @@ private void RequestCPUClock(uint cpuClock)
LogManager.LogWarning("Failed to set requested PROCFREQMAX");
}
- public override void Start()
+ public static void Start()
{
// initialize watchdog(s)
powerWatchdog.Start();
@@ -864,25 +1023,31 @@ public override void Start()
processor.MiscChanged += Processor_MiscChanged;
*/
- base.Start();
+ IsInitialized = true;
+ Initialized?.Invoke();
+
+ LogManager.LogInformation("{0} has started", "PerformanceManager");
}
- public override void Stop()
+ public static void Stop()
{
if (!IsInitialized)
return;
- processor.Stop();
+ if (processor.IsInitialized)
+ processor.Stop();
powerWatchdog.Stop();
cpuWatchdog.Stop();
gfxWatchdog.Stop();
autoWatchdog.Stop();
- base.Stop();
+ IsInitialized = false;
+
+ LogManager.LogInformation("{0} has started", "PerformanceManager");
}
- public Processor GetProcessor()
+ public static Processor GetProcessor()
{
return processor;
}
@@ -909,27 +1074,27 @@ public Processor GetProcessor()
#region events
- public event LimitChangedHandler PowerLimitChanged;
+ public static event LimitChangedHandler PowerLimitChanged;
public delegate void LimitChangedHandler(PowerType type, int limit);
- public event ValueChangedHandler PowerValueChanged;
+ public static event ValueChangedHandler PowerValueChanged;
public delegate void ValueChangedHandler(PowerType type, float value);
- public event StatusChangedHandler ProcessorStatusChanged;
+ public static event StatusChangedHandler ProcessorStatusChanged;
public delegate void StatusChangedHandler(bool CanChangeTDP, bool CanChangeGPU);
- public event PowerModeChangedEventHandler PowerModeChanged;
+ public static event PowerModeChangedEventHandler PowerModeChanged;
public delegate void PowerModeChangedEventHandler(int idx);
- public event PerfBoostModeChangedEventHandler PerfBoostModeChanged;
+ public static event PerfBoostModeChangedEventHandler PerfBoostModeChanged;
public delegate void PerfBoostModeChangedEventHandler(bool value);
- public event EPPChangedEventHandler EPPChanged;
+ public static event EPPChangedEventHandler EPPChanged;
public delegate void EPPChangedEventHandler(uint EPP);
@@ -937,49 +1102,28 @@ public Processor GetProcessor()
#region events
- private void HWiNFO_PowerLimitChanged(PowerType type, int limit)
+ private static void LibreHardwareMonitor_GPUClockChanged(float? value)
{
- var idx = (int)type;
- CurrentTDP[idx] = limit;
+ if (value is null) return;
- // workaround, HWiNFO doesn't have the ability to report MSR
- switch (type)
- {
- case PowerType.Slow:
- CurrentTDP[(int)PowerType.Stapm] = limit;
- CurrentTDP[(int)PowerType.MsrSlow] = limit;
- break;
- case PowerType.Fast:
- CurrentTDP[(int)PowerType.MsrFast] = limit;
- break;
- }
-
- // raise event
- PowerLimitChanged?.Invoke(type, limit);
-
- LogManager.LogTrace("PowerLimitChanged: {0}\t{1} W", type, limit);
- }
-
- private void HWiNFO_GPUFrequencyChanged(double value)
- {
- CurrentGfxClock = value;
+ CurrentGfxClock = (float) value;
- LogManager.LogTrace("GPUFrequencyChanged: {0} Mhz", value);
+ LogManager.LogTrace("GPUClockChange: {0} Mhz", value);
}
- private void Processor_StatusChanged(bool CanChangeTDP, bool CanChangeGPU)
+ private static void Processor_StatusChanged(bool CanChangeTDP, bool CanChangeGPU)
{
ProcessorStatusChanged?.Invoke(CanChangeTDP, CanChangeGPU);
}
[Obsolete("Method is deprecated.")]
- private void Processor_ValueChanged(PowerType type, float value)
+ private static void Processor_ValueChanged(PowerType type, float value)
{
PowerValueChanged?.Invoke(type, value);
}
[Obsolete("Method is deprecated.")]
- private void Processor_LimitChanged(PowerType type, int limit)
+ private static void Processor_LimitChanged(PowerType type, int limit)
{
var idx = (int)type;
CurrentTDP[idx] = limit;
@@ -989,7 +1133,7 @@ private void Processor_LimitChanged(PowerType type, int limit)
}
[Obsolete("Method is deprecated.")]
- private void Processor_MiscChanged(string misc, float value)
+ private static void Processor_MiscChanged(string misc, float value)
{
switch (misc)
{
diff --git a/HandheldCompanion/Managers/PlatformManager.cs b/HandheldCompanion/Managers/PlatformManager.cs
index 717e7f9f9..89e91ccfe 100644
--- a/HandheldCompanion/Managers/PlatformManager.cs
+++ b/HandheldCompanion/Managers/PlatformManager.cs
@@ -17,8 +17,7 @@ public static class PlatformManager
// misc platforms
public static RTSS RTSS = new();
- public static HWiNFO HWiNFO = new();
- public static OpenHardwareMonitor OpenHardwareMonitor = new();
+ public static Platforms.LibreHardwareMonitor LibreHardwareMonitor = new();
private static Timer UpdateTimer;
@@ -50,14 +49,6 @@ public static void Start()
UpdateCurrentNeeds_OnScreenDisplay(OSDManager.OverlayLevel);
}
- if (HWiNFO.IsInstalled)
- {
- // do something
- }
-
- if (OpenHardwareMonitor.IsInstalled)
- OpenHardwareMonitor.Start();
-
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
ProfileManager.Applied += ProfileManager_Applied;
PowerProfileManager.Applied += PowerProfileManager_Applied;
@@ -88,7 +79,7 @@ private static void PowerProfileManager_Applied(Misc.PowerProfile profile, Updat
private static void ProfileManager_Applied(Profile profile, UpdateSource source)
{
// Framerate limiter
- if (profile.FramerateEnabled)
+ if (profile.FramerateValue != 0)
CurrentNeeds |= PlatformNeeds.FramerateLimiter;
else
CurrentNeeds &= ~PlatformNeeds.FramerateLimiter;
@@ -141,17 +132,17 @@ private static void MonitorPlatforms()
{
/*
* Dependencies:
- * HWInfo: OSD
+ * LibreHardwareMonitor (LHM): OSD
* RTSS: AutoTDP, framerate limiter, OSD
*/
// Check if the current needs are the same as the previous needs
if (CurrentNeeds == PreviousNeeds) return;
- // Start or stop HWiNFO and RTSS based on the current and previous needs
+ // Start or stop LHM and RTSS based on the current and previous needs
if (CurrentNeeds.HasFlag(PlatformNeeds.OnScreenDisplay))
{
- // If OSD is needed, start RTSS and start HWiNFO only if OnScreenDisplayComplex is true
+ // If OSD is needed, start RTSS and start LHM only if OnScreenDisplayComplex is true
if (!PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplay))
// Only start RTSS if it was not running before and if it is installed
if (RTSS.IsInstalled)
@@ -162,45 +153,40 @@ private static void MonitorPlatforms()
if (CurrentNeeds.HasFlag(PlatformNeeds.OnScreenDisplayComplex))
{
// This condition checks if OnScreenDisplayComplex is true
- // OnScreenDisplayComplex is a new flag that indicates if the OSD needs more information from HWiNFO
+ // OnScreenDisplayComplex is a new flag that indicates if the OSD needs more information from LHM
if (!PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplay) ||
!PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplayComplex))
- // Only start HWiNFO if it was not running before or if OnScreenDisplayComplex was false and if it is installed
- if (HWiNFO.IsInstalled)
- HWiNFO.Start();
+ // Only start LHM if it was not running before or if OnScreenDisplayComplex was false
+ LibreHardwareMonitor.Start();
}
else
{
- // If OnScreenDisplayComplex is false, stop HWiNFO if it was running before
+ // If OnScreenDisplayComplex is false, stop LHM if it was running before
if (PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplay) &&
PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplayComplex))
- // Only stop HWiNFO if it is installed
- if (HWiNFO.IsInstalled)
- HWiNFO.Stop(true);
+ LibreHardwareMonitor.Stop(true);
}
}
else if (CurrentNeeds.HasFlag(PlatformNeeds.AutoTDP) || CurrentNeeds.HasFlag(PlatformNeeds.FramerateLimiter))
{
- // If AutoTDP or framerate limiter is needed, start only RTSS and stop HWiNFO
+ // If AutoTDP or framerate limiter is needed, start only RTSS and stop LHM
if (!PreviousNeeds.HasFlag(PlatformNeeds.AutoTDP) && !PreviousNeeds.HasFlag(PlatformNeeds.FramerateLimiter))
// Only start RTSS if it was not running before and if it is installed
if (RTSS.IsInstalled)
RTSS.Start();
- // Only stop HWiNFO if it was running before
- // Only stop HWiNFO if it is installed
- if (PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplay))
- if (HWiNFO.IsInstalled)
- HWiNFO.Stop(true);
+ // Only stop LHM if it was running before
+ if (PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplayComplex))
+ LibreHardwareMonitor.Stop(true);
}
else
{
- // If none of the needs are present, stop both HWiNFO and RTSS
+ // If none of the needs are present, stop both LHM and RTSS
if (PreviousNeeds.HasFlag(PlatformNeeds.OnScreenDisplay) || PreviousNeeds.HasFlag(PlatformNeeds.AutoTDP) ||
PreviousNeeds.HasFlag(PlatformNeeds.FramerateLimiter))
{
- // Only stop HWiNFO and RTSS if they were running before and if they are installed
- if (HWiNFO.IsInstalled) HWiNFO.Stop(true);
+ // Only stop LHM and RTSS if they were running before and if they are installed
+ LibreHardwareMonitor.Stop(true);
if (RTSS.IsInstalled)
{
// Stop RTSS
@@ -231,15 +217,8 @@ public static void Stop()
RTSS.Dispose();
}
- if (HWiNFO.IsInstalled)
- {
- var killHWiNFO = SettingsManager.GetBoolean("PlatformHWiNFOEnabled");
- HWiNFO.Stop(killHWiNFO);
- HWiNFO.Dispose();
- }
-
- if (OpenHardwareMonitor.IsInstalled)
- OpenHardwareMonitor.Stop();
+ if (LibreHardwareMonitor.IsInstalled)
+ LibreHardwareMonitor.Stop();
IsInitialized = false;
diff --git a/HandheldCompanion/Managers/PowerProfileManager.cs b/HandheldCompanion/Managers/PowerProfileManager.cs
index 6517f3609..052fde415 100644
--- a/HandheldCompanion/Managers/PowerProfileManager.cs
+++ b/HandheldCompanion/Managers/PowerProfileManager.cs
@@ -26,7 +26,7 @@ static PowerProfileManager()
if (!Directory.Exists(ProfilesPath))
Directory.CreateDirectory(ProfilesPath);
- PlatformManager.OpenHardwareMonitor.CpuTemperatureChanged += OpenHardwareMonitor_CpuTemperatureChanged;
+ PlatformManager.LibreHardwareMonitor.CPUTemperatureChanged += LibreHardwareMonitor_CpuTemperatureChanged;
ProfileManager.Applied += ProfileManager_Applied;
ProfileManager.Discarded += ProfileManager_Discarded;
@@ -39,13 +39,11 @@ public static void Start()
foreach (var fileName in fileEntries)
ProcessProfile(fileName);
- // process device profiles
- if (MainWindow.CurrentDevice.powerProfileQuiet is not null && !profiles.ContainsKey(MainWindow.CurrentDevice.powerProfileQuiet.Guid))
- UpdateOrCreateProfile(MainWindow.CurrentDevice.powerProfileQuiet, UpdateSource.Serializer);
- if (MainWindow.CurrentDevice.powerProfileCool is not null && !profiles.ContainsKey(MainWindow.CurrentDevice.powerProfileCool.Guid))
- UpdateOrCreateProfile(MainWindow.CurrentDevice.powerProfileCool, UpdateSource.Serializer);
- if (MainWindow.CurrentDevice.powerProfileBalanced is not null && !profiles.ContainsKey(MainWindow.CurrentDevice.powerProfileBalanced.Guid))
- UpdateOrCreateProfile(MainWindow.CurrentDevice.powerProfileBalanced, UpdateSource.Serializer);
+ foreach (var devicePowerProfile in MainWindow.CurrentDevice.DevicePowerProfiles)
+ {
+ if(!profiles.ContainsKey(devicePowerProfile.Guid))
+ UpdateOrCreateProfile(devicePowerProfile, UpdateSource.Serializer);
+ }
IsInitialized = true;
Initialized?.Invoke();
@@ -63,13 +61,13 @@ public static void Stop()
LogManager.LogInformation("{0} has stopped", "PowerProfileManager");
}
- private static void OpenHardwareMonitor_CpuTemperatureChanged(double value)
+ private static void LibreHardwareMonitor_CpuTemperatureChanged(float? value)
{
- if (currentProfile is null || currentProfile.FanProfile is null)
+ if (currentProfile is null || currentProfile.FanProfile is null || value is null)
return;
// update fan profile
- currentProfile.FanProfile.SetTemperature(value);
+ currentProfile.FanProfile.SetTemperature((float)value);
switch (currentProfile.FanProfile.fanMode)
{
@@ -160,7 +158,7 @@ public static void UpdateOrCreateProfile(PowerProfile profile, UpdateSource sour
return;
// warn owner
- bool isCurrent = profile.Guid == currentProfile.Guid;
+ bool isCurrent = profile.Guid == currentProfile?.Guid;
if (isCurrent)
Applied?.Invoke(profile, source);
@@ -183,6 +181,15 @@ public static PowerProfile GetProfile(Guid guid)
{
if (profiles.TryGetValue(guid, out var profile))
return profile;
+
+ return null;
+ }
+
+ public static PowerProfile GetCurrent()
+ {
+ if (currentProfile is not null)
+ return currentProfile;
+
return null;
}
@@ -216,7 +223,7 @@ public static void DeleteProfile(PowerProfile profile)
profiles.Remove(profile.Guid);
// warn owner
- bool isCurrent = profile.Guid == currentProfile.Guid;
+ bool isCurrent = profile.Guid == currentProfile?.Guid;
// raise event
Discarded?.Invoke(profile);
diff --git a/HandheldCompanion/Managers/ProcessManager.cs b/HandheldCompanion/Managers/ProcessManager.cs
index 74e82f96a..048b5a331 100644
--- a/HandheldCompanion/Managers/ProcessManager.cs
+++ b/HandheldCompanion/Managers/ProcessManager.cs
@@ -32,6 +32,8 @@ public static class ProcessManager
// process vars
private static readonly Timer ForegroundTimer;
+ private static readonly Timer ProcessWatcher;
+
private static readonly ConcurrentDictionary Processes = new();
private static ProcessEx foregroundProcess;
private static ProcessEx previousProcess;
@@ -57,6 +59,9 @@ static ProcessManager()
ForegroundTimer = new Timer(1000);
ForegroundTimer.Elapsed += ForegroundCallback;
+
+ ProcessWatcher = new Timer(2000);
+ ProcessWatcher.Elapsed += ProcessWatcher_Elapsed;
}
private static void OnWindowOpened(object sender, AutomationEventArgs automationEventArgs)
@@ -98,6 +103,7 @@ public static void Start()
// start processes monitor
ForegroundTimer.Start();
+ ProcessWatcher.Start();
IsInitialized = true;
Initialized?.Invoke();
@@ -113,8 +119,8 @@ public static void Stop()
IsInitialized = false;
// stop processes monitor
- ForegroundTimer.Elapsed -= ForegroundCallback;
ForegroundTimer.Stop();
+ ProcessWatcher.Stop();
LogManager.LogInformation("{0} has stopped", "ProcessManager");
}
@@ -126,7 +132,7 @@ public static ProcessEx GetForegroundProcess()
public static ProcessEx GetLastSuspendedProcess()
{
- return Processes.Values.LastOrDefault(item => item.IsSuspended());
+ return Processes.Values.LastOrDefault(item => item.IsSuspended);
}
public static ProcessEx GetProcess(int processId)
@@ -174,7 +180,7 @@ private static void ForegroundCallback(object? sender, EventArgs e)
ProcessEx prevProcess = foregroundProcess;
// filter based on current process status
- ProcessFilter filter = GetFilter(process.Executable, process.Path, ProcessUtils.GetWindowTitle(hWnd));
+ ProcessFilter filter = GetFilter(process.Executable, process.Path /*, ProcessUtils.GetWindowTitle(hWnd) */);
switch (filter)
{
// do nothing on QuickTools window, current process is kept
@@ -239,7 +245,6 @@ private static bool CreateProcess(int ProcessID, int NativeWindowHandle = 0, boo
{
// process has exited on arrival
Process proc = Process.GetProcessById(ProcessID);
- proc.EnableRaisingEvents = true;
if (proc.HasExited)
return false;
@@ -247,39 +252,47 @@ private static bool CreateProcess(int ProcessID, int NativeWindowHandle = 0, boo
return true;
// hook exited event
+ proc.EnableRaisingEvents = true;
proc.Exited += ProcessHalted;
+ // check process path
+ string path = ProcessUtils.GetPathToApp(proc.Id);
+ if (string.IsNullOrEmpty(path))
+ return false;
+
+ string exec = Path.GetFileName(path);
+ IntPtr hWnd = NativeWindowHandle != 0 ? NativeWindowHandle : proc.MainWindowHandle;
+
+ // get filter
+ ProcessFilter filter = GetFilter(exec, path);
+
// UI thread (synchronous)
+ ProcessEx processEx = null;
Application.Current.Dispatcher.Invoke(() =>
{
- // check process path
- string path = ProcessUtils.GetPathToApp(proc.Id);
- if (string.IsNullOrEmpty(path))
- return false;
-
- string exec = Path.GetFileName(path);
- IntPtr hWnd = NativeWindowHandle != 0 ? NativeWindowHandle : proc.MainWindowHandle;
+ // create process
+ processEx = new ProcessEx(proc, path, exec, filter);
+ // processEx.MainWindowTitle = ProcessUtils.GetWindowTitle(hWnd);
+ });
- // get filter
- ProcessFilter filter = GetFilter(exec, path);
+ if (processEx is null)
+ return false;
- ProcessEx processEx = new ProcessEx(proc, path, exec, filter);
- processEx.MainWindowHandle = hWnd;
- processEx.MainWindowTitle = ProcessUtils.GetWindowTitle(hWnd);
- processEx.MainThread = GetMainThread(proc);
+ processEx.MainWindowHandle = hWnd;
+ processEx.MainThread = GetMainThread(proc);
+ processEx.Platform = PlatformManager.GetPlatform(proc);
- Processes.TryAdd(ProcessID, processEx);
+ Processes.TryAdd(ProcessID, processEx);
- if (processEx.Filter != ProcessFilter.Allowed)
- return true;
+ if (processEx.Filter != ProcessFilter.Allowed)
+ return true;
- // raise event
- ProcessStarted?.Invoke(processEx, OnStartup);
+ // raise event
+ ProcessStarted?.Invoke(processEx, OnStartup);
- LogManager.LogDebug("Process detected: {0}", processEx.Executable);
+ LogManager.LogDebug("Process detected: {0}", processEx.Executable);
- return true;
- });
+ return true;
}
catch
{
@@ -401,6 +414,16 @@ private static ProcessThread GetMainThread(Process process)
return mainThread;
}
+ private static void ProcessWatcher_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
+ {
+ Parallel.ForEach(Processes,
+ new ParallelOptions { MaxDegreeOfParallelism = PerformanceManager.MaxDegreeOfParallelism }, process =>
+ {
+ ProcessEx processEx = process.Value;
+ processEx.Refresh();
+ });
+ }
+
public static void ResumeProcess(ProcessEx processEx)
{
// process has exited
@@ -415,7 +438,7 @@ public static void ResumeProcess(ProcessEx processEx)
Parallel.ForEach(processEx.Children,
new ParallelOptions { MaxDegreeOfParallelism = PerformanceManager.MaxDegreeOfParallelism }, childId =>
{
- var process = Process.GetProcessById(childId);
+ Process process = Process.GetProcessById(childId);
ProcessUtils.NtResumeProcess(process.Handle);
});
@@ -440,7 +463,7 @@ public static void SuspendProcess(ProcessEx processEx)
Parallel.ForEach(processEx.Children,
new ParallelOptions { MaxDegreeOfParallelism = PerformanceManager.MaxDegreeOfParallelism }, childId =>
{
- var process = Process.GetProcessById(childId);
+ Process process = Process.GetProcessById(childId);
ProcessUtils.NtSuspendProcess(process.Handle);
});
}
diff --git a/HandheldCompanion/Managers/ProfileManager.cs b/HandheldCompanion/Managers/ProfileManager.cs
index 0d056e434..4e6337546 100644
--- a/HandheldCompanion/Managers/ProfileManager.cs
+++ b/HandheldCompanion/Managers/ProfileManager.cs
@@ -18,6 +18,7 @@ public static class ProfileManager
public const string DefaultName = "Default";
public static Dictionary profiles = new(StringComparer.InvariantCultureIgnoreCase);
+ public static List subProfiles = new();
private static Profile currentProfile;
@@ -78,9 +79,6 @@ public static void Start()
UpdateOrCreateProfile(defaultProfile, UpdateSource.Creation);
}
- // force apply default
- ApplyProfile(GetDefault());
-
IsInitialized = true;
Initialized?.Invoke();
@@ -120,8 +118,12 @@ public static bool Contains(string fileName)
public static Profile GetProfileFromPath(string path, bool ignoreStatus)
{
- // get profile from path
- Profile profile = profiles.Values.FirstOrDefault(a => a.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase));
+ // check if favorite sub profile exists for path
+ Profile profile = subProfiles.FirstOrDefault(pr => pr.Path == path && pr.IsFavoriteSubProfile);
+
+ // get main profile from path instead
+ if (profile is null)
+ profile = profiles.Values.FirstOrDefault(a => a.Path.Equals(path, StringComparison.InvariantCultureIgnoreCase));
if (profile is null)
{
@@ -140,15 +142,105 @@ public static Profile GetProfileFromPath(string path, bool ignoreStatus)
return profile.Enabled ? profile : GetDefault();
}
+ public static Profile GetProfileFromGuid(Guid Guid, bool ignoreStatus, bool isSubProfile = false)
+ {
+ Profile profile = null;
+
+ if (isSubProfile)
+ profile = subProfiles.FirstOrDefault(pr => pr.Guid == Guid);
+ else
+ profile = profiles.Values.FirstOrDefault(pr => pr.Guid == Guid);
+
+ // get profile from path
+ if (profile is null)
+ return GetDefault();
+
+ // ignore profile status (enabled/disabled)
+ if (ignoreStatus)
+ return profile;
+
+ return profile.Enabled ? profile : GetDefault();
+ }
+
+ public static Profile[] GetSubProfilesFromPath(string path, bool ignoreStatus)
+ {
+ // get subprofile corresponding to path
+ List filteredSubProfiles = subProfiles.Where(pr => pr.Path == path).ToList();
+ return filteredSubProfiles.OrderBy(pr => pr.Name).ToArray();
+ }
+
+ public static Profile GetProfileForSubProfile(Profile subProfile)
+ {
+ // if passed in profile is main profile
+ if (!subProfile.IsSubProfile || !profiles.ContainsKey(subProfile.Path))
+ return subProfile;
+
+ // get the main profile if it exists/loaded .. else return the profile itself
+ return profiles[subProfile.Path];
+ }
+
+ public static void SetSubProfileAsFavorite(Profile subProfile)
+ {
+ // remove favorite from all subprofiles
+ foreach (var profile in GetSubProfilesFromPath(subProfile.Path, false))
+ {
+ profile.IsFavoriteSubProfile = false;
+ SerializeProfile(profile);
+ }
+
+ // check if subProfile is not the main profile itself
+ if (subProfile.IsSubProfile)
+ {
+ subProfile.IsFavoriteSubProfile = true;
+ SerializeProfile(subProfile);
+ }
+ }
+
+ public static void CycleSubProfiles(bool previous = false)
+ {
+ if (currentProfile == null)
+ return;
+ // called using previousSubProfile/nextSubProfile hotkeys
+ List subProfilesList = new();
+ subProfilesList.Add(GetProfileForSubProfile(currentProfile)); // adds main profile as sub profile
+ subProfilesList.AddRange(GetSubProfilesFromPath(currentProfile.Path, false).ToList()); // adds all sub profiles
+
+ // if profile does not have sub profiles -> do nothing
+ if (subProfilesList.Count <= 1)
+ return;
+
+ // get index of currently applied profile
+ int currentIndex = subProfilesList.IndexOf(currentProfile);
+ int newIndex = currentIndex;
+
+ // previous? decrement, next? increment
+ if (previous)
+ newIndex -= 1;
+ else
+ newIndex += 1;
+
+ // ensure index is within list bounds, wrap if needed
+ newIndex = (newIndex + subProfilesList.Count) % subProfilesList.Count;
+
+ // if for whatever reason index is out of bound -> return
+ if (newIndex < 0 || newIndex >= subProfilesList.Count)
+ return;
+
+ // apply profile
+ Profile profileToApply = subProfilesList[newIndex];
+ UpdateOrCreateProfile(profileToApply);
+ }
+
+
private static void ApplyProfile(Profile profile, UpdateSource source = UpdateSource.Background,
bool announce = true)
{
// might not be the same anymore if disabled
- profile = GetProfileFromPath(profile.Path, false);
+ profile = GetProfileFromGuid(profile.Guid, false, profile.IsSubProfile);
// we've already announced this profile
if (currentProfile is not null)
- if (currentProfile.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase))
+ if (currentProfile.Guid == profile.Guid)
announce = false;
// update current profile before invoking event
@@ -168,7 +260,10 @@ private static void ApplyProfile(Profile profile, UpdateSource source = UpdateSo
private static void PowerProfileManager_Deleted(PowerProfile powerProfile)
{
- foreach(Profile profile in profiles.Values)
+ Profile profileToApply = null;
+
+ // update main profiles
+ foreach (Profile profile in profiles.Values)
{
bool isCurrent = profile.PowerProfile == powerProfile.Guid;
if (isCurrent)
@@ -180,9 +275,32 @@ private static void PowerProfileManager_Deleted(PowerProfile powerProfile)
UpdateOrCreateProfile(profile);
if (currentProfile.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase))
- ApplyProfile(profile);
+ profileToApply = profile;
}
}
+
+ // update sub profiles
+ foreach (Profile profile in subProfiles)
+ {
+ bool isCurrent = profile.PowerProfile == powerProfile.Guid;
+ if (isCurrent)
+ {
+ // sanitize profile
+ SanitizeProfile(profile);
+
+ // update profile
+ UpdateOrCreateProfile(profile);
+
+ if (currentProfile.Guid == profile.Guid)
+ {
+ profileToApply = profile;
+ }
+ }
+ }
+
+ if (profileToApply != null)
+ ApplyProfile(profileToApply);
+
}
private static void ProcessManager_ProcessStopped(ProcessEx processEx)
@@ -364,6 +482,13 @@ public static void DeleteProfile(Profile profile)
if (profiles.ContainsKey(profile.Path))
{
+ // delete associated subprofiles
+ foreach (Profile subprofile in GetSubProfilesFromPath(profile.Path, false))
+ {
+ DeleteSubProfile(subprofile);
+ }
+ LogManager.LogInformation("Deleted subprofiles for profile {0}", profile);
+
// Unregister application from HidHide
HidHide.UnregisterApplication(profile.Path);
@@ -373,7 +498,10 @@ public static void DeleteProfile(Profile profile)
profiles.Remove(profile.Path);
// warn owner
- var isCurrent = profile.Path.Equals(currentProfile.Path, StringComparison.InvariantCultureIgnoreCase);
+ var isCurrent = false;
+
+ if (currentProfile != null)
+ isCurrent = profile.Path.Equals(currentProfile.Path, StringComparison.InvariantCultureIgnoreCase);
// raise event
Discarded?.Invoke(profile);
@@ -395,6 +523,42 @@ public static void DeleteProfile(Profile profile)
FileUtils.FileDelete(profilePath);
}
+ public static void DeleteSubProfile(Profile subProfile)
+ {
+ var profilePath = Path.Combine(ProfilesPath, subProfile.GetFileName());
+
+ if (subProfiles.Contains(subProfile))
+ {
+ // remove sub profile from memory
+ subProfiles.Remove(subProfile);
+
+ // warn owner
+ var isCurrent = subProfile.Guid == currentProfile.Guid;
+
+ // raise event
+ Discarded?.Invoke(subProfile);
+
+ // raise event(s)
+ Deleted?.Invoke(subProfile);
+
+ // send toast
+ // todo: localize me
+ ToastManager.SendToast($"Subprofile {subProfile.Name} deleted");
+
+ LogManager.LogInformation("Deleted subprofile {0}", profilePath);
+
+ // restore main profile as favorite
+ if (isCurrent)
+ {
+ // apply the main profile if it still exists
+ Profile originalProfile = profiles.Values.FirstOrDefault(p => p.Path == subProfile.Path, GetDefault());
+ ApplyProfile(originalProfile);
+ }
+ }
+
+ FileUtils.FileDelete(profilePath);
+ }
+
public static void SerializeProfile(Profile profile)
{
// update profile version to current build
@@ -443,24 +607,25 @@ private static void SanitizeProfile(Profile profile)
// looks like profile power profile was deleted, restore balanced
if (!PowerProfileManager.Contains(profile.PowerProfile))
- profile.PowerProfile = PowerMode.BetterPerformance;
+ profile.PowerProfile = OSPowerMode.BetterPerformance;
}
public static void UpdateOrCreateProfile(Profile profile, UpdateSource source = UpdateSource.Background)
{
+ LogManager.LogInformation($"Attempting to update/create profile {profile.Name} => sub profile? {profile.IsSubProfile}");
bool isCurrent = false;
switch (source)
{
- // update current profile on creation
- case UpdateSource.Creation:
- case UpdateSource.QuickProfilesPage:
+ // if profile is created from QT -> apply it
+ case UpdateSource.QuickProfilesCreation:
isCurrent = true;
break;
+ case UpdateSource.ProfilesPageUpdateOnly: // when renaming main profile in ProfilesPage
+ isCurrent = false;
+ break;
default:
// check if this is current profile
- isCurrent = currentProfile is null
- ? false
- : profile.Path.Equals(currentProfile.Path, StringComparison.InvariantCultureIgnoreCase);
+ isCurrent = currentProfile is null ? false : profile.Path.Equals(currentProfile.Path, StringComparison.InvariantCultureIgnoreCase);
break;
}
@@ -469,13 +634,26 @@ public static void UpdateOrCreateProfile(Profile profile, UpdateSource source =
// used to get and store a few previous values
XInputPlusMethod prevWrapper = XInputPlusMethod.Disabled;
- if (profiles.TryGetValue(profile.Path, out Profile prevProfile))
+ if (!profile.IsSubProfile && profiles.TryGetValue(profile.Path, out Profile prevProfile))
{
prevWrapper = prevProfile.XInputPlus;
}
+ else if (profile.IsSubProfile) // TODO check if necessary
+ {
+ Profile prevSubProfile = subProfiles.FirstOrDefault(sub => sub.Guid == profile.Guid);
+ if (prevSubProfile != null)
+ prevWrapper = prevSubProfile.XInputPlus;
+ }
// update database
- profiles[profile.Path] = profile;
+ if (profile.IsSubProfile)
+ {
+ // remove sub profile if it already exists, then add the updated one
+ subProfiles = subProfiles.Where(pr => pr.Guid != profile.Guid).ToList();
+ subProfiles.Add(profile);
+ }
+ else
+ profiles[profile.Path] = profile;
// raise event(s)
Updated?.Invoke(profile, source, isCurrent);
@@ -499,8 +677,12 @@ public static void UpdateOrCreateProfile(Profile profile, UpdateSource source =
}
// apply profile (silently)
+ LogManager.LogInformation($"Checking if profile: {profile} is current => {isCurrent}");
if (isCurrent)
+ {
+ SetSubProfileAsFavorite(profile); // if sub profile, set it as favorite for main profile
ApplyProfile(profile, source);
+ }
// serialize profile
SerializeProfile(profile);
diff --git a/HandheldCompanion/Managers/SettingsManager.cs b/HandheldCompanion/Managers/SettingsManager.cs
index a1ea71d66..114df2cd2 100644
--- a/HandheldCompanion/Managers/SettingsManager.cs
+++ b/HandheldCompanion/Managers/SettingsManager.cs
@@ -5,8 +5,8 @@
using System.Collections.Specialized;
using System.Configuration;
using System.Linq;
-using System.Windows.Media;
-
+using System.Windows.Media;
+
namespace HandheldCompanion.Managers;
public static class SettingsManager
@@ -80,9 +80,8 @@ public static void SetProperty(string name, object value, bool force = false, bo
switch (name)
{
case "OverlayControllerBackgroundColor":
- value = Convert.ToString(value);
- break;
case "LEDMainColor":
+ case "LEDSecondColor":
value = Convert.ToString(value);
break;
}
@@ -205,20 +204,20 @@ public static bool GetBoolean(string name, bool temporary = false)
}
public static Color GetColor(string name, bool temporary = false)
- {
- // Conver color, which is stored as a HEX string to a color datatype
- string hexColor = Convert.ToString(GetProperty(name, temporary));
-
- // Remove the '#' character and convert the remaining string to a 32-bit integer
- var argbValue = int.Parse(hexColor.Substring(1), System.Globalization.NumberStyles.HexNumber);
-
- // Extract alpha, red, green, and blue components
- byte alpha = (byte)((argbValue >> 24) & 0xFF);
- byte red = (byte)((argbValue >> 16) & 0xFF);
- byte green = (byte)((argbValue >> 8) & 0xFF);
- byte blue = (byte)(argbValue & 0xFF);
-
- // Create a Color object from the extracted components
+ {
+ // Conver color, which is stored as a HEX string to a color datatype
+ string hexColor = Convert.ToString(GetProperty(name, temporary));
+
+ // Remove the '#' character and convert the remaining string to a 32-bit integer
+ var argbValue = int.Parse(hexColor.Substring(1), System.Globalization.NumberStyles.HexNumber);
+
+ // Extract alpha, red, green, and blue components
+ byte alpha = (byte)((argbValue >> 24) & 0xFF);
+ byte red = (byte)((argbValue >> 16) & 0xFF);
+ byte green = (byte)((argbValue >> 8) & 0xFF);
+ byte blue = (byte)(argbValue & 0xFF);
+
+ // Create a Color object from the extracted components
Color color = Color.FromArgb(alpha, red, green, blue);
return color;
diff --git a/HandheldCompanion/Managers/SystemManager.cs b/HandheldCompanion/Managers/SystemManager.cs
index 582c7202d..f1c91639a 100644
--- a/HandheldCompanion/Managers/SystemManager.cs
+++ b/HandheldCompanion/Managers/SystemManager.cs
@@ -1,630 +1,747 @@
-using HandheldCompanion.Devices;
-using HandheldCompanion.Managers.Desktop;
-using HandheldCompanion.Misc;
-using HandheldCompanion.Views;
-using Microsoft.Win32;
-using NAudio.CoreAudioApi;
-using NAudio.CoreAudioApi.Interfaces;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Management;
-using System.Media;
-using System.Runtime.InteropServices;
-using System.Timers;
-using System.Windows.Forms;
-using Timer = System.Timers.Timer;
-
-namespace HandheldCompanion.Managers;
-
-public static class SystemManager
-{
- private static DesktopScreen DesktopScreen;
- private static ScreenRotation ScreenOrientation;
-
- private static readonly MMDeviceEnumerator DevEnum;
- private static MMDevice multimediaDevice;
- private static readonly MMDeviceNotificationClient notificationClient;
-
- private static readonly ManagementEventWatcher BrightnessWatcher;
- private static readonly ManagementScope Scope;
-
- private static bool VolumeSupport;
- private static readonly bool BrightnessSupport;
- private static bool FanControlSupport;
-
- private const int UpdateInterval = 1000;
- private static readonly Timer ADLXTimer;
- private static int prevRSRState = -2;
- private static int prevRSRSharpness = -1;
-
- public static bool IsInitialized;
-
- static SystemManager()
- {
- // ADLX
- ADLXTimer = new Timer(UpdateInterval);
- ADLXTimer.AutoReset = true;
- ADLXTimer.Elapsed += ADLXTimer_Elapsed;
-
- // setup the multimedia device and get current volume value
- notificationClient = new MMDeviceNotificationClient();
- DevEnum = new MMDeviceEnumerator();
- DevEnum.RegisterEndpointNotificationCallback(notificationClient);
- SetDefaultAudioEndPoint();
-
- // get current brightness value
- Scope = new ManagementScope(@"\\.\root\wmi");
- Scope.Connect();
-
- // creating the watcher
- BrightnessWatcher = new ManagementEventWatcher(Scope, new EventQuery("Select * From WmiMonitorBrightnessEvent"));
- BrightnessWatcher.EventArrived += onWMIEvent;
-
- SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
-
- // check if we have control over brightness
- BrightnessSupport = GetBrightness() != -1;
-
- if (MainWindow.CurrentDevice.IsOpen && MainWindow.CurrentDevice.IsSupported)
- if (MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.FanControl))
- FanControlSupport = true;
-
- SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
- HotkeysManager.CommandExecuted += HotkeysManager_CommandExecuted;
- }
-
- private static void ADLXTimer_Elapsed(object? sender, ElapsedEventArgs e)
- {
- try
- {
- var RSRState = ADLXBackend.GetRSRState();
- var RSRSharpness = ADLXBackend.GetRSRSharpness();
-
- if ((RSRState != prevRSRState) || (RSRSharpness != prevRSRSharpness))
- {
- RSRStateChanged?.Invoke(RSRState, RSRSharpness);
-
- prevRSRState = RSRState;
- prevRSRSharpness = RSRSharpness;
- }
- }
- catch { }
- }
-
- private static void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
- {
- VolumeNotification?.Invoke(data.MasterVolume * 100.0f);
- }
-
- private static void SetDefaultAudioEndPoint()
- {
- try
- {
- if (multimediaDevice is not null && multimediaDevice.AudioEndpointVolume is not null)
- {
- VolumeSupport = false;
- multimediaDevice.AudioEndpointVolume.OnVolumeNotification -= AudioEndpointVolume_OnVolumeNotification;
- }
-
- multimediaDevice = DevEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
-
- if (multimediaDevice is not null && multimediaDevice.AudioEndpointVolume is not null)
- {
- VolumeSupport = true;
- multimediaDevice.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
- }
-
- // do this even when no device found, to set to 0
- VolumeNotification?.Invoke((float)GetVolume());
- }
- catch (Exception)
- {
- LogManager.LogError("No AudioEndpoint available");
- }
- }
-
- private static void SettingsManager_SettingValueChanged(string name, object value)
- {
- switch (name)
- {
- case "NativeDisplayOrientation":
- {
- var nativeOrientation = (ScreenRotation.Rotations)Convert.ToInt32(value);
-
- if (!IsInitialized)
- return;
-
- var oldOrientation = ScreenOrientation.rotation;
- ScreenOrientation = new ScreenRotation(ScreenOrientation.rotationUnnormalized, nativeOrientation);
-
- if (oldOrientation != ScreenOrientation.rotation)
- // Though the real orientation didn't change, raise event because the interpretation of it changed
- DisplayOrientationChanged?.Invoke(ScreenOrientation);
- }
- break;
- }
- }
-
- private static void HotkeysManager_CommandExecuted(string listener)
- {
- switch (listener)
- {
- case "increaseBrightness":
- {
- var stepRoundDn = (int)Math.Floor(GetBrightness() / 5.0d);
- var brightness = stepRoundDn * 5 + 5;
- SetBrightness(brightness);
- }
- break;
- case "decreaseBrightness":
- {
- var stepRoundUp = (int)Math.Ceiling(GetBrightness() / 5.0d);
- var brightness = stepRoundUp * 5 - 5;
- SetBrightness(brightness);
- }
- break;
- case "increaseVolume":
- {
- var stepRoundDn = (int)Math.Floor(Math.Round(GetVolume() / 5.0d, 2));
- var volume = stepRoundDn * 5 + 5;
- SetVolume(volume);
- }
- break;
- case "decreaseVolume":
- {
- var stepRoundUp = (int)Math.Ceiling(Math.Round(GetVolume() / 5.0d, 2));
- var volume = stepRoundUp * 5 - 5;
- SetVolume(volume);
- }
- break;
- }
- }
-
- private static void onWMIEvent(object sender, EventArrivedEventArgs e)
- {
- var brightness = Convert.ToInt32(e.NewEvent.Properties["Brightness"].Value);
- BrightnessNotification?.Invoke(brightness);
- }
-
- private static void SystemEvents_DisplaySettingsChanged(object? sender, EventArgs e)
- {
- Screen PrimaryScreen = Screen.PrimaryScreen;
-
- if (DesktopScreen is null || DesktopScreen.PrimaryScreen.DeviceName != PrimaryScreen.DeviceName)
- {
- // update current desktop screen
- DesktopScreen = new DesktopScreen(PrimaryScreen);
-
- // pull resolutions details
- List resolutions = GetResolutions(DesktopScreen.PrimaryScreen.DeviceName);
-
- foreach (var mode in resolutions)
- {
- ScreenResolution res = new ScreenResolution(mode.dmPelsWidth, mode.dmPelsHeight, mode.dmBitsPerPel);
-
- List frequencies = resolutions
- .Where(a => a.dmPelsWidth == mode.dmPelsWidth && a.dmPelsHeight == mode.dmPelsHeight)
- .Select(b => b.dmDisplayFrequency).Distinct().ToList();
- foreach (int frequency in frequencies)
- res.Frequencies[frequency] = new ScreenFrequency(frequency);
-
- if (!DesktopScreen.HasResolution(res))
- DesktopScreen.resolutions.Add(res);
- }
-
- // sort resolutions
- DesktopScreen.SortResolutions();
-
- // raise event
- PrimaryScreenChanged?.Invoke(DesktopScreen);
- }
-
- // update current desktop resolution
- DesktopScreen.devMode = GetDisplay(DesktopScreen.PrimaryScreen.DeviceName);
- ScreenResolution ScreenResolution = DesktopScreen.GetResolution(DesktopScreen.devMode.dmPelsWidth, DesktopScreen.devMode.dmPelsHeight);
-
- ScreenRotation.Rotations oldOrientation = ScreenOrientation.rotation;
-
- if (!IsInitialized)
- {
- var nativeScreenRotation = (ScreenRotation.Rotations)SettingsManager.GetInt("NativeDisplayOrientation");
- ScreenOrientation = new ScreenRotation((ScreenRotation.Rotations)DesktopScreen.devMode.dmDisplayOrientation,
- nativeScreenRotation);
- oldOrientation = ScreenRotation.Rotations.UNSET;
-
- if (nativeScreenRotation == ScreenRotation.Rotations.UNSET)
- SettingsManager.SetProperty("NativeDisplayOrientation", (int)ScreenOrientation.rotationNativeBase,
- true);
- }
- else
- {
- ScreenOrientation = new ScreenRotation((ScreenRotation.Rotations)DesktopScreen.devMode.dmDisplayOrientation,
- ScreenOrientation.rotationNativeBase);
- }
-
- // raise event
- if (ScreenResolution is not null)
- DisplaySettingsChanged?.Invoke(ScreenResolution);
-
- if (oldOrientation != ScreenOrientation.rotation)
- // raise event
- DisplayOrientationChanged?.Invoke(ScreenOrientation);
- }
-
- public static DesktopScreen GetDesktopScreen()
- {
- return DesktopScreen;
- }
-
- public static ScreenRotation GetScreenOrientation()
- {
- return ScreenOrientation;
- }
-
- public static void Start()
- {
- // start brightness watcher
- BrightnessWatcher.Start();
- ADLXTimer.Start();
-
- // force trigger events
- SystemEvents_DisplaySettingsChanged(null, null);
-
- IsInitialized = true;
- Initialized?.Invoke();
-
- LogManager.LogInformation("{0} has started", "SystemManager");
- }
-
- public static void Stop()
- {
- if (!IsInitialized)
- return;
-
- // stop brightness watcher
- BrightnessWatcher.Stop();
- ADLXTimer.Stop();
-
- DevEnum.UnregisterEndpointNotificationCallback(notificationClient);
-
- IsInitialized = false;
-
- LogManager.LogInformation("{0} has stopped", "SystemManager");
- }
-
- public static bool SetResolution(int width, int height, int displayFrequency)
- {
- if (!IsInitialized)
- return false;
-
- var ret = false;
- long RetVal = 0;
- var dm = new Display();
- dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
- dm.dmPelsWidth = width;
- dm.dmPelsHeight = height;
- dm.dmDisplayFrequency = displayFrequency;
- dm.dmFields = Display.DM_PELSWIDTH | Display.DM_PELSHEIGHT | Display.DM_DISPLAYFREQUENCY;
- RetVal = ChangeDisplaySettings(ref dm, CDS_TEST);
- if (RetVal == 0)
- {
- RetVal = ChangeDisplaySettings(ref dm, 0);
- ret = true;
- }
-
- return ret;
- }
-
- public static bool SetResolution(int width, int height, int displayFrequency, int bitsPerPel)
- {
- if (!IsInitialized)
- return false;
-
- var ret = false;
- long RetVal = 0;
- var dm = new Display();
- dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
- dm.dmPelsWidth = width;
- dm.dmPelsHeight = height;
- dm.dmDisplayFrequency = displayFrequency;
- dm.dmBitsPerPel = bitsPerPel;
- dm.dmFields = Display.DM_PELSWIDTH | Display.DM_PELSHEIGHT | Display.DM_DISPLAYFREQUENCY;
- RetVal = ChangeDisplaySettings(ref dm, CDS_TEST);
- if (RetVal == 0)
- {
- RetVal = ChangeDisplaySettings(ref dm, 0);
- ret = true;
- }
-
- return ret;
- }
-
- public static Display GetDisplay(string DeviceName)
- {
- var dm = new Display();
- dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
- bool mybool;
- mybool = EnumDisplaySettings(DeviceName, -1, ref dm);
- return dm;
- }
-
- public static List GetResolutions(string DeviceName)
- {
- var allMode = new List();
- var dm = new Display();
- dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
- var index = 0;
- while (EnumDisplaySettings(DeviceName, index, ref dm))
- {
- allMode.Add(dm);
- index++;
- }
-
- return allMode;
- }
-
- public static void PlayWindowsMedia(string file)
- {
- var path = Path.Combine(@"c:\Windows\Media\", file);
- if (File.Exists(path))
- new SoundPlayer(path).Play();
- }
-
- public static bool HasVolumeSupport()
- {
- return VolumeSupport;
- }
-
- public static void SetVolume(double volume)
- {
- if (!VolumeSupport)
- return;
-
- multimediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar = (float)(volume / 100.0d);
- }
-
- public static double GetVolume()
- {
- if (!VolumeSupport)
- return 0.0d;
-
- return multimediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100.0d;
- }
-
- public static bool HasBrightnessSupport()
- {
- return BrightnessSupport;
- }
-
- public static void SetBrightness(double brightness)
- {
- if (!BrightnessSupport)
- return;
-
- try
- {
- using (var mclass = new ManagementClass("WmiMonitorBrightnessMethods"))
- {
- mclass.Scope = new ManagementScope(@"\\.\root\wmi");
- using (var instances = mclass.GetInstances())
- {
- foreach (ManagementObject instance in instances)
- {
- object[] args = { 1, brightness };
- instance.InvokeMethod("WmiSetBrightness", args);
- }
- }
- }
- }
- catch
- {
- }
- }
-
- public static short GetBrightness()
- {
- try
- {
- using (var mclass = new ManagementClass("WmiMonitorBrightness"))
- {
- mclass.Scope = new ManagementScope(@"\\.\root\wmi");
- using (var instances = mclass.GetInstances())
- {
- foreach (ManagementObject instance in instances)
- return (byte)instance.GetPropertyValue("CurrentBrightness");
- }
- }
-
- return 0;
- }
- catch
- {
- }
-
- return -1;
- }
-
- private class MMDeviceNotificationClient : IMMNotificationClient
- {
- public void OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId)
- {
- SetDefaultAudioEndPoint();
- }
-
- public void OnDeviceAdded(string deviceId)
- {
- }
-
- public void OnDeviceRemoved(string deviceId)
- {
- }
-
- public void OnDeviceStateChanged(string deviceId, DeviceState newState)
- {
- }
-
- public void OnPropertyValueChanged(string deviceId, PropertyKey key)
- {
- }
- }
-
- #region imports
-
- public enum DMDO
- {
- DEFAULT = 0,
- D90 = 1,
- D180 = 2,
- D270 = 3
- }
-
- public const int CDS_UPDATEREGISTRY = 0x01;
- public const int CDS_TEST = 0x02;
- public const int DISP_CHANGE_SUCCESSFUL = 0;
- public const int DISP_CHANGE_RESTART = 1;
- public const int DISP_CHANGE_FAILED = -1;
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
- public struct Display
- {
- public const int DM_DISPLAYFREQUENCY = 0x400000;
- public const int DM_PELSWIDTH = 0x80000;
- public const int DM_PELSHEIGHT = 0x100000;
- private const int CCHDEVICENAME = 32;
- private const int CCHFORMNAME = 32;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
- public string dmDeviceName;
-
- public short dmSpecVersion;
- public short dmDriverVersion;
- public short dmSize;
- public short dmDriverExtra;
- public int dmFields;
-
- public int dmPositionX;
- public int dmPositionY;
- public DMDO dmDisplayOrientation;
- public int dmDisplayFixedOutput;
-
- public short dmColor;
- public short dmDuplex;
- public short dmYResolution;
- public short dmTTOption;
- public short dmCollate;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
- public string dmFormName;
-
- public short dmLogPixels;
- public int dmBitsPerPel;
- public int dmPelsWidth;
- public int dmPelsHeight;
- public int dmDisplayFlags;
- public int dmDisplayFrequency;
- public int dmICMMethod;
- public int dmICMIntent;
- public int dmMediaType;
- public int dmDitherType;
- public int dmReserved1;
- public int dmReserved2;
- public int dmPanningWidth;
- public int dmPanningHeight;
-
- public override string ToString()
- {
- return $"{dmPelsWidth}x{dmPelsHeight}, {dmDisplayFrequency}, {dmBitsPerPel}";
- }
- }
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern int ChangeDisplaySettings([In] ref Display lpDevMode, int dwFlags);
-
- [DllImport("user32.dll", CharSet = CharSet.Auto)]
- private static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref Display lpDevMode);
-
- [Flags]
- public enum DisplayDeviceStateFlags
- {
- /// The device is part of the desktop.
- AttachedToDesktop = 0x1,
- MultiDriver = 0x2,
-
- /// The device is part of the desktop.
- PrimaryDevice = 0x4,
-
- /// Represents a pseudo device used to mirror application drawing for remoting or other purposes.
- MirroringDriver = 0x8,
-
- /// The device is VGA compatible.
- VGACompatible = 0x16,
-
- /// The device is removable; it cannot be the primary display.
- Removable = 0x20,
-
- /// The device has more display modes than its output devices support.
- ModesPruned = 0x8000000,
- Remote = 0x4000000,
- Disconnect = 0x2000000
- }
-
- [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
- public struct DisplayDevice
- {
- [MarshalAs(UnmanagedType.U4)] public int cb;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
- public string DeviceName;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceString;
-
- [MarshalAs(UnmanagedType.U4)] public DisplayDeviceStateFlags StateFlags;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceID;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
- public string DeviceKey;
- }
-
- [DllImport("User32.dll")]
- private static extern int EnumDisplayDevices(string lpDevice, int iDevNum, ref DisplayDevice lpDisplayDevice,
- int dwFlags);
-
- #endregion
-
- #region events
-
- public static event RSRStateChangedEventHandler RSRStateChanged;
-
- public delegate void RSRStateChangedEventHandler(int RSRState, int RSRSharpness);
-
- public static event DisplaySettingsChangedEventHandler DisplaySettingsChanged;
-
- public delegate void DisplaySettingsChangedEventHandler(ScreenResolution resolution);
-
- public static event PrimaryScreenChangedEventHandler PrimaryScreenChanged;
-
- public delegate void PrimaryScreenChangedEventHandler(DesktopScreen screen);
-
- public static event DisplayOrientationChangedEventHandler DisplayOrientationChanged;
-
- public delegate void DisplayOrientationChangedEventHandler(ScreenRotation rotation);
-
- public static event VolumeNotificationEventHandler VolumeNotification;
-
- public delegate void VolumeNotificationEventHandler(float volume);
-
- public static event BrightnessNotificationEventHandler BrightnessNotification;
-
- public delegate void BrightnessNotificationEventHandler(int brightness);
-
- public static event InitializedEventHandler Initialized;
-
- public delegate void InitializedEventHandler();
-
- #endregion
+using HandheldCompanion.Managers.Desktop;
+using HandheldCompanion.Misc;
+using Microsoft.Win32;
+using NAudio.CoreAudioApi;
+using NAudio.CoreAudioApi.Interfaces;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Management;
+using System.Media;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Timers;
+using System.Windows.Forms;
+using Timer = System.Timers.Timer;
+
+namespace HandheldCompanion.Managers;
+
+public static class SystemManager
+{
+ private static DesktopScreen desktopScreen;
+ private static ScreenRotation screenOrientation;
+
+ private static readonly MMDeviceEnumerator DevEnum;
+ private static MMDevice multimediaDevice;
+ private static readonly MMDeviceNotificationClient notificationClient;
+
+ private static readonly ManagementEventWatcher BrightnessWatcher;
+ private static readonly ManagementScope Scope;
+
+ private static bool VolumeSupport;
+ private static readonly bool BrightnessSupport;
+
+ private const int ADLXUpdateInterval = 2000;
+ private static readonly Timer ADLXTimer;
+
+ private static bool prevRSRSupport = false;
+ private static bool prevRSR = false;
+ private static int prevRSRSharpness = -1;
+
+ private static bool prevGPUScalingSupport = false;
+ private static bool prevGPUScaling = false;
+ private static int prevScalingMode = -1;
+
+ private static bool prevIntegerScaling = false;
+ private static bool prevIntegerScalingSupport = false;
+
+ private static bool prevImageSharpening = false;
+ private static int prevImageSharpeningSharpness = -1;
+
+ public static bool IsInitialized;
+
+ static SystemManager()
+ {
+ // ADLX
+ ADLXTimer = new Timer(ADLXUpdateInterval);
+ ADLXTimer.AutoReset = true;
+ ADLXTimer.Elapsed += ADLXTimer_Elapsed;
+
+ // setup the multimedia device and get current volume value
+ notificationClient = new MMDeviceNotificationClient();
+ DevEnum = new MMDeviceEnumerator();
+ DevEnum.RegisterEndpointNotificationCallback(notificationClient);
+ SetDefaultAudioEndPoint();
+
+ // get current brightness value
+ Scope = new ManagementScope(@"\\.\root\wmi");
+ Scope.Connect();
+
+ // creating the watcher
+ BrightnessWatcher = new ManagementEventWatcher(Scope, new EventQuery("Select * From WmiMonitorBrightnessEvent"));
+ BrightnessWatcher.EventArrived += onWMIEvent;
+
+ // check if we have control over brightness
+ BrightnessSupport = GetBrightness() != -1;
+
+ // manage events
+ SystemEvents.DisplaySettingsChanged += SystemEvents_DisplaySettingsChanged;
+ SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ HotkeysManager.CommandExecuted += HotkeysManager_CommandExecuted;
+ }
+
+ // create a lock object
+ private static object ADLXlockObject = new object();
+ private static void ADLXTimer_Elapsed(object? sender, ElapsedEventArgs e)
+ {
+ if (Monitor.TryEnter(ADLXlockObject))
+ {
+ bool GPUScaling = false;
+
+ try
+ {
+ // check for GPU Scaling support
+ // if yes, get GPU Scaling (bool)
+ bool GPUScalingSupport = ADLXWrapper.HasGPUScalingSupport();
+ if (GPUScalingSupport)
+ GPUScaling = ADLXWrapper.GetGPUScaling();
+
+ // check for Scaling Mode support
+ // if yes, get Scaling Mode (int)
+ bool ScalingSupport = ADLXWrapper.HasScalingModeSupport();
+ int ScalingMode = 0;
+ if (ScalingSupport)
+ ScalingMode = ADLXWrapper.GetScalingMode();
+
+ if ((GPUScalingSupport != prevGPUScalingSupport) || (GPUScaling != prevGPUScaling) || (ScalingMode != prevScalingMode))
+ {
+ // raise event
+ StateChanged_GPUScaling?.Invoke(GPUScalingSupport, GPUScaling, ScalingMode);
+
+ prevGPUScaling = GPUScaling;
+ prevScalingMode = ScalingMode;
+ prevGPUScalingSupport = GPUScalingSupport;
+ }
+ }
+ catch { }
+
+ try
+ {
+ // get rsr
+ bool RSRSupport = false;
+ bool RSR = false;
+ int RSRSharpness = ADLXWrapper.GetRSRSharpness();
+
+ DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(3));
+ while (DateTime.Now < timeout && !RSRSupport)
+ {
+ RSRSupport = ADLXWrapper.HasRSRSupport();
+ Thread.Sleep(250);
+ }
+ RSR = ADLXWrapper.GetRSR();
+
+ if ((RSRSupport != prevRSRSupport) || (RSR != prevRSR) || (RSRSharpness != prevRSRSharpness))
+ {
+ // raise event
+ StateChanged_RSR?.Invoke(RSRSupport, RSR, RSRSharpness);
+
+ prevRSRSupport = RSRSupport;
+ prevRSR = RSR;
+ prevRSRSharpness = RSRSharpness;
+ }
+ }
+ catch { }
+
+ try
+ {
+ // get gpu scaling and scaling mode
+ bool IntegerScalingSupport = false;
+ bool IntegerScaling = false;
+
+ DateTime timeout = DateTime.Now.Add(TimeSpan.FromSeconds(3));
+ while (DateTime.Now < timeout && !IntegerScalingSupport)
+ {
+ IntegerScalingSupport = ADLXWrapper.HasIntegerScalingSupport();
+ Thread.Sleep(250);
+ }
+ IntegerScaling = ADLXWrapper.GetIntegerScaling();
+
+ if ((IntegerScalingSupport != prevIntegerScalingSupport) || (IntegerScaling != prevIntegerScaling))
+ {
+ // raise event
+ StateChanged_IntegerScaling?.Invoke(IntegerScalingSupport, IntegerScaling);
+
+ prevIntegerScalingSupport = IntegerScalingSupport;
+ prevIntegerScaling = IntegerScaling;
+ }
+ }
+ catch { }
+
+ try
+ {
+ bool ImageSharpening = ADLXWrapper.GetImageSharpening();
+ int ImageSharpeningSharpness = ADLXWrapper.GetImageSharpeningSharpness();
+
+ if ((ImageSharpening != prevImageSharpening) || (ImageSharpeningSharpness != prevImageSharpeningSharpness))
+ {
+ // raise event
+ StateChanged_ImageSharpening?.Invoke(ImageSharpening, ImageSharpeningSharpness);
+
+ prevImageSharpening = ImageSharpening;
+ prevImageSharpeningSharpness = ImageSharpeningSharpness;
+ }
+ }
+ catch { }
+
+ Monitor.Exit(ADLXlockObject);
+ }
+ }
+
+ private static void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
+ {
+ VolumeNotification?.Invoke(data.MasterVolume * 100.0f);
+ }
+
+ private static void SetDefaultAudioEndPoint()
+ {
+ try
+ {
+ if (multimediaDevice is not null && multimediaDevice.AudioEndpointVolume is not null)
+ {
+ VolumeSupport = false;
+ multimediaDevice.AudioEndpointVolume.OnVolumeNotification -= AudioEndpointVolume_OnVolumeNotification;
+ }
+
+ multimediaDevice = DevEnum.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
+
+ if (multimediaDevice is not null && multimediaDevice.AudioEndpointVolume is not null)
+ {
+ VolumeSupport = true;
+ multimediaDevice.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
+ }
+
+ // do this even when no device found, to set to 0
+ VolumeNotification?.Invoke((float)GetVolume());
+ }
+ catch (Exception)
+ {
+ LogManager.LogError("No AudioEndpoint available");
+ }
+ }
+
+ private static void SettingsManager_SettingValueChanged(string name, object value)
+ {
+ switch (name)
+ {
+ case "NativeDisplayOrientation":
+ {
+ var nativeOrientation = (ScreenRotation.Rotations)Convert.ToInt32(value);
+
+ if (!IsInitialized)
+ return;
+
+ var oldOrientation = screenOrientation.rotation;
+ screenOrientation = new ScreenRotation(screenOrientation.rotationUnnormalized, nativeOrientation);
+
+ if (oldOrientation != screenOrientation.rotation)
+ // Though the real orientation didn't change, raise event because the interpretation of it changed
+ DisplayOrientationChanged?.Invoke(screenOrientation);
+ }
+ break;
+ }
+ }
+
+ private static void HotkeysManager_CommandExecuted(string listener)
+ {
+ switch (listener)
+ {
+ case "increaseBrightness":
+ {
+ var stepRoundDn = (int)Math.Floor(GetBrightness() / 5.0d);
+ var brightness = stepRoundDn * 5 + 5;
+ SetBrightness(brightness);
+ }
+ break;
+ case "decreaseBrightness":
+ {
+ var stepRoundUp = (int)Math.Ceiling(GetBrightness() / 5.0d);
+ var brightness = stepRoundUp * 5 - 5;
+ SetBrightness(brightness);
+ }
+ break;
+ case "increaseVolume":
+ {
+ var stepRoundDn = (int)Math.Floor(Math.Round(GetVolume() / 5.0d, 2));
+ var volume = stepRoundDn * 5 + 5;
+ SetVolume(volume);
+ }
+ break;
+ case "decreaseVolume":
+ {
+ var stepRoundUp = (int)Math.Ceiling(Math.Round(GetVolume() / 5.0d, 2));
+ var volume = stepRoundUp * 5 - 5;
+ SetVolume(volume);
+ }
+ break;
+ }
+ }
+
+ private static void onWMIEvent(object sender, EventArrivedEventArgs e)
+ {
+ var brightness = Convert.ToInt32(e.NewEvent.Properties["Brightness"].Value);
+ BrightnessNotification?.Invoke(brightness);
+ }
+
+ private static void SystemEvents_DisplaySettingsChanged(object? sender, EventArgs e)
+ {
+ Screen PrimaryScreen = Screen.PrimaryScreen;
+
+ if (desktopScreen is null || desktopScreen.PrimaryScreen.DeviceName != PrimaryScreen.DeviceName)
+ {
+ // update current desktop screen
+ desktopScreen = new DesktopScreen(PrimaryScreen);
+ desktopScreen.devMode = GetDisplay(desktopScreen.PrimaryScreen.DeviceName);
+
+ // pull resolutions details
+ List resolutions = GetResolutions(desktopScreen.PrimaryScreen.DeviceName);
+ foreach (Display mode in resolutions)
+ {
+ ScreenResolution res = new ScreenResolution(mode.dmPelsWidth, mode.dmPelsHeight, mode.dmBitsPerPel);
+
+ List frequencies = resolutions
+ .Where(a => a.dmPelsWidth == mode.dmPelsWidth && a.dmPelsHeight == mode.dmPelsHeight)
+ .Select(b => b.dmDisplayFrequency).Distinct().ToList();
+
+ foreach (int frequency in frequencies)
+ res.Frequencies.Add(frequency, frequency);
+
+ if (!desktopScreen.HasResolution(res))
+ desktopScreen.screenResolutions.Add(res);
+ }
+
+ // sort resolutions
+ desktopScreen.SortResolutions();
+
+ // raise event
+ PrimaryScreenChanged?.Invoke(desktopScreen);
+ }
+ else
+ {
+ // update current desktop resolution
+ desktopScreen.devMode = GetDisplay(desktopScreen.PrimaryScreen.DeviceName);
+ }
+
+ ScreenRotation.Rotations oldOrientation = screenOrientation.rotation;
+
+ if (!IsInitialized)
+ {
+ var nativeScreenRotation = (ScreenRotation.Rotations)SettingsManager.GetInt("NativeDisplayOrientation");
+ screenOrientation = new ScreenRotation((ScreenRotation.Rotations)desktopScreen.devMode.dmDisplayOrientation,
+ nativeScreenRotation);
+ oldOrientation = ScreenRotation.Rotations.UNSET;
+
+ if (nativeScreenRotation == ScreenRotation.Rotations.UNSET)
+ SettingsManager.SetProperty("NativeDisplayOrientation", (int)screenOrientation.rotationNativeBase,
+ true);
+ }
+ else
+ {
+ screenOrientation = new ScreenRotation((ScreenRotation.Rotations)desktopScreen.devMode.dmDisplayOrientation,
+ screenOrientation.rotationNativeBase);
+ }
+
+ // raise event
+ ScreenResolution screenResolution = desktopScreen.GetResolution(desktopScreen.devMode.dmPelsWidth, desktopScreen.devMode.dmPelsHeight);
+ if (screenResolution is not null)
+ DisplaySettingsChanged?.Invoke(screenResolution);
+
+ // raise event
+ if (oldOrientation != screenOrientation.rotation)
+ DisplayOrientationChanged?.Invoke(screenOrientation);
+ }
+
+ public static DesktopScreen GetDesktopScreen()
+ {
+ return desktopScreen;
+ }
+
+ public static ScreenRotation GetScreenOrientation()
+ {
+ return screenOrientation;
+ }
+
+ public static void Start()
+ {
+ // start brightness watcher
+ BrightnessWatcher.Start();
+ ADLXTimer.Start();
+
+ // force trigger events
+ SystemEvents_DisplaySettingsChanged(null, null);
+
+ // get native resolution
+ ScreenResolution nativeResolution = desktopScreen.screenResolutions.First();
+
+ // get integer scaling dividers
+ int idx = 1;
+
+ while (true)
+ {
+ int height = nativeResolution.Height / idx;
+ var dividedRes = desktopScreen.screenResolutions.FirstOrDefault(r => r.Height == height);
+ if (dividedRes is null)
+ break;
+
+ desktopScreen.screenDividers.Add(new(idx, dividedRes));
+ idx++;
+ }
+
+ IsInitialized = true;
+ Initialized?.Invoke();
+
+ LogManager.LogInformation("{0} has started", "SystemManager");
+ }
+
+ public static void Stop()
+ {
+ if (!IsInitialized)
+ return;
+
+ // stop brightness watcher
+ BrightnessWatcher.Stop();
+ ADLXTimer.Stop();
+
+ DevEnum.UnregisterEndpointNotificationCallback(notificationClient);
+
+ IsInitialized = false;
+
+ LogManager.LogInformation("{0} has stopped", "SystemManager");
+ }
+
+ public static bool SetResolution(int width, int height, int displayFrequency)
+ {
+ if (!IsInitialized)
+ return false;
+
+ var ret = false;
+ long RetVal = 0;
+ var dm = new Display();
+ dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
+ dm.dmPelsWidth = width;
+ dm.dmPelsHeight = height;
+ dm.dmDisplayFrequency = displayFrequency;
+ dm.dmFields = Display.DM_PELSWIDTH | Display.DM_PELSHEIGHT | Display.DM_DISPLAYFREQUENCY;
+ RetVal = ChangeDisplaySettings(ref dm, CDS_TEST);
+ if (RetVal == 0)
+ {
+ RetVal = ChangeDisplaySettings(ref dm, 0);
+ ret = true;
+ }
+
+ return ret;
+ }
+
+ public static bool SetResolution(int width, int height, int displayFrequency, int bitsPerPel)
+ {
+ if (!IsInitialized)
+ return false;
+
+ var ret = false;
+ long RetVal = 0;
+ var dm = new Display();
+ dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
+ dm.dmPelsWidth = width;
+ dm.dmPelsHeight = height;
+ dm.dmDisplayFrequency = displayFrequency;
+ dm.dmBitsPerPel = bitsPerPel;
+ dm.dmFields = Display.DM_PELSWIDTH | Display.DM_PELSHEIGHT | Display.DM_DISPLAYFREQUENCY;
+ RetVal = ChangeDisplaySettings(ref dm, CDS_TEST);
+ if (RetVal == 0)
+ {
+ RetVal = ChangeDisplaySettings(ref dm, 0);
+ ret = true;
+ }
+
+ return ret;
+ }
+
+ public static Display GetDisplay(string DeviceName)
+ {
+ var dm = new Display();
+ dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
+ bool mybool;
+ mybool = EnumDisplaySettings(DeviceName, -1, ref dm);
+ return dm;
+ }
+
+ public static List GetResolutions(string DeviceName)
+ {
+ var allMode = new List();
+ var dm = new Display();
+ dm.dmSize = (short)Marshal.SizeOf(typeof(Display));
+ var index = 0;
+ while (EnumDisplaySettings(DeviceName, index, ref dm))
+ {
+ allMode.Add(dm);
+ index++;
+ }
+
+ return allMode;
+ }
+
+ public static void PlayWindowsMedia(string file)
+ {
+ var path = Path.Combine(@"c:\Windows\Media\", file);
+ if (File.Exists(path))
+ new SoundPlayer(path).Play();
+ }
+
+ public static bool HasVolumeSupport()
+ {
+ return VolumeSupport;
+ }
+
+ public static void SetVolume(double volume)
+ {
+ if (!VolumeSupport)
+ return;
+
+ multimediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar = (float)(volume / 100.0d);
+ }
+
+ public static double GetVolume()
+ {
+ if (!VolumeSupport)
+ return 0.0d;
+
+ return multimediaDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100.0d;
+ }
+
+ public static bool HasBrightnessSupport()
+ {
+ return BrightnessSupport;
+ }
+
+ public static void SetBrightness(double brightness)
+ {
+ if (!BrightnessSupport)
+ return;
+
+ try
+ {
+ using (var mclass = new ManagementClass("WmiMonitorBrightnessMethods"))
+ {
+ mclass.Scope = new ManagementScope(@"\\.\root\wmi");
+ using (var instances = mclass.GetInstances())
+ {
+ foreach (ManagementObject instance in instances)
+ {
+ object[] args = { 1, brightness };
+ instance.InvokeMethod("WmiSetBrightness", args);
+ }
+ }
+ }
+ }
+ catch
+ {
+ }
+ }
+
+ public static short GetBrightness()
+ {
+ try
+ {
+ using (var mclass = new ManagementClass("WmiMonitorBrightness"))
+ {
+ mclass.Scope = new ManagementScope(@"\\.\root\wmi");
+ using (var instances = mclass.GetInstances())
+ {
+ foreach (ManagementObject instance in instances)
+ return (byte)instance.GetPropertyValue("CurrentBrightness");
+ }
+ }
+
+ return 0;
+ }
+ catch
+ {
+ }
+
+ return -1;
+ }
+
+ private class MMDeviceNotificationClient : IMMNotificationClient
+ {
+ public void OnDefaultDeviceChanged(DataFlow flow, Role role, string defaultDeviceId)
+ {
+ SetDefaultAudioEndPoint();
+ }
+
+ public void OnDeviceAdded(string deviceId)
+ {
+ }
+
+ public void OnDeviceRemoved(string deviceId)
+ {
+ }
+
+ public void OnDeviceStateChanged(string deviceId, DeviceState newState)
+ {
+ }
+
+ public void OnPropertyValueChanged(string deviceId, PropertyKey key)
+ {
+ }
+ }
+
+ #region imports
+
+ public enum DMDO
+ {
+ DEFAULT = 0,
+ D90 = 1,
+ D180 = 2,
+ D270 = 3
+ }
+
+ public const int CDS_UPDATEREGISTRY = 0x01;
+ public const int CDS_TEST = 0x02;
+ public const int DISP_CHANGE_SUCCESSFUL = 0;
+ public const int DISP_CHANGE_RESTART = 1;
+ public const int DISP_CHANGE_FAILED = -1;
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ public struct Display
+ {
+ public const int DM_DISPLAYFREQUENCY = 0x400000;
+ public const int DM_PELSWIDTH = 0x80000;
+ public const int DM_PELSHEIGHT = 0x100000;
+ private const int CCHDEVICENAME = 32;
+ private const int CCHFORMNAME = 32;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHDEVICENAME)]
+ public string dmDeviceName;
+
+ public short dmSpecVersion;
+ public short dmDriverVersion;
+ public short dmSize;
+ public short dmDriverExtra;
+ public int dmFields;
+
+ public int dmPositionX;
+ public int dmPositionY;
+ public DMDO dmDisplayOrientation;
+ public int dmDisplayFixedOutput;
+
+ public short dmColor;
+ public short dmDuplex;
+ public short dmYResolution;
+ public short dmTTOption;
+ public short dmCollate;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCHFORMNAME)]
+ public string dmFormName;
+
+ public short dmLogPixels;
+ public int dmBitsPerPel;
+ public int dmPelsWidth;
+ public int dmPelsHeight;
+ public int dmDisplayFlags;
+ public int dmDisplayFrequency;
+ public int dmICMMethod;
+ public int dmICMIntent;
+ public int dmMediaType;
+ public int dmDitherType;
+ public int dmReserved1;
+ public int dmReserved2;
+ public int dmPanningWidth;
+ public int dmPanningHeight;
+
+ public override string ToString()
+ {
+ return $"{dmPelsWidth}x{dmPelsHeight}, {dmDisplayFrequency}, {dmBitsPerPel}";
+ }
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern int ChangeDisplaySettings([In] ref Display lpDevMode, int dwFlags);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto)]
+ private static extern bool EnumDisplaySettings(string lpszDeviceName, int iModeNum, ref Display lpDevMode);
+
+ [Flags]
+ public enum DisplayDeviceStateFlags
+ {
+ /// The device is part of the desktop.
+ AttachedToDesktop = 0x1,
+ MultiDriver = 0x2,
+
+ /// The device is part of the desktop.
+ PrimaryDevice = 0x4,
+
+ /// Represents a pseudo device used to mirror application drawing for remoting or other purposes.
+ MirroringDriver = 0x8,
+
+ /// The device is VGA compatible.
+ VGACompatible = 0x16,
+
+ /// The device is removable; it cannot be the primary display.
+ Removable = 0x20,
+
+ /// The device has more display modes than its output devices support.
+ ModesPruned = 0x8000000,
+ Remote = 0x4000000,
+ Disconnect = 0x2000000
+ }
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ public struct DisplayDevice
+ {
+ [MarshalAs(UnmanagedType.U4)] public int cb;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
+ public string DeviceName;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string DeviceString;
+
+ [MarshalAs(UnmanagedType.U4)] public DisplayDeviceStateFlags StateFlags;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string DeviceID;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
+ public string DeviceKey;
+ }
+
+ [DllImport("User32.dll")]
+ private static extern int EnumDisplayDevices(string lpDevice, int iDevNum, ref DisplayDevice lpDisplayDevice,
+ int dwFlags);
+
+ #endregion
+
+ #region events
+
+ public static event RSRStateChangedEventHandler StateChanged_RSR;
+ public delegate void RSRStateChangedEventHandler(bool Supported, bool Enabled, int Sharpness);
+
+ public static event IntegerScalingStateChangedEventHandler StateChanged_IntegerScaling;
+ public delegate void IntegerScalingStateChangedEventHandler(bool Supported, bool Enabled);
+
+ public static event ImageSharpeningISStateChangedEventHandler StateChanged_ImageSharpening;
+ public delegate void ImageSharpeningISStateChangedEventHandler(bool Enabled, int Sharpness);
+
+ public static event GPUScalingStateChangedEventHandler StateChanged_GPUScaling;
+ public delegate void GPUScalingStateChangedEventHandler(bool Supported, bool Enabled, int Mode);
+
+ public static event DisplaySettingsChangedEventHandler DisplaySettingsChanged;
+ public delegate void DisplaySettingsChangedEventHandler(ScreenResolution resolution);
+
+ public static event PrimaryScreenChangedEventHandler PrimaryScreenChanged;
+ public delegate void PrimaryScreenChangedEventHandler(DesktopScreen screen);
+
+ public static event DisplayOrientationChangedEventHandler DisplayOrientationChanged;
+ public delegate void DisplayOrientationChangedEventHandler(ScreenRotation rotation);
+
+ public static event VolumeNotificationEventHandler VolumeNotification;
+ public delegate void VolumeNotificationEventHandler(float volume);
+
+ public static event BrightnessNotificationEventHandler BrightnessNotification;
+ public delegate void BrightnessNotificationEventHandler(int brightness);
+
+ public static event InitializedEventHandler Initialized;
+ public delegate void InitializedEventHandler();
+
+ #endregion
}
\ No newline at end of file
diff --git a/HandheldCompanion/Managers/TaskManager.cs b/HandheldCompanion/Managers/TaskManager.cs
index 876781e95..f3a06d8ad 100644
--- a/HandheldCompanion/Managers/TaskManager.cs
+++ b/HandheldCompanion/Managers/TaskManager.cs
@@ -4,25 +4,27 @@
namespace HandheldCompanion.Managers;
-public class TaskManager : Manager
+public static class TaskManager
{
- private readonly string TaskName;
- private readonly string TaskExecutable;
+ private const string TaskName = "HandheldCompanion";
+ private static string TaskExecutable;
// TaskManager vars
- private Task task;
- private TaskDefinition taskDefinition;
- private TaskService taskService;
+ private static Task task;
+ private static TaskDefinition taskDefinition;
+ private static TaskService taskService;
- public TaskManager(string TaskName, string Executable)
- {
- this.TaskName = TaskName;
- TaskExecutable = Executable;
+ private static bool IsInitialized;
+ public static event InitializedEventHandler Initialized;
+ public delegate void InitializedEventHandler();
+
+ static TaskManager()
+ {
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
}
- private void SettingsManager_SettingValueChanged(string name, object value)
+ private static void SettingsManager_SettingValueChanged(string name, object value)
{
switch (name)
{
@@ -32,16 +34,23 @@ private void SettingsManager_SettingValueChanged(string name, object value)
}
}
- public override void Start()
+ public static void Start(string Executable)
{
+ TaskExecutable = Executable;
taskService = new TaskService();
- task = taskService.FindTask(TaskName);
try
{
+ // get current task, if any, delete it
+ task = taskService.FindTask(TaskName);
if (task is not null)
taskService.RootFolder.DeleteTask(TaskName);
+ }
+ catch { }
+ try
+ {
+ // create a new task
taskDefinition = TaskService.Instance.NewTask();
taskDefinition.Principal.RunLevel = TaskRunLevel.Highest;
taskDefinition.Principal.UserId = WindowsIdentity.GetCurrent().Name;
@@ -56,22 +65,27 @@ public override void Start()
task = TaskService.Instance.RootFolder.RegisterTaskDefinition(TaskName, taskDefinition);
task.Enabled = SettingsManager.GetBoolean("RunAtStartup");
}
- catch
- {
- }
+ catch { }
- base.Start();
+ IsInitialized = true;
+ Initialized?.Invoke();
+
+ LogManager.LogInformation("{0} has started", "TaskManager");
}
- public override void Stop()
+ public static void Stop()
{
if (!IsInitialized)
return;
- base.Stop();
+ IsInitialized = false;
+
+ SettingsManager.SettingValueChanged -= SettingsManager_SettingValueChanged;
+
+ LogManager.LogInformation("{0} has stopped", "TaskManager");
}
- public void UpdateTask(bool value)
+ private static void UpdateTask(bool value)
{
if (task is null)
return;
diff --git a/HandheldCompanion/Managers/UpdateManager.cs b/HandheldCompanion/Managers/UpdateManager.cs
index c9eeb35ab..faa46f28d 100644
--- a/HandheldCompanion/Managers/UpdateManager.cs
+++ b/HandheldCompanion/Managers/UpdateManager.cs
@@ -1,7 +1,7 @@
using HandheldCompanion.Misc;
using HandheldCompanion.Properties;
using HandheldCompanion.Views;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
@@ -14,8 +14,9 @@
namespace HandheldCompanion.Managers;
-public class UpdateManager : Manager
+public static class UpdateManager
{
+ public static event UpdatedEventHandler Updated;
public delegate void UpdatedEventHandler(UpdateStatus status, UpdateFile? update, object? value);
public enum UpdateStatus
@@ -31,17 +32,23 @@ public enum UpdateStatus
Failed
}
- private readonly Assembly assembly;
+ private static readonly Assembly assembly;
- private readonly Version build;
- private DateTime lastchecked;
+ private static readonly Version build;
+ private static DateTime lastchecked;
- private UpdateStatus status;
- private readonly Dictionary updateFiles = new();
- private string url;
- private readonly WebClient webClient;
+ private static UpdateStatus status;
+ private static readonly Dictionary updateFiles = new();
+ private static string url;
+ private static readonly WebClient webClient;
+ private static readonly string InstallPath;
- public UpdateManager()
+ private static bool IsInitialized;
+
+ public static event InitializedEventHandler Initialized;
+ public delegate void InitializedEventHandler();
+
+ static UpdateManager()
{
// check assembly
assembly = Assembly.GetExecutingAssembly();
@@ -65,9 +72,7 @@ public UpdateManager()
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
}
- public event UpdatedEventHandler Updated;
-
- private void SettingsManager_SettingValueChanged(string name, object value)
+ private static void SettingsManager_SettingValueChanged(string name, object value)
{
switch (name)
{
@@ -77,7 +82,7 @@ private void SettingsManager_SettingValueChanged(string name, object value)
}
}
- private int GetFileSize(Uri uriPath)
+ private static int GetFileSize(Uri uriPath)
{
try
{
@@ -96,7 +101,7 @@ private int GetFileSize(Uri uriPath)
}
}
- private void WebClient_DownloadFileCompleted(object? sender, AsyncCompletedEventArgs e)
+ private static void WebClient_DownloadFileCompleted(object? sender, AsyncCompletedEventArgs e)
{
if (status != UpdateStatus.Downloading)
return;
@@ -112,7 +117,7 @@ private void WebClient_DownloadFileCompleted(object? sender, AsyncCompletedEvent
Updated?.Invoke(status, update, null);
}
- private void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
+ private static void WebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (status != UpdateStatus.Download && status != UpdateStatus.Downloading)
return;
@@ -126,7 +131,7 @@ private void WebClient_DownloadProgressChanged(object sender, DownloadProgressCh
}
}
- private void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
+ private static void WebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// something went wrong with the connection
if (e.Error is not null)
@@ -163,7 +168,7 @@ private void WebClient_DownloadStringCompleted(object sender, DownloadStringComp
}
}
- public void DownloadUpdateFile(UpdateFile update)
+ public static void DownloadUpdateFile(UpdateFile update)
{
if (webClient.IsBusy)
return; // lazy
@@ -176,7 +181,7 @@ public void DownloadUpdateFile(UpdateFile update)
webClient.DownloadFileAsync(update.uri, filename, update.filename);
}
- private void ParseLatest(string contentsJson)
+ private static void ParseLatest(string contentsJson)
{
try
{
@@ -244,7 +249,7 @@ private void ParseLatest(string contentsJson)
}
}
- public override void Start()
+ public static void Start()
{
var dateTime = SettingsManager.GetDateTime("UpdateLastChecked");
@@ -253,29 +258,36 @@ public override void Start()
status = UpdateStatus.Initialized;
Updated?.Invoke(status, null, null);
- base.Start();
+ IsInitialized = true;
+ Initialized?.Invoke();
+
+ LogManager.LogInformation("{0} has started", "UpdateManager");
}
- public override void Stop()
+ public static void Stop()
{
if (!IsInitialized)
return;
- base.Stop();
+ IsInitialized = false;
+
+ SettingsManager.SettingValueChanged -= SettingsManager_SettingValueChanged;
+
+ LogManager.LogInformation("{0} has stopped", "UpdateManager");
}
- public DateTime GetTime()
+ public static DateTime GetTime()
{
return lastchecked;
}
- public void UpdateTime()
+ private static void UpdateTime()
{
lastchecked = DateTime.Now;
SettingsManager.SetProperty("UpdateLastChecked", lastchecked);
}
- public void StartProcess()
+ public static void StartProcess()
{
// Update UI
status = UpdateStatus.Checking;
@@ -285,7 +297,7 @@ public void StartProcess()
webClient.DownloadStringAsync(new Uri($"{url}/releases/latest"));
}
- public void InstallUpdate(UpdateFile updateFile)
+ public static void InstallUpdate(UpdateFile updateFile)
{
var filename = Path.Combine(InstallPath, updateFile.filename);
diff --git a/HandheldCompanion/Misc/ADLXBackend.cs b/HandheldCompanion/Misc/ADLXBackend.cs
index 8a88d034b..d64938e01 100644
--- a/HandheldCompanion/Misc/ADLXBackend.cs
+++ b/HandheldCompanion/Misc/ADLXBackend.cs
@@ -4,20 +4,45 @@ namespace HandheldCompanion.Misc
{
public class ADLXBackend
{
- public const string CppFunctionsDLL = @"PerformanceMetrics.dll";
- public const string CppFunctionsDLL1 = @"GraphSettings.dll";
- [DllImport(CppFunctionsDLL, CallingConvention = CallingConvention.Cdecl)] public static extern int GetFPSData();
- [DllImport(CppFunctionsDLL, CallingConvention = CallingConvention.Cdecl)] public static extern int GetGPUMetrics(int GPU, int Sensor);
-
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetFPSLimit(int GPU, bool isEnabled, int FPS);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetAntiLag(int GPU, bool isEnabled);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetBoost(int GPU, bool isEnabled, int percent);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetRSR(bool isEnabled);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int GetRSRState();
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetRSRSharpness(int sharpness);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int GetRSRSharpness();
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetChill(int GPU, bool isEnabled, int maxFPS, int minFPS);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetImageSharpning(int GPU, bool isEnabled, int percent);
- [DllImport(CppFunctionsDLL1, CallingConvention = CallingConvention.Cdecl)] public static extern int SetEnhancedSync(int GPU, bool isEnabled);
+ public const string ADLX_3DSettings = @"ADLX_3DSettings.dll";
+ public const string ADLX_DisplaySettings = @"ADLX_DisplaySettings.dll";
+
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool HasRSRSupport();
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetRSR();
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetRSR(bool enable);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetRSRSharpness();
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetRSRSharpness(int sharpness);
+
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetAntiLag(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetAntiLag(int GPU, bool enable);
+
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetBoost(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetBoost(int GPU, bool enable);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetBoostResolution(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetBoostResolution(int GPU, int minRes);
+
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetChill(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetChill(int GPU, bool enable);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetChillMinFPS(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetChillMinFPS(int GPU, int minFPS);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetChillMaxFPS(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetChillMaxFPS(int GPU, int maxFPS);
+
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetImageSharpening(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetImageSharpening(int GPU, bool enable);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetImageSharpeningSharpness(int GPU);
+ [DllImport(ADLX_3DSettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetImageSharpeningSharpness(int GPU, int sharpness);
+
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool HasIntegerScalingSupport(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetIntegerScaling(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetIntegerScaling(int GPU, bool enabled);
+
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool HasGPUScalingSupport(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool GetGPUScaling(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetGPUScaling(int GPU, bool enabled);
+
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool HasScalingModeSupport(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern int GetScalingMode(int GPU);
+ [DllImport(ADLX_DisplaySettings, CallingConvention = CallingConvention.Cdecl)] public static extern bool SetScalingMode(int GPU, int mode);
}
}
diff --git a/HandheldCompanion/Misc/ADLXWrapper.cs b/HandheldCompanion/Misc/ADLXWrapper.cs
new file mode 100644
index 000000000..949c47684
--- /dev/null
+++ b/HandheldCompanion/Misc/ADLXWrapper.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Threading.Tasks;
+
+namespace HandheldCompanion.Misc
+{
+ public static class ADLXWrapper
+ {
+ private static object ADLXLock = new();
+
+ private static T Execute(Func func, T defaultValue)
+ {
+ lock (ADLXLock)
+ {
+ Task task = Task.Run(func);
+ if (task.Wait(TimeSpan.FromSeconds(5)))
+ {
+ return task.Result;
+ }
+
+ return defaultValue;
+ }
+ }
+
+ // RSR
+ public static bool HasRSRSupport() => Execute(ADLXBackend.HasRSRSupport, false);
+ public static bool GetRSR() => Execute(ADLXBackend.GetRSR, false);
+ public static bool SetRSR(bool enable) => Execute(() => ADLXBackend.SetRSR(enable), false);
+ public static int GetRSRSharpness() => Execute(ADLXBackend.GetRSRSharpness, -1);
+ public static bool SetRSRSharpness(int sharpness) => Execute(() => ADLXBackend.SetRSRSharpness(sharpness), false);
+
+ // ImageSharpening
+ public static bool GetImageSharpening() => Execute(() => ADLXBackend.GetImageSharpening(0), false);
+ public static bool SetImageSharpening(bool enable) => Execute(() => ADLXBackend.SetImageSharpening(0, enable), false);
+ public static int GetImageSharpeningSharpness() => Execute(() => ADLXBackend.GetImageSharpeningSharpness(0), -1);
+ public static bool SetImageSharpeningSharpness(int sharpness) => Execute(() => ADLXBackend.SetImageSharpeningSharpness(0, sharpness), false);
+
+ // IntegerScaling
+ public static bool HasIntegerScalingSupport() => Execute(() => ADLXBackend.HasIntegerScalingSupport(0), false);
+ public static bool GetIntegerScaling() => Execute(() => ADLXBackend.GetIntegerScaling(0), false);
+ public static bool SetIntegerScaling(bool enabled) => Execute(() => ADLXBackend.SetIntegerScaling(0, enabled), false);
+
+ public static bool HasGPUScalingSupport() => Execute(() => ADLXBackend.HasGPUScalingSupport(0), false);
+ public static bool GetGPUScaling() => Execute(() => ADLXBackend.GetGPUScaling(0), false);
+ public static bool SetGPUScaling(bool enabled) => Execute(() => ADLXBackend.SetGPUScaling(0, enabled), false);
+
+ public static bool HasScalingModeSupport() => Execute(() => ADLXBackend.HasScalingModeSupport(0), false);
+ public static int GetScalingMode() => Execute(() => ADLXBackend.GetScalingMode(0), -1);
+ public static bool SetScalingMode(int mode) => Execute(() => ADLXBackend.SetScalingMode(0, mode), false);
+ }
+}
diff --git a/HandheldCompanion/Misc/Dialog.cs b/HandheldCompanion/Misc/Dialog.cs
index 8a62006e4..c83ebe220 100644
--- a/HandheldCompanion/Misc/Dialog.cs
+++ b/HandheldCompanion/Misc/Dialog.cs
@@ -1,4 +1,4 @@
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System.Threading.Tasks;
namespace HandheldCompanion.Misc;
diff --git a/HandheldCompanion/Misc/FanProfile.cs b/HandheldCompanion/Misc/FanProfile.cs
index 72b1a460a..a699e89e4 100644
--- a/HandheldCompanion/Misc/FanProfile.cs
+++ b/HandheldCompanion/Misc/FanProfile.cs
@@ -1,4 +1,5 @@
-using System;
+using HandheldCompanion.Views;
+using System;
using System.Linq;
namespace HandheldCompanion.Misc
@@ -60,11 +61,20 @@ public double GetFanSpeed()
}
// A public method that takes a temperature as a parameter and returns the corresponding fan speed by linear interpolation
+ private bool TjmaxReached = false;
public double GetFanSpeed(double temp)
{
- // Check if the temperature is within the range of 0°C to 100°C
- if (temp < 0 || temp > 100)
- return 50.0d;
+ // Check if the temperature is within the °C range of Tjmax
+ if (temp >= MainWindow.CurrentDevice.Tjmax)
+ TjmaxReached = true;
+
+ if (TjmaxReached)
+ {
+ if (temp <= 80)
+ TjmaxReached = false;
+ else
+ return 100.0d;
+ }
// Find the two closest points that bracket the temperature
int low = (int)Math.Floor(temp / fanSpeeds.Length);
diff --git a/HandheldCompanion/Misc/NightLight.cs b/HandheldCompanion/Misc/NightLight.cs
new file mode 100644
index 000000000..f35bc8ecc
--- /dev/null
+++ b/HandheldCompanion/Misc/NightLight.cs
@@ -0,0 +1,102 @@
+using HandheldCompanion.Utils;
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Management;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HandheldCompanion.Misc
+{
+ public static class NightLight
+ {
+ private static string _key =
+ "Software\\Microsoft\\Windows\\CurrentVersion\\CloudStore\\Store\\DefaultAccount\\Current\\default$windows.data.bluelightreduction.bluelightreductionstate\\windows.data.bluelightreduction.bluelightreductionstate";
+
+ private static RegistryKey _registryKey;
+
+ private static readonly RegistryWatcher _nightLightStateWatcher = new(WatchedRegistry.CurrentUser,
+ @"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\CloudStore\\" +
+ @"Store\\DefaultAccount\\Current\\default$windows.data.bluelightreduction.bluelightreductionstate\\" +
+ @"windows.data.bluelightreduction.bluelightreductionstate", "Data");
+
+ public static bool Enabled
+ {
+ get
+ {
+ if (!Supported) return false;
+
+ byte[] data = new byte[43];
+ byte[] registry = _registryKey?.GetValue("Data") as byte[];
+ Array.Copy(registry, 0, data, 0, registry.Length); // copy the second array into the first array starting at index 5
+ if (data == null) return false;
+ return data[18] == 0x15;
+ }
+ set
+ {
+ if (Supported && Enabled != value) Toggle();
+ }
+ }
+
+ public static bool Supported
+ {
+ get => _registryKey != null;
+ }
+
+ static NightLight()
+ {
+ _registryKey = Registry.CurrentUser.OpenSubKey(_key, true);
+
+ if (!Supported)
+ return;
+
+ _nightLightStateWatcher.RegistryChanged += UpdateNightLight;
+ _nightLightStateWatcher.StartWatching();
+ }
+
+ private static void UpdateNightLight(object? sender, RegistryChangedEventArgs e)
+ {
+ Toggled?.Invoke(Enabled);
+ }
+
+ public static event ToggledEventHandler Toggled;
+ public delegate void ToggledEventHandler(bool enabled);
+
+ private static void Toggle()
+ {
+ byte[] data = new byte[43];
+ byte[] newData = new byte[43];
+ byte[] registry = _registryKey?.GetValue("Data") as byte[];
+ Array.Copy(registry, 0, data, 0, registry.Length); // copy the second array into the first array starting at index 5
+
+ if (Enabled)
+ {
+ newData = new byte[41];
+ Array.Copy(data, 0, newData, 0, 22);
+ Array.Copy(data, 25, newData, 23, 43 - 25);
+ newData[18] = 0x13;
+ }
+ else
+ {
+ Array.Copy(data, 0, newData, 0, 22);
+ Array.Copy(data, 23, newData, 25, 41 - 23);
+ newData[18] = 0x15;
+ newData[23] = 0x10;
+ newData[24] = 0x00;
+ }
+
+ for (int i = 10; i < 15; i++)
+ {
+ if (newData[i] != 0xff)
+ {
+ newData[i]++;
+ break;
+ }
+ }
+
+ _registryKey.SetValue("Data", newData, RegistryValueKind.Binary);
+ _registryKey.Flush();
+ }
+ }
+}
diff --git a/HandheldCompanion/Misc/PowerProfile.cs b/HandheldCompanion/Misc/PowerProfile.cs
index e0735d7e7..a7cb527cb 100644
--- a/HandheldCompanion/Misc/PowerProfile.cs
+++ b/HandheldCompanion/Misc/PowerProfile.cs
@@ -1,5 +1,5 @@
using HandheldCompanion.Managers;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.IO;
@@ -56,6 +56,7 @@ public string Description
public string FileName { get; set; }
public bool Default { get; set; }
+ public bool DeviceDefault { get; set; }
public Version Version { get; set; } = new();
public Guid Guid { get; set; } = Guid.NewGuid();
@@ -83,7 +84,7 @@ public string Description
public FanProfile FanProfile { get; set; } = new();
public int OEMPowerMode { get; set; } = 0xFF;
- public Guid OSPowerMode { get; set; } = PowerMode.BetterPerformance;
+ public Guid OSPowerMode { get; set; } = Managers.OSPowerMode.BetterPerformance;
private Dictionary uIElements = new();
diff --git a/HandheldCompanion/Misc/Profile.cs b/HandheldCompanion/Misc/Profile.cs
index 03a3cabb2..ad5c3e804 100644
--- a/HandheldCompanion/Misc/Profile.cs
+++ b/HandheldCompanion/Misc/Profile.cs
@@ -1,4 +1,5 @@
using HandheldCompanion.Inputs;
+using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
using Newtonsoft.Json;
using System;
@@ -24,8 +25,10 @@ public enum UpdateSource
Background = 0,
ProfilesPage = 1,
QuickProfilesPage = 2,
+ QuickProfilesCreation = 3,
Creation = 4,
- Serializer = 5
+ Serializer = 5,
+ ProfilesPageUpdateOnly = 6
}
[Serializable]
@@ -37,6 +40,8 @@ public partial class Profile : ICloneable, IComparable
public string Name { get; set; } = string.Empty;
public string Path { get; set; } = string.Empty;
+ public bool IsSubProfile { get; set; } = false;
+ public bool IsFavoriteSubProfile { get; set; } = false;
public Guid Guid { get; set; } = Guid.NewGuid();
public string Executable { get; set; } = string.Empty;
@@ -79,18 +84,24 @@ public partial class Profile : ICloneable, IComparable
public float FlickstickDuration { get; set; } = 0.1f;
public float FlickstickSensivity { get; set; } = 3.0f;
- // power
+ // power & graphics
public Guid PowerProfile { get; set; } = new();
-
- public bool FramerateEnabled { get; set; }
- public int FramerateValue { get; set; } = 0;
-
- public bool RSREnabled { get; set; }
- public int RSRSharpness { get; set; } = 20;
-
- public bool CPUCoreEnabled { get; set; }
+ public int FramerateValue { get; set; } = 0; // default RTSS value
+ public bool GPUScaling { get; set;} = false;
+ public int ScalingMode { get; set; } = 0; // default AMD value
+ public bool RSREnabled { get; set; } = false;
+ public int RSRSharpness { get; set; } = 20; // default AMD value
+ public bool IntegerScalingEnabled { get; set; } = false;
+ public int IntegerScalingDivider { get; set; } = 1;
+ public bool RISEnabled { get; set; } = false;
+ public int RISSharpness { get; set; } = 80; // default AMD value
+ public bool CPUCoreEnabled { get; set; } = false;
public int CPUCoreCount { get; set; } = Environment.ProcessorCount;
+ // AppCompatFlags
+ public bool FullScreenOptimization { get; set; } = true;
+ public bool HighDPIAware { get; set; } = true;
+
// emulated controller type, default is default
public HIDmode HID { get; set; } = HIDmode.NotSelected;
@@ -155,12 +166,23 @@ public string GetFileName()
if (!Default)
name = System.IO.Path.GetFileNameWithoutExtension(Executable);
+
+ // sub profile files will be of form "executable - #guid"
+ if (IsSubProfile)
+ name = $"{name} - {Guid}";
return $"{name}.json";
}
public override string ToString()
{
- return Name;
+ // if sub profile, return the following (mainprofile.name - subprofile.name)
+ if (IsSubProfile)
+ {
+ string mainProfileName = ProfileManager.GetProfileForSubProfile(this).Name;
+ return $"{mainProfileName} - {Name}";
+ }
+ else
+ return Name;
}
}
\ No newline at end of file
diff --git a/HandheldCompanion/Platforms/HWiNFO.cs b/HandheldCompanion/Platforms/HWiNFO.cs
deleted file mode 100644
index cf177d6d4..000000000
--- a/HandheldCompanion/Platforms/HWiNFO.cs
+++ /dev/null
@@ -1,673 +0,0 @@
-using HandheldCompanion.Managers;
-using HandheldCompanion.Processors;
-using HandheldCompanion.Utils;
-using System;
-using System.Collections.Concurrent;
-using System.Diagnostics;
-using System.IO;
-using System.IO.MemoryMappedFiles;
-using System.Runtime.InteropServices;
-using System.Threading;
-using System.Timers;
-using System.Windows;
-using Timer = System.Timers.Timer;
-
-namespace HandheldCompanion.Platforms;
-
-public class HWiNFO : IPlatform
-{
- public enum SensorElementType
- {
- CPUTemperature,
- CPUFrequency,
- CPUPower,
- CPUUsage,
-
- GPUTemperature,
- GPUFrequency,
- GPUPower,
- GPUUsage,
- GPUMemoryUsage,
-
- PL1,
- PL2,
-
- BatteryChargeLevel,
- BatteryRemainingCapacity,
- BatteryRemainingTime,
-
- PhysicalMemoryUsage,
- VirtualMemoryUsage
- }
-
- private const string HWiNFO_SHARED_MEM_FILE_NAME = "Global\\HWiNFO_SENS_SM2";
- private const int HWiNFO_SENSORS_STRING_LEN = 128;
- private const int HWiNFO_UNIT_STRING_LEN = 16;
- private const int MemoryInterval = 1000;
-
- private readonly Timer MemoryTimer;
-
- private SharedMemory HWiNFOMemory;
-
- private ConcurrentDictionary HWiNFOSensors;
- private MemoryMappedViewAccessor MemoryAccessor;
-
- private MemoryMappedFile MemoryMapped;
-
- public ConcurrentDictionary MonitoredSensors = new();
-
- private long prevPoll_time = -1;
-
- public HWiNFO()
- {
- PlatformType = PlatformType.HWiNFO;
- ExpectedVersion = new Version(7, 42, 5030);
- Url = "https://www.hwinfo.com/files/hwi_742.exe";
-
- Name = "HWiNFO64";
- ExecutableName = RunningName = "HWiNFO64.exe";
-
- // check if platform is installed
- InstallPath = RegistryUtils.GetString(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\HWiNFO64_is1",
- "InstallLocation");
- if (Path.Exists(InstallPath))
- {
- // update paths
- SettingsPath = Path.Combine(InstallPath, "HWiNFO64.ini");
- ExecutablePath = Path.Combine(InstallPath, ExecutableName);
-
- // check executable
- if (File.Exists(ExecutablePath))
- {
- // check executable version
- var versionInfo = FileVersionInfo.GetVersionInfo(ExecutablePath);
- var CurrentVersion = new Version(versionInfo.ProductMajorPart, versionInfo.ProductMinorPart,
- versionInfo.ProductBuildPart);
-
- if (CurrentVersion < ExpectedVersion)
- {
- LogManager.LogWarning("HWiNFO is outdated. Please get it from: {0}", Url);
- return;
- }
-
- IsInstalled = true;
- }
- }
-
- if (!IsInstalled)
- {
- LogManager.LogWarning("HWiNFO is missing. Please get it from: {0}", Url);
- return;
- }
-
- // those are used for computes
- MonitoredSensors[SensorElementType.PL1] = new SensorElement();
- MonitoredSensors[SensorElementType.PL2] = new SensorElement();
- MonitoredSensors[SensorElementType.CPUFrequency] = new SensorElement();
- MonitoredSensors[SensorElementType.GPUFrequency] = new SensorElement();
-
- // file watcher
- if (File.Exists(SettingsPath))
- {
- systemWatcher = new(Path.GetDirectoryName(SettingsPath));
- systemWatcher.Filter = "*.ini";
- systemWatcher.EnableRaisingEvents = true;
- systemWatcher.Changed += SystemWatcher_Changed;
- }
-
- // our main watchdog to (re)apply requested settings
- PlatformWatchdog = new Timer(3000) { Enabled = false };
- PlatformWatchdog.Elapsed += Watchdog_Elapsed;
-
- // secondary watchdog to (re)populate sensors
- MemoryTimer = new Timer(MemoryInterval) { Enabled = false };
- MemoryTimer.Elapsed += (sender, e) => PopulateSensors();
- }
-
- private void SystemWatcher_Changed(object sender, FileSystemEventArgs e)
- {
- bool SensorsSM = GetProperty("SensorsSM");
- SystemWatcher_Changed("SensorsSM", SensorsSM);
- }
-
- public override bool Start()
- {
- // start HWiNFO if not running
- if (!IsRunning)
- {
- StartProcess();
- }
- else
- {
- // hook into current process
- Process.Exited += Process_Exited;
- }
-
- SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
-
- return base.Start();
- }
-
- public override bool Stop(bool kill = false)
- {
- if (MemoryTimer is not null)
- MemoryTimer.Stop();
-
- SettingsManager.SettingValueChanged -= SettingsManager_SettingValueChanged;
-
- return base.Stop(kill);
- }
-
- private void SettingsManager_SettingValueChanged(string name, object value)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- switch (name)
- {
- case "OnScreenDisplayRefreshRate":
- SetProperty("SensorInterval", Convert.ToInt32(value));
- break;
- }
- });
- }
-
- private void Watchdog_Elapsed(object? sender, ElapsedEventArgs e)
- {
- if (Monitor.TryEnter(updateLock))
- {
- try
- {
- // check shared memory
- MemoryMappedFile.OpenExisting(HWiNFO_SHARED_MEM_FILE_NAME, MemoryMappedFileRights.Read);
- }
- catch
- {
- // not authorized
- // shared memory is disabled
-
- // raise event
- SetStatus(PlatformStatus.Stalled);
- Monitor.Exit(updateLock);
- return;
- }
-
- // we couldn't poll HWiNFO, halt process
- if (HWiNFOMemory.poll_time == prevPoll_time)
- {
- // raise event
- SetStatus(PlatformStatus.Stalled);
- Monitor.Exit(updateLock);
- return;
- }
-
- // update poll time
- if (HWiNFOMemory.poll_time != 0)
- prevPoll_time = HWiNFOMemory.poll_time;
-
- // reset tentative counter
- Tentative = 0;
-
- // connect to shared memory
- if (MemoryMapped is null)
- MemoryMapped = MemoryMappedFile.OpenExisting(HWiNFO_SHARED_MEM_FILE_NAME, MemoryMappedFileRights.Read);
-
- // get accessor
- if (MemoryAccessor is null)
- MemoryAccessor =
- MemoryMapped.CreateViewAccessor(0L, Marshal.SizeOf(typeof(SharedMemory)), MemoryMappedFileAccess.Read);
- MemoryAccessor.Read(0L, out HWiNFOMemory);
-
- // we listed sensors already
- if (HWiNFOSensors is null)
- {
- // (re)set sensors array
- HWiNFOSensors = new ConcurrentDictionary();
-
- // populate sensors array
- GetSensors();
- }
-
- MemoryTimer.Start();
-
- Monitor.Exit(updateLock);
- }
- }
-
- public void GetSensors()
- {
- try
- {
- for (uint index = 0; index < HWiNFOMemory.dwNumSensorElements; ++index)
- using (var viewStream = MemoryMapped.CreateViewStream(
- HWiNFOMemory.dwOffsetOfSensorSection + index * HWiNFOMemory.dwSizeOfSensorElement,
- HWiNFOMemory.dwSizeOfSensorElement, MemoryMappedFileAccess.Read))
- {
- var buffer = new byte[(int)HWiNFOMemory.dwSizeOfSensorElement];
- viewStream.Read(buffer, 0, (int)HWiNFOMemory.dwSizeOfSensorElement);
- var gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
- var structure =
- (SensorStructure)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(SensorStructure));
- gcHandle.Free();
- var sensor = new Sensor
- {
- NameOrig = structure.szSensorNameOrig,
- NameUser = structure.szSensorNameUser,
- Elements = new ConcurrentDictionary()
- };
- HWiNFOSensors[index] = sensor;
- }
- }
- catch
- {
- // do something
- }
- }
-
- public void PopulateSensors()
- {
- if (MemoryMapped is null)
- return;
-
- try
- {
- for (uint index = 0; index < HWiNFOMemory.dwNumReadingElements; ++index)
- using (var viewStream = MemoryMapped.CreateViewStream(
- HWiNFOMemory.dwOffsetOfReadingSection + index * HWiNFOMemory.dwSizeOfReadingElement,
- HWiNFOMemory.dwSizeOfReadingElement, MemoryMappedFileAccess.Read))
- {
- var buffer = new byte[(int)HWiNFOMemory.dwSizeOfReadingElement];
- viewStream.Read(buffer, 0, (int)HWiNFOMemory.dwSizeOfReadingElement);
- var gcHandle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
-
- var element =
- (SensorElement)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(SensorElement));
- gcHandle.Free();
-
- if (HWiNFOSensors.TryGetValue(element.dwSensorIndex, out var sensor))
- sensor.Elements[element.dwSensorID] = element;
- else
- continue;
-
- switch (element.tReading)
- {
- case SENSOR_READING_TYPE.SENSOR_TYPE_TEMP:
- {
- switch (element.szLabelOrig)
- {
- case "CPU Package":
- case "CPU (Tctl/Tdie)":
- MonitoredSensors[SensorElementType.CPUTemperature] = element;
- break;
-
- case "CPU GT Cores (Graphics)":
- case "GPU Temperature":
- MonitoredSensors[SensorElementType.GPUTemperature] = element;
- break;
- }
- }
- break;
-
- case SENSOR_READING_TYPE.SENSOR_TYPE_POWER:
- {
- switch (element.szLabelOrig)
- {
- case "CPU Package Power":
- case "CPU PPT":
- MonitoredSensors[SensorElementType.CPUPower] = element;
- break;
-
- case "PL1 Power Limit":
- // case "PL1 Power Limit (Static)":
- case "PL1 Power Limit (Dynamic)":
- {
- var reading = (int)Math.Ceiling(element.Value);
- if (reading != MonitoredSensors[SensorElementType.PL1].Value)
- PowerLimitChanged?.Invoke(PowerType.Slow, reading);
-
- element.Value = reading;
- MonitoredSensors[SensorElementType.PL1] = element;
- }
- break;
- case "PL2 Power Limit":
- // case "PL2 Power Limit (Static)":
- case "PL2 Power Limit (Dynamic)":
- {
- var reading = (int)Math.Ceiling(element.Value);
- if (reading != MonitoredSensors[SensorElementType.PL2].Value)
- PowerLimitChanged?.Invoke(PowerType.Fast, reading);
-
- element.Value = reading;
- MonitoredSensors[SensorElementType.PL2] = element;
- }
- break;
-
- case "GPU ASIC Power":
- case "GT Cores Power":
- case "GPU SoC Power (VDDCR_SOC)":
- case "GPU PPT":
- MonitoredSensors[SensorElementType.GPUPower] = element;
- break;
- }
- }
- break;
-
- case SENSOR_READING_TYPE.SENSOR_TYPE_USAGE:
- {
- switch (element.szLabelOrig)
- {
- case "GPU Utilization":
- case "GPU D3D Usage":
- MonitoredSensors[SensorElementType.GPUUsage] = element;
- break;
-
- case "Total CPU Usage":
- MonitoredSensors[SensorElementType.CPUUsage] = element;
- break;
-
- case "CPU PPT SLOW Limit":
- {
- var reading = (int)Math.Floor(MonitoredSensors[SensorElementType.CPUPower].Value /
- element.Value * 100.0d);
- if (reading != MonitoredSensors[SensorElementType.PL1].Value)
- PowerLimitChanged?.Invoke(PowerType.Slow, reading);
-
- element.Value = reading;
- MonitoredSensors[SensorElementType.PL1] = element;
- }
- break;
- case "CPU PPT FAST Limit":
- {
- var reading = (int)Math.Floor(MonitoredSensors[SensorElementType.CPUPower].Value /
- element.Value * 100.0d);
- if (reading != MonitoredSensors[SensorElementType.PL2].Value)
- PowerLimitChanged?.Invoke(PowerType.Fast, reading);
-
- element.Value = reading;
- MonitoredSensors[SensorElementType.PL2] = element;
- }
- break;
- }
- }
- break;
-
- case SENSOR_READING_TYPE.SENSOR_TYPE_CLOCK:
- {
- switch (element.szLabelOrig)
- {
- case "GPU Clock":
- case "GPU SoC Clock": // keep me ?
- {
- var reading = element.Value;
- if (reading != MonitoredSensors[SensorElementType.GPUFrequency].Value)
- GPUFrequencyChanged?.Invoke(reading);
-
- MonitoredSensors[SensorElementType.GPUFrequency] = element;
- }
- break;
-
- case "Core 0 Clock":
- case "Core 1 Clock":
- case "Core 2 Clock":
- case "Core 3 Clock":
- case "Core 4 Clock":
- case "Core 5 Clock":
- case "Core 6 Clock":
- case "Core 7 Clock":
- case "Core 8 Clock":
- case "Core 9 Clock":
- case "Core 10 Clock":
- case "Core 11 Clock":
- case "Core 12 Clock":
- case "Core 13 Clock":
- case "Core 14 Clock":
- case "Core 15 Clock":
- case "Core 16 Clock":
- case "Core 17 Clock":
- case "Core 18 Clock": // improve me (lol)
- {
- // we'll keep the highest known frequency right now
- if (element.Value > MonitoredSensors[SensorElementType.CPUFrequency].Value)
- MonitoredSensors[SensorElementType.CPUFrequency] = element;
- }
- break;
- }
- }
- break;
-
- case SENSOR_READING_TYPE.SENSOR_TYPE_VOLT:
- {
- }
- break;
-
- case SENSOR_READING_TYPE.SENSOR_TYPE_OTHER:
- {
- }
- break;
- }
-
- // move me !
- switch (element.szLabelOrig)
- {
- case "Remaining Capacity":
- MonitoredSensors[SensorElementType.BatteryRemainingCapacity] = element;
- break;
- case "Charge Level":
- MonitoredSensors[SensorElementType.BatteryChargeLevel] = element;
- break;
- case "Estimated Remaining Time":
- MonitoredSensors[SensorElementType.BatteryRemainingTime] = element;
- break;
-
- case "Physical Memory Used":
- MonitoredSensors[SensorElementType.PhysicalMemoryUsage] = element;
- break;
- case "Virtual Memory Committed":
- MonitoredSensors[SensorElementType.VirtualMemoryUsage] = element;
- break;
-
- case "GPU D3D Memory Dynamic":
- case "GPU Memory Usage":
- MonitoredSensors[SensorElementType.GPUMemoryUsage] = element;
- break;
- }
- // Debug.WriteLine("{0}:\t\t{1} {2}\t{3}", sensor.szLabelOrig, sensor.Value, sensor.szUnit, sensor.tReading);
- }
- }
- catch
- {
- // do something
- }
- }
-
- public bool SetProperty(string propertyName, object value)
- {
- try
- {
- IniFile settings = new(SettingsPath);
- settings.Write(propertyName, Convert.ToString(value), "Settings");
-
- return true;
- }
- catch
- {
- return false;
- }
- }
-
- public bool GetProperty(string propertyName)
- {
- try
- {
- IniFile settings = new(SettingsPath);
- string value = settings.Read(propertyName, "Settings");
-
- if (string.IsNullOrEmpty(value))
- return false;
-
- return Convert.ToBoolean(Convert.ToInt16(value));
- }
- catch
- {
- return false;
- }
- }
-
- public override bool StartProcess()
- {
- if (!IsInstalled)
- return false;
-
- if (IsRunning)
- KillProcess();
-
- // (re)set elements
- DisposeMemory();
-
- // Quiet startup
- SetProperty("OpenSystemSummary", 0);
- SetProperty("OpenSensors", 1);
- SetProperty("MinimalizeMainWnd", 1);
- SetProperty("MinimalizeSensors", 1);
- SetProperty("MinimalizeSensorsClose", 1);
- SetProperty("ShowWelcomeAndProgress", 0);
- SetProperty("SensorsOnly", 1);
- SetProperty("AutoUpdateBetaDisable", 1);
- SetProperty("AutoUpdate", 0);
-
- // stop watchdog
- PlatformWatchdog.Stop();
-
- return base.StartProcess();
- }
-
- public override bool StopProcess()
- {
- if (IsStarting)
- return false;
-
- KillProcess();
-
- return true;
- }
-
- public void ReaffirmRunningProcess()
- {
- if (!IsRunning)
- StartProcess();
- }
-
- private void DisposeMemory()
- {
- if (MemoryMapped is not null)
- {
- MemoryMapped.Dispose();
- MemoryMapped = null;
- }
-
- if (MemoryAccessor is not null)
- {
- MemoryAccessor.Dispose();
- MemoryAccessor = null;
- }
-
- if (HWiNFOSensors is not null)
- HWiNFOSensors = null;
-
- prevPoll_time = -1;
- }
-
- public override void Dispose()
- {
- DisposeMemory();
- base.Dispose();
- }
-
- #region struct
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct SharedMemory
- {
- public uint dwSignature;
- public uint dwVersion;
- public uint dwRevision;
- public long poll_time;
- public uint dwOffsetOfSensorSection;
- public uint dwSizeOfSensorElement;
- public uint dwNumSensorElements;
- public uint dwOffsetOfReadingSection;
- public uint dwSizeOfReadingElement;
- public uint dwNumReadingElements;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct SensorStructure
- {
- public uint dwSensorID;
- public uint dwSensorInst;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string szSensorNameOrig;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string szSensorNameUser;
- }
-
- [StructLayout(LayoutKind.Sequential, Pack = 1)]
- public struct SensorElement
- {
- public SENSOR_READING_TYPE tReading;
- public uint dwSensorIndex;
- public uint dwSensorID;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string szLabelOrig;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string szLabelUser;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_UNIT_STRING_LEN)]
- public string szUnit;
-
- public double Value;
- public double FanValueMin;
- public double FanValueMax;
- public double ValueAvg;
- }
-
- public enum SENSOR_READING_TYPE
- {
- SENSOR_TYPE_NONE,
- SENSOR_TYPE_TEMP,
- SENSOR_TYPE_VOLT,
- SENSOR_TYPE_FAN,
- SENSOR_TYPE_CURRENT,
- SENSOR_TYPE_POWER,
- SENSOR_TYPE_CLOCK,
- SENSOR_TYPE_USAGE,
- SENSOR_TYPE_OTHER
- }
-
- public class Sensor
- {
- public ConcurrentDictionary Elements;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string NameOrig;
-
- [MarshalAs(UnmanagedType.ByValTStr, SizeConst = HWiNFO_SENSORS_STRING_LEN)]
- public string NameUser;
- }
-
- #endregion
-
- #region events
-
- public event LimitChangedHandler PowerLimitChanged;
- public delegate void LimitChangedHandler(PowerType type, int limit);
-
- public event GPUFrequencyChangedHandler GPUFrequencyChanged;
- public delegate void GPUFrequencyChangedHandler(double value);
-
- #endregion
-}
diff --git a/HandheldCompanion/Platforms/IPlatform.cs b/HandheldCompanion/Platforms/IPlatform.cs
index 78c25799f..004c12ae3 100644
--- a/HandheldCompanion/Platforms/IPlatform.cs
+++ b/HandheldCompanion/Platforms/IPlatform.cs
@@ -19,8 +19,7 @@ public enum PlatformType
Origin = 2,
UbisoftConnect = 3,
GOG = 4,
- RTSS = 5,
- HWiNFO = 6
+ RTSS = 5
}
public enum PlatformStatus
diff --git a/HandheldCompanion/Platforms/LibreHardwareMonitor.cs b/HandheldCompanion/Platforms/LibreHardwareMonitor.cs
new file mode 100644
index 000000000..46a0065ba
--- /dev/null
+++ b/HandheldCompanion/Platforms/LibreHardwareMonitor.cs
@@ -0,0 +1,347 @@
+using LibreHardwareMonitor.Hardware;
+using System.Timers;
+
+namespace HandheldCompanion.Platforms
+{
+ public class LibreHardwareMonitor : IPlatform
+ {
+ private Computer computer;
+ private string ProductName;
+
+ private Timer updateTimer;
+ private int updateInterval = 1000;
+
+ public float? CPULoad;
+ public float? CPUClock;
+ public float? CPUPower;
+ public float? CPUTemperatur;
+
+ public float? GPULoad;
+ public float? GPUClock;
+ public float? GPUPower;
+ public float? GPUTemperatur;
+
+ public float? MemoryLoad;
+
+ public float? VRAMLoad;
+
+ public float? BatteryLevel;
+ public float? BatteryPower;
+ public float? BatteryTimeSpan;
+
+ public LibreHardwareMonitor()
+ {
+ Name = "LibreHardwareMonitor";
+ IsInstalled = true;
+
+ ProductName = MotherboardInfo.Product;
+
+ // watchdog to populate sensors
+ updateTimer = new Timer(updateInterval) { Enabled = false };
+ updateTimer.Elapsed += UpdateTimer_Elapsed;
+
+ // prepare for sensors reading
+ computer = new Computer
+ {
+ IsCpuEnabled = true,
+ IsGpuEnabled = true,
+ IsMemoryEnabled = true,
+ IsBatteryEnabled = true,
+ };
+ }
+
+ public override bool Start()
+ {
+ // open computer, slow
+ computer.Open();
+
+ updateTimer.Start();
+
+ return base.Start();
+ }
+
+ public override bool Stop(bool kill = false)
+ {
+ if (updateTimer is not null)
+ updateTimer.Stop();
+
+ if (computer is not null)
+ computer.Close();
+
+ return base.Stop(kill);
+ }
+
+ private void UpdateTimer_Elapsed(object? sender, ElapsedEventArgs e)
+ {
+ // pull temperature sensor
+ foreach (var hardware in computer.Hardware)
+ {
+ hardware.Update();
+ switch (hardware.HardwareType)
+ {
+ case HardwareType.Cpu:
+ HandleCPU(hardware);
+ break;
+ case HardwareType.GpuAmd:
+ case HardwareType.GpuIntel:
+ case HardwareType.GpuNvidia:
+ HandleGPU(hardware);
+ break;
+ case HardwareType.Memory:
+ HandleMemory(hardware);
+ break;
+ case HardwareType.Battery:
+ HandleBattery(hardware);
+ break;
+ }
+ }
+ }
+
+ #region cpu updates
+ private void HandleCPU(IHardware cpu)
+ {
+ float highestClock = 0;
+ foreach (var sensor in cpu.Sensors)
+ {
+ switch (sensor.SensorType)
+ {
+ case SensorType.Load:
+ HandleCPU_Load(sensor);
+ break;
+ case SensorType.Clock:
+ highestClock = HandleCPU_Clock(sensor, highestClock);
+ break;
+ case SensorType.Power:
+ HandleCPU_Power(sensor);
+ break;
+ case SensorType.Temperature:
+ HandleCPU_Temperatur(sensor);
+ break;
+ }
+ }
+ }
+
+ private void HandleCPU_Load(ISensor sensor)
+ {
+ if (sensor.Name == "CPU Total")
+ {
+ CPULoad = (float)sensor.Value;
+ CPUPowerChanged?.Invoke(CPULoad);
+ }
+ }
+
+ private float HandleCPU_Clock(ISensor sensor, float currentHighest)
+ {
+ if ((sensor.Name.StartsWith("CPU Core #") || sensor.Name.StartsWith("Core #")))
+ {
+ var value = (float)sensor.Value;
+ if (value > currentHighest)
+ {
+ CPUClock = (float)sensor.Value;
+ CPULoadChanged?.Invoke(CPUPower);
+ return value;
+ }
+ }
+ return currentHighest;
+ }
+
+ private void HandleCPU_Power(ISensor sensor)
+ {
+ if (sensor.Name == "Package")
+ {
+ CPUPower = (float)sensor.Value;
+ CPULoadChanged?.Invoke(CPUPower);
+ }
+ }
+
+ private void HandleCPU_Temperatur(ISensor sensor)
+ {
+ if (sensor.Name == "CPU Package" || sensor.Name == "Core (Tctl/Tdie)")
+ {
+ CPUTemperatur = (float)sensor.Value;
+
+ // dirty
+ switch (ProductName)
+ {
+ case "Galileo":
+ CPUTemperatur /= 2.0f;
+ break;
+ }
+
+ CPUTemperatureChanged?.Invoke(CPUTemperatur);
+ }
+ }
+ #endregion
+
+ #region gpu updates
+ private void HandleGPU(IHardware cpu)
+ {
+ float highestClock = 0;
+ foreach (var sensor in cpu.Sensors)
+ {
+ switch (sensor.SensorType)
+ {
+ case SensorType.Load:
+ HandleGPU_Load(sensor);
+ break;
+ case SensorType.Clock:
+ highestClock = HandleGPU_Clock(sensor, highestClock);
+ break;
+ case SensorType.Power:
+ HandleGPU_Power(sensor);
+ break;
+ case SensorType.Temperature:
+ HandleGPU_Temperatur(sensor);
+ break;
+ }
+ }
+ }
+
+ private void HandleGPU_Load(ISensor sensor)
+ {
+ if (sensor.Name == "GPU Core")
+ {
+ GPULoad = (float)sensor.Value;
+ GPULoadChanged?.Invoke(GPULoad);
+ }
+ if (sensor.Name == "GPU Memory")
+ {
+ VRAMLoad = (float)sensor.Value;
+ VRAMLoadChanged?.Invoke(VRAMLoad);
+ }
+ }
+
+ private float HandleGPU_Clock(ISensor sensor, float currentHighest)
+ {
+ if (sensor.Name == "GPU Core")
+ {
+ var value = (float)sensor.Value;
+ if (value > currentHighest)
+ {
+ GPUClock = (float)sensor.Value;
+ GPUClockChanged?.Invoke(GPUClock);
+ return value;
+ }
+ }
+ return currentHighest;
+ }
+
+ private void HandleGPU_Power(ISensor sensor)
+ {
+ if (sensor.Name == "GPU Core")
+ {
+ GPUPower = (float)sensor.Value;
+ GPUPowerChanged?.Invoke(GPUPower);
+ }
+ }
+
+ private void HandleGPU_Temperatur(ISensor sensor)
+ {
+ if (sensor.Name == "GPU Core")
+ {
+ GPUTemperatur = (float)sensor.Value;
+ GPUTemperatureChanged?.Invoke(GPUTemperatur);
+ }
+ }
+ #endregion
+
+ #region memory updates
+ private void HandleMemory(IHardware cpu)
+ {
+ foreach (var sensor in cpu.Sensors)
+ {
+ switch (sensor.SensorType)
+ {
+ case SensorType.Load:
+ HandleMemory_Load(sensor);
+ break;
+ }
+ }
+ }
+
+ private void HandleMemory_Load(ISensor sensor)
+ {
+ if (sensor.Name == "Memory")
+ {
+ MemoryLoad = (float)sensor.Value;
+ MemoryLoadChanged?.Invoke(MemoryLoad);
+ }
+ }
+ #endregion
+
+ #region battery updates
+ private void HandleBattery(IHardware cpu)
+ {
+ foreach (var sensor in cpu.Sensors)
+ {
+ switch (sensor.SensorType)
+ {
+ case SensorType.Level:
+ HandleBattery_Level(sensor);
+ break;
+ case SensorType.Power:
+ HandleBattery_Power(sensor);
+ break;
+ case SensorType.TimeSpan:
+ HandleBattery_TimeSpan(sensor);
+ break;
+ }
+ }
+ }
+
+ private void HandleBattery_Level(ISensor sensor)
+ {
+ if (sensor.Name == "Charge Level")
+ {
+ BatteryLevel = (float)sensor.Value;
+ BatteryLevelChanged?.Invoke(BatteryLevel);
+ }
+ }
+
+ private void HandleBattery_Power(ISensor sensor)
+ {
+ if (sensor.Name == "Charge Rate")
+ {
+ BatteryPower = (float)sensor.Value;
+ BatteryPowerChanged?.Invoke(BatteryPower);
+ }
+ if (sensor.Name == "Discharge Rate")
+ {
+ BatteryPower = -(float)sensor.Value;
+ BatteryPowerChanged?.Invoke(BatteryPower);
+ }
+ }
+
+ private void HandleBattery_TimeSpan(ISensor sensor)
+ {
+ if (sensor.Name == "Remaining Time (Estimated)")
+ {
+ BatteryTimeSpan = ((float)sensor.Value) / 60;
+ BatteryTimeSpanChanged?.Invoke(BatteryTimeSpan);
+ }
+ }
+ #endregion
+
+ #region events
+ public delegate void ChangedHandler(float? value);
+
+ public event ChangedHandler CPULoadChanged;
+ public event ChangedHandler CPUPowerChanged;
+ public event ChangedHandler CPUClockChanged;
+ public event ChangedHandler CPUTemperatureChanged;
+
+ public event ChangedHandler GPULoadChanged;
+ public event ChangedHandler GPUClockChanged;
+ public event ChangedHandler GPUPowerChanged;
+ public event ChangedHandler GPUTemperatureChanged;
+
+ public event ChangedHandler MemoryLoadChanged;
+
+ public event ChangedHandler VRAMLoadChanged;
+
+ public event ChangedHandler BatteryLevelChanged;
+ public event ChangedHandler BatteryPowerChanged;
+ public event ChangedHandler BatteryTimeSpanChanged;
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/HandheldCompanion/Platforms/RTSS.cs b/HandheldCompanion/Platforms/RTSS.cs
index 81f3724a6..d3e9265f3 100644
--- a/HandheldCompanion/Platforms/RTSS.cs
+++ b/HandheldCompanion/Platforms/RTSS.cs
@@ -124,23 +124,31 @@ public override bool Stop(bool kill = false)
ProfileManager.Applied -= ProfileManager_Applied;
return base.Stop(kill);
- }
-
- private void ProfileManager_Applied(Profile profile, UpdateSource source)
- {
- if (profile.FramerateEnabled)
- {
- // Apply profile-defined framerate
- int frequency = (int)Math.Floor(SystemManager.GetDesktopScreen().GetFrequency()
- .GetValue((Frequency)profile.FramerateValue));
- RequestFPS(frequency);
- }
- else if (RequestedFramerate > 0 && !profile.FramerateEnabled)
- {
- // Reset to 0 only when a cap was set previously and the current profile has no limit
- // These conditions prevent 0 from being set on every profile change
- RequestFPS(0); // Restore default framerate
- }
+ }
+
+ private void ProfileManager_Applied(Profile profile, UpdateSource source)
+ {
+ int frameLimit = 0;
+
+ DesktopScreen desktopScreen = SystemManager.GetDesktopScreen();
+
+ if (desktopScreen is not null)
+ {
+ // Determine most approriate frame rate limit based on screen frequency
+ frameLimit = desktopScreen.GetClosest(profile.FramerateValue).limit;
+ }
+
+ if (frameLimit > 0)
+ {
+ // Apply profile-defined framerate
+ RequestFPS(frameLimit);
+ }
+ else if (frameLimit == 0 && RequestedFramerate > 0)
+ {
+ // Reset to 0 only when a cap was set previously and the current profile has no limit
+ // These conditions prevent 0 from being set on every profile change
+ RequestFPS(frameLimit);
+ }
}
private async void ProcessManager_ForegroundChanged(ProcessEx processEx, ProcessEx backgroundEx)
diff --git a/HandheldCompanion/Presets/ColorPresetResources.cs b/HandheldCompanion/Presets/ColorPresetResources.cs
index 816cf9a87..d45ca3946 100644
--- a/HandheldCompanion/Presets/ColorPresetResources.cs
+++ b/HandheldCompanion/Presets/ColorPresetResources.cs
@@ -1,4 +1,4 @@
-using Inkore.UI.WPF.Modern;
+using iNKORE.UI.WPF.Modern;
using System;
using System.Windows;
diff --git a/HandheldCompanion/Processors/AMDProcessor.cs b/HandheldCompanion/Processors/AMDProcessor.cs
index d0e210d3c..4062cb52c 100644
--- a/HandheldCompanion/Processors/AMDProcessor.cs
+++ b/HandheldCompanion/Processors/AMDProcessor.cs
@@ -203,22 +203,22 @@ public override void SetGPUClock(double clock, int result)
default:
{
- int error1, error2, error3;
+ int error1 = RyzenAdj.set_gfx_clk(ry, (uint)clock);
+ /*
if (clock == 12750)
{
- error1 = RyzenAdj.set_gfx_clk(ry, (uint)clock);
error2 = RyzenAdj.set_min_gfxclk_freq(ry, (uint)MainWindow.CurrentDevice.GfxClock[0]);
error3 = RyzenAdj.set_max_gfxclk_freq(ry, (uint)MainWindow.CurrentDevice.GfxClock[1]);
}
else
{
- error1 = RyzenAdj.set_gfx_clk(ry, (uint)clock);
error2 = RyzenAdj.set_min_gfxclk_freq(ry, (uint)clock);
error3 = RyzenAdj.set_max_gfxclk_freq(ry, (uint)clock);
}
+ */
- base.SetGPUClock(clock, error1 + error2 + error3);
+ base.SetGPUClock(clock, error1);
}
break;
}
diff --git a/HandheldCompanion/Processors/Processor.cs b/HandheldCompanion/Processors/Processor.cs
index ae2c58b9e..c5ee16530 100644
--- a/HandheldCompanion/Processors/Processor.cs
+++ b/HandheldCompanion/Processors/Processor.cs
@@ -67,9 +67,9 @@ public static Processor GetCurrent()
public virtual void Initialize()
{
StatusChanged?.Invoke(CanChangeTDP, CanChangeGPU);
- Initialized?.Invoke();
+ Initialized?.Invoke(this);
- // deprecated, we're using HWiNFO to provide values and limits
+ // deprecated, we're using LibreHardwareMonitor to provide values and limits
/*
if (CanChangeTDP)
updateTimer.Start();
@@ -78,7 +78,7 @@ public virtual void Initialize()
public virtual void Stop()
{
- // deprecated, we're using HWiNFO to provide values and limits
+ // deprecated, we're using LibreHardwareMonitor to provide values and limits
/*
if (CanChangeTDP)
updateTimer.Stop();
@@ -160,7 +160,7 @@ protected virtual void UpdateTimer_Elapsed(object sender, ElapsedEventArgs e)
public event InitializedEventHandler Initialized;
- public delegate void InitializedEventHandler();
+ public delegate void InitializedEventHandler(Processor processor);
#endregion
}
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.Designer.cs b/HandheldCompanion/Properties/Resources.Designer.cs
index 51e39ce08..ed38d8465 100644
--- a/HandheldCompanion/Properties/Resources.Designer.cs
+++ b/HandheldCompanion/Properties/Resources.Designer.cs
@@ -1006,6 +1006,15 @@ public static string DevicePage_PowerOptions {
}
}
+ ///
+ /// Looks up a localized string similar to Use second color.
+ ///
+ public static string DevicePage_UseSecondColor {
+ get {
+ return ResourceManager.GetString("DevicePage_UseSecondColor", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Your device must be restarted in order for the changes to take effect. Would you like to restart now?.
///
@@ -2709,7 +2718,7 @@ public static string Enum_ProController_ButtonFlags_Start {
}
///
- /// Looks up a localized string similar to This is your default controller profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled..
+ /// Looks up a localized string similar to This is your default profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled..
///
public static string Enum_ProfileErrorCode_Default {
get {
@@ -3024,7 +3033,7 @@ public static string Enum_XInputController_ButtonFlags_DPadLeft {
}
///
- /// Looks up a localized string similar to PPad Right.
+ /// Looks up a localized string similar to DPad Right.
///
public static string Enum_XInputController_ButtonFlags_DPadRight {
get {
@@ -3267,106 +3276,79 @@ public static string Enum_XInputController_ButtonFlags_Start {
}
///
- /// Looks up a localized string similar to Core isolation features are turned on.
- ///
- public static string Hint_CoreIsolationCheck {
- get {
- return ResourceManager.GetString("Hint_CoreIsolationCheck", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Disable Core isolation.
- ///
- public static string Hint_CoreIsolationCheckAction {
- get {
- return ResourceManager.GetString("Hint_CoreIsolationCheckAction", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Your system core isolation features are turned on, therefore TDP read/write and fan control might be disabled.
- ///
- public static string Hint_CoreIsolationCheckDesc {
- get {
- return ResourceManager.GetString("Hint_CoreIsolationCheckDesc", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to You might want to turn off core isolation and restart your system to enable TDP manipulations.
+ /// Looks up a localized string similar to Integer scaling is not available.
///
- public static string Hint_CoreIsolationCheckReadme {
+ public static string Hint_AMD_IntegerScalingCheck {
get {
- return ResourceManager.GetString("Hint_CoreIsolationCheckReadme", resourceCulture);
+ return ResourceManager.GetString("Hint_AMD_IntegerScalingCheck", resourceCulture);
}
}
///
- /// Looks up a localized string similar to HWiNFO Shared Memory limit was reached.
+ /// Looks up a localized string similar to Deploy integer scaling.
///
- public static string Hint_HWiNFO12hLimitPassed {
+ public static string Hint_AMD_IntegerScalingCheckAction {
get {
- return ResourceManager.GetString("Hint_HWiNFO12hLimitPassed", resourceCulture);
+ return ResourceManager.GetString("Hint_AMD_IntegerScalingCheckAction", resourceCulture);
}
}
///
- /// Looks up a localized string similar to HWiNFO has reached its shared memory time limit and disabled the shared memory support. This may result in missing or outdated sensor readings.
+ /// Looks up a localized string similar to Integer scaling feature is not installed, therefore you won't be able to enable or disable it.
///
- public static string Hint_HWiNFO12hLimitPassedDesc {
+ public static string Hint_AMD_IntegerScalingCheckDesc {
get {
- return ResourceManager.GetString("Hint_HWiNFO12hLimitPassedDesc", resourceCulture);
+ return ResourceManager.GetString("Hint_AMD_IntegerScalingCheckDesc", resourceCulture);
}
}
///
- /// Looks up a localized string similar to You should manually re-activate the shared memory time limit in the HWiNFO settings.
+ /// Looks up a localized string similar to We need to execute some script to deploy the integer scaling on your system.
///
- public static string Hint_HWiNFO12hLimitPassedReadme {
+ public static string Hint_AMD_IntegerScalingCheckReadme {
get {
- return ResourceManager.GetString("Hint_HWiNFO12hLimitPassedReadme", resourceCulture);
+ return ResourceManager.GetString("Hint_AMD_IntegerScalingCheckReadme", resourceCulture);
}
}
///
- /// Looks up a localized string similar to LSDaemon is active.
+ /// Looks up a localized string similar to Core isolation features are turned on.
///
- public static string Hint_LegionGoDaemon {
+ public static string Hint_CoreIsolationCheck {
get {
- return ResourceManager.GetString("Hint_LegionGoDaemon", resourceCulture);
+ return ResourceManager.GetString("Hint_CoreIsolationCheck", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Quit LSDaemon.
+ /// Looks up a localized string similar to Disable Core isolation.
///
- public static string Hint_LegionGoDaemonAction {
+ public static string Hint_CoreIsolationCheckAction {
get {
- return ResourceManager.GetString("Hint_LegionGoDaemonAction", resourceCulture);
+ return ResourceManager.GetString("Hint_CoreIsolationCheckAction", resourceCulture);
}
}
///
- /// Looks up a localized string similar to LSDaemon is already active on your console. This may cause compatibility issues with the application.
+ /// Looks up a localized string similar to Your system core isolation features are turned on, therefore TDP read/write and fan control might be disabled.
///
- public static string Hint_LegionGoDaemonDesc {
+ public static string Hint_CoreIsolationCheckDesc {
get {
- return ResourceManager.GetString("Hint_LegionGoDaemonDesc", resourceCulture);
+ return ResourceManager.GetString("Hint_CoreIsolationCheckDesc", resourceCulture);
}
}
///
- /// Looks up a localized string similar to You should quit LSDaemon, so that the application can run properly and without any errors.
+ /// Looks up a localized string similar to You might want to turn off core isolation and restart your system to enable TDP manipulations.
///
- public static string Hint_LegionGoDaemonReadme {
+ public static string Hint_CoreIsolationCheckReadme {
get {
- return ResourceManager.GetString("Hint_LegionGoDaemonReadme", resourceCulture);
+ return ResourceManager.GetString("Hint_CoreIsolationCheckReadme", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Legion Space Daemon is active.
+ /// Looks up a localized string similar to Legion Space Tasks and Services are active.
///
public static string Hint_LegionGoServices {
get {
@@ -3375,7 +3357,7 @@ public static string Hint_LegionGoServices {
}
///
- /// Looks up a localized string similar to Disable Legion Space Daemon.
+ /// Looks up a localized string similar to Disable Legion Space.
///
public static string Hint_LegionGoServicesAction {
get {
@@ -3384,7 +3366,7 @@ public static string Hint_LegionGoServicesAction {
}
///
- /// Looks up a localized string similar to Legion Space Daemon is already active on your console. This may cause compatibility issues with the application..
+ /// Looks up a localized string similar to Legion Space Tasks and Services are already active on your console. This may cause compatibility issues with the application..
///
public static string Hint_LegionGoServicesDesc {
get {
@@ -3393,7 +3375,7 @@ public static string Hint_LegionGoServicesDesc {
}
///
- /// Looks up a localized string similar to You should disable Legion Space Daemon, so that the application can run properly and without any errors.
+ /// Looks up a localized string similar to You should disable Legion Space Tasks and Services, so that the application can run properly and without any errors.
///
public static string Hint_LegionGoServicesReadme {
get {
@@ -3663,6 +3645,24 @@ public static string InputsHotkey_increaseVolumeDesc {
}
}
+ ///
+ /// Looks up a localized string similar to Select next sub profile.
+ ///
+ public static string InputsHotkey_nextSubProfile {
+ get {
+ return ResourceManager.GetString("InputsHotkey_nextSubProfile", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Apply next sub profile for the current game.
+ ///
+ public static string InputsHotkey_nextSubProfileDesc {
+ get {
+ return ResourceManager.GetString("InputsHotkey_nextSubProfileDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to On-screen display.
///
@@ -3681,6 +3681,24 @@ public static string InputsHotkey_OnScreenDisplayDesc {
}
}
+ ///
+ /// Looks up a localized string similar to On Screen Overlay.
+ ///
+ public static string InputsHotkey_OnScreenDisplayToggle {
+ get {
+ return ResourceManager.GetString("InputsHotkey_OnScreenDisplayToggle", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Toggle on screen overlay.
+ ///
+ public static string InputsHotkey_OnScreenDisplayToggleDesc {
+ get {
+ return ResourceManager.GetString("InputsHotkey_OnScreenDisplayToggleDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Display 3D controller.
///
@@ -3717,6 +3735,24 @@ public static string InputsHotkey_overlayTrackpadsDesc {
}
}
+ ///
+ /// Looks up a localized string similar to Select previous sub profile.
+ ///
+ public static string InputsHotkey_previousSubProfile {
+ get {
+ return ResourceManager.GetString("InputsHotkey_previousSubProfile", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Apply previous sub profile for the current game.
+ ///
+ public static string InputsHotkey_previousSubProfileDesc {
+ get {
+ return ResourceManager.GetString("InputsHotkey_previousSubProfileDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Summon quick tools window.
///
@@ -4537,7 +4573,7 @@ public static string OverlayPage_CameraAnglePitch {
}
///
- /// Looks up a localized string similar to Change the angle, in degree.
+ /// Looks up a localized string similar to Change the angle.
///
public static string OverlayPage_CameraAnglePitchDesc {
get {
@@ -4986,6 +5022,60 @@ public static string PowerProfileDefaultName {
}
}
+ ///
+ /// Looks up a localized string similar to Preset similar to Balanced Mode in LS. TDP Limit: 15W.
+ ///
+ public static string PowerProfileLegionGoBalancedDescription {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoBalancedDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Legion Go - Balanced.
+ ///
+ public static string PowerProfileLegionGoBalancedName {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoBalancedName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Preset similar to Performance Mode in LS. TDP Limit: 20W.
+ ///
+ public static string PowerProfileLegionGoPerformanceDescription {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoPerformanceDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Legion Go - Performance.
+ ///
+ public static string PowerProfileLegionGoPerformanceName {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoPerformanceName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Preset similar to Quiet Mode in LS. TDP Limit: 8W.
+ ///
+ public static string PowerProfileLegionGoQuietDescription {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoQuietDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Legion Go - Quiet.
+ ///
+ public static string PowerProfileLegionGoQuietName {
+ get {
+ return ResourceManager.GetString("PowerProfileLegionGoQuietName", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to User-defined power and fan speed..
///
@@ -5007,54 +5097,90 @@ public static string PowerProfileManualName {
///
/// Looks up a localized string similar to Balances performance, temperature and acoustic for any scenario..
///
- public static string PowerProfilePerformanceDescription {
+ public static string PowerProfileROGAllyPerformanceDescription {
get {
- return ResourceManager.GetString("PowerProfilePerformanceDescription", resourceCulture);
+ return ResourceManager.GetString("PowerProfileROGAllyPerformanceDescription", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Performance.
+ /// Looks up a localized string similar to ROG Ally - Performance.
///
- public static string PowerProfilePerformanceName {
+ public static string PowerProfileROGAllyPerformanceName {
get {
- return ResourceManager.GetString("PowerProfilePerformanceName", resourceCulture);
+ return ResourceManager.GetString("PowerProfileROGAllyPerformanceName", resourceCulture);
}
}
///
/// Looks up a localized string similar to Limits CPU and GPU power, but keeps noise levels quiet..
///
- public static string PowerProfileSilentDescription {
+ public static string PowerProfileROGAllySilentDescription {
get {
- return ResourceManager.GetString("PowerProfileSilentDescription", resourceCulture);
+ return ResourceManager.GetString("PowerProfileROGAllySilentDescription", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Silent.
+ /// Looks up a localized string similar to ROG Ally - Silent.
///
- public static string PowerProfileSilentName {
+ public static string PowerProfileROGAllySilentName {
get {
- return ResourceManager.GetString("PowerProfileSilentName", resourceCulture);
+ return ResourceManager.GetString("PowerProfileROGAllySilentName", resourceCulture);
}
}
///
/// Looks up a localized string similar to Maximizes power to the CPU and GPU for high-performance gaming and work, with maximum airflow from fans..
///
- public static string PowerProfileTurboDescription {
+ public static string PowerProfileROGAllyTurboDescription {
+ get {
+ return ResourceManager.GetString("PowerProfileROGAllyTurboDescription", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to ROG Ally - Turbo.
+ ///
+ public static string PowerProfileROGAllyTurboName {
+ get {
+ return ResourceManager.GetString("PowerProfileROGAllyTurboName", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Device presets.
+ ///
+ public static string PowerProfilesPage_DevicePresets {
+ get {
+ return ResourceManager.GetString("PowerProfilesPage_DevicePresets", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Preset selection.
+ ///
+ public static string PowerProfilesPage_PresetSelection {
+ get {
+ return ResourceManager.GetString("PowerProfilesPage_PresetSelection", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Select the preset you would like to edit.
+ ///
+ public static string PowerProfilesPage_PresetSelectionDesc {
get {
- return ResourceManager.GetString("PowerProfileTurboDescription", resourceCulture);
+ return ResourceManager.GetString("PowerProfilesPage_PresetSelectionDesc", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Turbo.
+ /// Looks up a localized string similar to User presets.
///
- public static string PowerProfileTurboName {
+ public static string PowerProfilesPage_UserPresets {
get {
- return ResourceManager.GetString("PowerProfileTurboName", resourceCulture);
+ return ResourceManager.GetString("PowerProfilesPage_UserPresets", resourceCulture);
}
}
@@ -5311,7 +5437,7 @@ public static string ProfilesPage_CreateNewProfile {
}
///
- /// Looks up a localized string similar to Create a new power profile.
+ /// Looks up a localized string similar to Create a new power preset.
///
public static string ProfilesPage_CreatePowerProfile {
get {
@@ -5320,7 +5446,7 @@ public static string ProfilesPage_CreatePowerProfile {
}
///
- /// Looks up a localized string similar to Create power profile.
+ /// Looks up a localized string similar to Create power preset.
///
public static string ProfilesPage_CreatePowerProfileButton {
get {
@@ -5328,6 +5454,24 @@ public static string ProfilesPage_CreatePowerProfileButton {
}
}
+ ///
+ /// Looks up a localized string similar to This is a default device preset and cannot be edited. These are comparable to the presets provided by the devices original software..
+ ///
+ public static string ProfilesPage_DefaultDeviceProfile {
+ get {
+ return ResourceManager.GetString("ProfilesPage_DefaultDeviceProfile", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to This is the default preset, you cannot modify the fan curve on this preset..
+ ///
+ public static string ProfilesPage_DefaultProfile {
+ get {
+ return ResourceManager.GetString("ProfilesPage_DefaultProfile", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Delete.
///
@@ -5338,7 +5482,7 @@ public static string ProfilesPage_Delete {
}
///
- /// Looks up a localized string similar to Delete power profile.
+ /// Looks up a localized string similar to Delete power preset.
///
public static string ProfilesPage_DeletePowerProfileButton {
get {
@@ -5526,6 +5670,42 @@ public static string ProfilesPage_GPUMhzDesc {
}
}
+ ///
+ /// Looks up a localized string similar to GPU Scaling.
+ ///
+ public static string ProfilesPage_GPUScaling {
+ get {
+ return ResourceManager.GetString("ProfilesPage_GPUScaling", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to GPU will scale up lower resolutions to fit the display.
+ ///
+ public static string ProfilesPage_GPUScalingDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_GPUScalingDesc", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Graphics settings.
+ ///
+ public static string ProfilesPage_GraphicsSettings {
+ get {
+ return ResourceManager.GetString("ProfilesPage_GraphicsSettings", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Change the graphics settings.
+ ///
+ public static string ProfilesPage_GraphicsSettingsDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_GraphicsSettingsDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Gyrometer multiplier.
///
@@ -5562,6 +5742,24 @@ public static string ProfilesPage_GyroSteeringAxisDesc {
}
}
+ ///
+ /// Looks up a localized string similar to Radeon Image Sharpening.
+ ///
+ public static string ProfilesPage_ImageSharpening {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ImageSharpening", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Enhances visual detail.
+ ///
+ public static string ProfilesPage_ImageSharpeningDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ImageSharpeningDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Invert horizontal axis.
///
@@ -5580,6 +5778,24 @@ public static string ProfilesPage_InvertVerticalAxis {
}
}
+ ///
+ /// Looks up a localized string similar to Integer scaling.
+ ///
+ public static string ProfilesPage_IS {
+ get {
+ return ResourceManager.GetString("ProfilesPage_IS", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Scales up resolution by multiplying each pixel by an integer.
+ ///
+ public static string ProfilesPage_ISDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ISDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Joystick deadzone % left.
///
@@ -5626,7 +5842,7 @@ public static string ProfilesPage_MotionControlSettings {
}
///
- /// Looks up a localized string similar to Change the global motion control settings.
+ /// Looks up a localized string similar to Change the motion control settings.
///
public static string ProfilesPage_MotionControlSettingsDesc {
get {
@@ -5653,20 +5869,29 @@ public static string ProfilesPage_PowerLimitTarget {
}
///
- /// Looks up a localized string similar to Power settings.
+ /// Looks up a localized string similar to Power preset.
///
- public static string ProfilesPage_PowerSettings {
+ public static string ProfilesPage_PowerPreset {
get {
- return ResourceManager.GetString("ProfilesPage_PowerSettings", resourceCulture);
+ return ResourceManager.GetString("ProfilesPage_PowerPreset", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Change the selected power preset.
+ ///
+ public static string ProfilesPage_PowerPresetDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_PowerPresetDesc", resourceCulture);
}
}
///
- /// Looks up a localized string similar to Change the power settings.
+ /// Looks up a localized string similar to Power settings.
///
- public static string ProfilesPage_PowerSettingsDesc {
+ public static string ProfilesPage_PowerSettings {
get {
- return ResourceManager.GetString("ProfilesPage_PowerSettingsDesc", resourceCulture);
+ return ResourceManager.GetString("ProfilesPage_PowerSettings", resourceCulture);
}
}
@@ -5751,6 +5976,24 @@ public static string ProfilesPage_ProfileUpdated2 {
}
}
+ ///
+ /// Looks up a localized string similar to Resolution scale.
+ ///
+ public static string ProfilesPage_ResolutionScale {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ResolutionScale", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Resolution scale to which integer scaling will apply.
+ ///
+ public static string ProfilesPage_ResolutionScaleDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ResolutionScaleDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Roll.
///
@@ -5760,6 +6003,69 @@ public static string ProfilesPage_Roll {
}
}
+ ///
+ /// Looks up a localized string similar to Radeon Super Resolution.
+ ///
+ public static string ProfilesPage_RSR {
+ get {
+ return ResourceManager.GetString("ProfilesPage_RSR", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to In-driver-based upscaling feature for faster framerates.
+ ///
+ public static string ProfilesPage_RSRDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_RSRDesc", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Scaling mode.
+ ///
+ public static string ProfilesPage_ScalingMode {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ScalingMode", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Center.
+ ///
+ public static string ProfilesPage_ScalingMode_Center {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ScalingMode_Center", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Full panel.
+ ///
+ public static string ProfilesPage_ScalingMode_FullPanel {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ScalingMode_FullPanel", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Preserve aspect ratio.
+ ///
+ public static string ProfilesPage_ScalingMode_PreserveAspectRatio {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ScalingMode_PreserveAspectRatio", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Choose the method used to stretch and position images to fir the display.
+ ///
+ public static string ProfilesPage_ScalingModeDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_ScalingModeDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to X.
///
@@ -5778,6 +6084,15 @@ public static string ProfilesPage_SensitivityY {
}
}
+ ///
+ /// Looks up a localized string similar to Sharpen effect.
+ ///
+ public static string ProfilesPage_Sharpen {
+ get {
+ return ResourceManager.GetString("ProfilesPage_Sharpen", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Style of input.
///
@@ -5814,6 +6129,24 @@ public static string ProfilesPage_StyleofOutputTooltip {
}
}
+ ///
+ /// Looks up a localized string similar to Sub Profiles.
+ ///
+ public static string ProfilesPage_SubProfiles {
+ get {
+ return ResourceManager.GetString("ProfilesPage_SubProfiles", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Add different profiles to the same game.
+ ///
+ public static string ProfilesPage_SubProfilesDesc {
+ get {
+ return ResourceManager.GetString("ProfilesPage_SubProfilesDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Sustained power limit.
///
@@ -5968,9 +6301,9 @@ public static string ProfilesPage_UMCMotionOnOff {
}
///
- /// Looks up a localized string similar to With motion input disabled, hold selected button(s) to enable motion,
- ///with motion input enabled, hold selected button(s) to disable motion,
- ///with motion input toggle, press selected button(s) to switch from enabled to disabled and viceversa..
+ /// Looks up a localized string similar to Motion input disabled: hold selected button(s) to enable motion.
+ ///Motion input enabled: hold selected button(s) to disable motion.
+ ///Motion input toggle: press selected button(s) to switch motion state..
///
public static string ProfilesPage_UMCMotionOnOffDesc {
get {
@@ -6140,6 +6473,24 @@ public static string QuickHomePage_Title {
}
}
+ ///
+ /// Looks up a localized string similar to Manage on-screen overlay.
+ ///
+ public static string QuickOverlayPage_Desc {
+ get {
+ return ResourceManager.GetString("QuickOverlayPage_Desc", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Overlay.
+ ///
+ public static string QuickOverlayPage_Title {
+ get {
+ return ResourceManager.GetString("QuickOverlayPage_Title", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to FPS.
///
@@ -6410,6 +6761,15 @@ public static string QuickProfilesPage_PowerLimitTarget {
}
}
+ ///
+ /// Looks up a localized string similar to Select a sub profile to apply.
+ ///
+ public static string QuickProfilesPage_SubProfilesDesc {
+ get {
+ return ResourceManager.GetString("QuickProfilesPage_SubProfilesDesc", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Profiles.
///
@@ -6429,7 +6789,7 @@ public static string QuickProfilesPage_Waiting {
}
///
- /// Looks up a localized string similar to Preferred actions, device settings.
+ /// Looks up a localized string similar to Preferred actions.
///
public static string QuickSettingsPage_Desc {
get {
@@ -6473,6 +6833,24 @@ public static string QuickSettingsPage_DisplayResolutionDesc {
}
}
+ ///
+ /// Looks up a localized string similar to Resolution is currently overridden by profile.
+ ///
+ public static string QuickSettingsPage_ResolutionOverrideWarning {
+ get {
+ return ResourceManager.GetString("QuickSettingsPage_ResolutionOverrideWarning", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 1/1 only supports Exclusive Fullscreen..
+ ///
+ public static string QuickSettingsPage_ResScaleExclusiveFullscreen {
+ get {
+ return ResourceManager.GetString("QuickSettingsPage_ResScaleExclusiveFullscreen", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Actions.
///
@@ -6771,7 +7149,7 @@ public static string SettingsMode1_Deadzone {
}
///
- /// Looks up a localized string similar to Change the steering deadzone, in degree. Improves steering straight.
+ /// Looks up a localized string similar to Change the steering deadzone. Improves steering straight.
///
public static string SettingsMode1_DeadzoneDesc {
get {
@@ -6825,7 +7203,7 @@ public static string SettingsMode1_MaxSteeringAngle {
}
///
- /// Looks up a localized string similar to Change the maximum steering angle value, in degree.
+ /// Looks up a localized string similar to Change the maximum steering angle value.
///
public static string SettingsMode1_MaxSteeringAngleDesc {
get {
@@ -7121,24 +7499,6 @@ public static string SettingsPage_HideWhenLoseFocusDesc {
}
}
- ///
- /// Looks up a localized string similar to HWiNFO.
- ///
- public static string SettingsPage_HwInfo {
- get {
- return ResourceManager.GetString("SettingsPage_HwInfo", resourceCulture);
- }
- }
-
- ///
- /// Looks up a localized string similar to Automatically turn HWiNFO off when companion is closed.
- ///
- public static string SettingsPage_HwInfoDesc {
- get {
- return ResourceManager.GetString("SettingsPage_HwInfoDesc", resourceCulture);
- }
- }
-
///
/// Looks up a localized string similar to Install now.
///
@@ -7274,6 +7634,24 @@ public static string SettingsPage_QuickToolsWindowLocationDesc {
}
}
+ ///
+ /// Looks up a localized string similar to Left.
+ ///
+ public static string SettingsPage_QuickToolsWindowLocationLeft {
+ get {
+ return ResourceManager.GetString("SettingsPage_QuickToolsWindowLocationLeft", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to Right.
+ ///
+ public static string SettingsPage_QuickToolsWindowLocationRight {
+ get {
+ return ResourceManager.GetString("SettingsPage_QuickToolsWindowLocationRight", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Top left.
///
diff --git a/HandheldCompanion/Properties/Resources.de-DE.resx b/HandheldCompanion/Properties/Resources.de-DE.resx
index 141f662a7..968301477 100644
--- a/HandheldCompanion/Properties/Resources.de-DE.resx
+++ b/HandheldCompanion/Properties/Resources.de-DE.resx
@@ -1,2361 +1,2355 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Über
-
-
- Eine Kombination aus einem Windows-Dienst und einer für das Touch-Overlay optimierten GUI, um Ihr Handheld-Gaming-Computer-Erlebnis zu verbessern. Zu den Funktionen gehören: Bewegungssteuerung (Gyrometer), virtuelle Controller-Simulation, Quick-Tools-Overlay, virtuelle Touchpads, 3D-Controller-Modell, anwendungsbasiertes Profileinstellungssystem. Handheld Companion basiert auf dem ViGEmBus-Treiber und den ViGEmClient-Bibliotheken sowie dem HidHide-Filtertreiber für den Kernel-Modus. Die Algorithmen zur Bewegungssteuerung basieren auf der Arbeit von Jibbsmart und den verfügbaren Informationen im GyroWiki.
-
-
- Autor
-
-
- Mitwirkende
-
-
- Beschreibung
-
-
- Spenden
-
-
- Gyrometer
-
-
- Neigungssensor
-
-
- N/A
-
-
- Weitere Links
-
-
- Extern
-
-
- Intern
-
-
- Sensor-Name
-
-
- Sensor-Spezifikation
-
-
- Service
-
-
- Quellcode
-
-
- Version
-
-
- Wiki
-
-
- Administrator
-
-
- Verbundene Controller verstecken
-
-
- Änderung der Sichtbarkeit des physischen Controllers für andere Anwendungen
-
-
- Verbinden
-
-
- Controller
-
-
- Controller verstecken
-
-
- Controller-Einstellungen
-
-
- Getrennt
-
-
- Eingabegeräte
-
-
- Controller beim Schließen anzeigen
-
-
- Wiederherstellung der Sichtbarkeit aller physischen Steuerungen für andere Anwendungen bei Beendigung des Dienstes
-
-
- Vibrations-Intensität
-
-
- Vibrationsstärke des Controllers ändern
-
-
-
- ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- Thermische Leistungsbregrenzung (TDP) verringern
-
-
- TDP um einen Watt senken
-
-
- Drücken, um die Hotkey-Eingabe zu definieren
-
-
- Drücken, um die Hotkey-Ausgabe zu definieren
-
-
- Thermische Leistungsgrenze (TDP) erhöhen
-
-
- Erhöhen Sie den TDP des Systems oder des aktuell verwendeten Profils um ein Watt
-
-
- 3D-Controller anzeigen
-
-
- Ändern des 3D-Hotkeys durch Drücken eines Hotkeys oder einer speziellen Taste
-
-
- Virtuelle Trackpads anzeigen
-
-
- Hotkey durch Drücken eines Buttons oder einer speziellen Taste ändern
-
-
- Fenster für QuickTools aufrufen
-
-
- Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
-
-
- Benutzerdefinierte Verknüpfung
-
-
- Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
-
-
- Desktop anzeigen und ausblenden
-
-
- Drücke diese Tasten: Windows + D
-
-
- Escape
-
-
- Drücke diese Tasten: Escape
-
-
- Zwischen Fenster und Vollbild wechseln
-
-
- Drücke diese Tasten: Alt + Enter
-
-
- XBOX- oder PS-Taste
-
-
- XBOX- oder PS-Taste simulieren
-
-
- Bildschirmtastatur anzeigen
-
-
- Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
-
-
- Beenden der Anwendung erzwingen
-
-
- Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
-
-
- Hauptfenster anzeigen und ausblenden
-
-
- Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
-
-
- Task-Manager öffnen
-
-
- Drücke diese Tasten: Strg + Shift + Esc
-
-
- Aufgabenansicht öffnen
-
-
- Drücke diese Tasten: Windows + Tab
-
-
- Suspendierung schalten
-
-
- Unterbrechen oder Fortsetzen der Vordergrundanwendung
-
-
- Handheld Companion
-
-
- Über
-
-
- Controller
-
-
- Overlay
-
-
- Profile
-
-
- OK
-
-
- Einstellungen
-
-
- 8BitDo Lite 2
-
-
- Ausrichtung
-
-
- Ausrichtung des 3D-Controller-Overlays ändern
-
-
- Trackpad-Overlay-Ausrichtung ändern
-
-
- Immer ganz oben
-
-
- Wenn umgeschaltet, bleibt das 3D-Controller-Overlay über anderen Fenstern.
-
-
- Zurück
-
-
- Kamera-Ausrichtung
-
-
- Ändern Sie das Verhalten des 3D-Controller-Overlay-Modells für die Ausrichtung der Kamera
-
-
- Statische Kameraneigung
-
-
- Ändern Sie den Winkel, in Grad
-
-
- Hintergrundfarbe
-
-
- Hintergrundfarbe des 3D-Controller-Overlays ändern
-
-
- Controller-Optionen
-
-
- PlayStation DualSense
-
-
- Emulierter Controller
-
-
- Kamera-Ausrichtung
-
-
- 3D-Modell dreht sich langsam in Richtung Kamera als Standardposition
-
-
- Warten...
-
-
- MACHENIKE HG510
-
-
- Hauptschalter
-
-
- 3D-Controller-Overlay-Hauptschalter ändern
-
-
- Bewegung
-
-
- Das Modell bewegt sich entsprechend den Bewegungen des Benutzers auf der Grundlage von Sensorinformationen
-
-
- N64
-
-
- OEM-Controller
-
-
- Deckkraft
-
-
- Deckkraft der 3D-Controller-Überlagerung ändern
-
-
- Trackpad-Overlay-Transparent ändern
-
-
- Overlay
-
-
- Overlay-Modell
-
-
- 3D-Overlay-Modell ändern
-
-
- Overlay-Vorschau
-
-
- Render-Einstellungen
-
-
- Anti-Aliasing
-
-
- Ändern des Rendering-Anti-Aliasing-Status
-
-
- Ändern Sie die Rendereinstellungen Ihres stationären 3D-Overlay-Controller-Modells
-
-
- Aktualisierungsrate
-
-
- Ändern Sie die Render-Update-Rate, in Update pro Sekunde
-
-
- Größe
-
-
- Größe des 3D-Controller-Overlays ändern
-
-
- Trackpad-Overlay-Größe ändern
-
-
- Start
-
-
- Fisher-Price Controller
-
-
- Optionen für Trackpads
-
-
- Xbox One
-
-
- ZD O+
-
-
- Overlay
-
-
- Fortsetzen
-
-
- Pausieren
-
-
- Beschleunigungssensor-Multiplikator
-
-
- Ändern Sie den vom System gemeldeten Beschleunigungssensorwert
-
-
- Zusätzliche Einstellungen
-
-
- Anti-Deadzone
-
-
- Ändern Sie die Anti-Deadzone im Spiel, in Prozent
-
-
- %
-
-
- Sind Sie sicher, dass Sie dies löschen wollen?
-
-
- Dieses Element wird sofort gelöscht. Sie können diese Aktion nicht rückgängig machen.
-
-
- Sind Sie sicher, dass Sie das Profil überschreiben wollen?
-
-
- {0} wird überschrieben. Sie können diese Aktion nicht rückgängig machen.
-
-
- Schub-Begrenzung
-
-
- Ändere TDP-Boost-Begrenzung
-
-
- Abbrechen
-
-
- Neues Profil erstellen
-
-
- Löschen
-
-
- Profil löschen
-
-
- Profil aktivieren
-
-
- Das Profil wird automatisch angewendet, wenn die zugehörige Anwendung erkannt wird.
-
-
- Globale Einstellungen
-
-
- Ändern Sie die globalen Profileinstellungen
-
-
- Gyrometer-Multiplikator
-
-
- Ändern Sie den vom System gemeldeten Gyrometerwert
-
-
- Gyro-Lenkachse
-
-
- Zur Steuerung der horizontalen Bewegung des Controllers können Sie entweder die Gier- oder die Rollachse verwenden
-
-
- Horizontale Achse invertieren
-
-
- Vertikale Achse invertieren
-
-
- Einstellungen der Bewegungssteuerung
-
-
- Ändern Sie die globalen Bewegungssteuerungseinstellungen
-
-
- OK
-
-
- Energie-Einstellungen
-
-
- Ändern Sie die Energieeinstellungen
-
-
- Profil-Details
-
-
- Profilname
-
-
- Profilpfad
-
-
- Profile
-
-
- Profilauswahl
-
-
- Wählen Sie das Profil, das Sie bearbeiten möchten
-
-
- Profileinstellungen
-
-
- Profil aktualisieren
-
-
- wurden aktualisiert.
-
-
- Roll
-
-
- X
-
-
- Y
-
-
- Eingabeart
-
-
- Die physikalischen Controllereingaben können so programmiert werden, dass sie sich wie verschiedene Gerätetypen verhalten
-
-
- Ausgabegerät
-
-
- Wählen Sie das Gerät, das die Bewegungsbefehle empfangen soll
-
-
- Anhaltende Leistungsgrenze
-
-
- Änderung der Dauerwärmeleistungsgrenze
-
-
- Thermische Leistung (TDP) überschreiben
-
-
- Überschreiben Sie das thermal power limit des Prozessors
-
-
- Aktivieren der universellen Bewegungssteuerung
-
-
- Deaktiviert, einschalten mit Taste(n)
-
-
- Aktiviert, ausschalten mit Taste(n)
-
-
- Bewegungsaktivierung
-
-
- Wenn die Bewegungseingabe deaktiviert ist, verwenden Sie die ausgewählte(n) Taste(n), um die Bewegung zu aktivieren,
-Wenn die Bewegungseingabe aktiviert ist, verwenden Sie die ausgewählte(n) Taste(n), um die Bewegung zu deaktivieren.
-
-
- Wählen Sie das Gerät, das die Bewegungsbefehle empfangen soll
-
-
- Universelle Einstellungen für die Bewegungssteuerung
-
-
- Übersetzen von Gerätebewegungen in Controllereingaben
-
-
- Profil aktualisieren
-
-
- Der Anwendung den Zugriff auf den physischen Controller des Geräts ermöglichen
-
-
- Erweiterte Kompatibilität (XInputPlus)
-
-
- Gier
-
-
- Ja
-
-
- Manuelle GPU-Takteinstellungen
-
-
- Setzt die GPU auf einen festen Takt
-
-
- MHz
-
-
- Leistungsmodus
-
-
- Ausgeglichen
-
-
- Optimieren Sie Ihr Gerät auf der Grundlage von Stromverbrauch und Leistung
-
-
- Effizienz
-
-
- Leistung
-
-
- Schub
-
-
- Thermische Leistungsgrenze (TDP)
-
-
- Begrenze Prozessorleistung für weniger Gesamtleistung
-
-
- Thermal Power Limit wird von einem Profil überschrieben
-
-
- Anhaltend
-
-
- W
-
-
- Profil erstellen
-
-
- Bietet Gyroskop- und Beschleunigungssensor-Unterstützung für Windows-Handheld-Gamingcomputer über einen virtuellen Controller. Wenn der Dienst aktiviert ist, wird der eingebettete Controller für Anwendungen außerhalb der Whitelist getarnt. Wenn der Dienst deaktiviert ist, wird der eingebettete Controller enttarnt und der virtuelle Controller deaktiviert.
-
-
- Controller-Service
-
-
- Sprache
-
-
- Die Anwendungssprache
-
-
- Neustart erforderlich
-
-
- Damit die Änderungen wirksam werden, starten Sie bitte die Anwendung neu
-
-
- Anwendungs-Theme
-
-
- Das Anwednungs-Theme, light oder dark mode
-
-
- Anwendung mit Windows starten
-
-
- Die Anwendung wird automatisch gestartet, wenn ich mich bei Windows anmelde
-
-
- Acrylhintergrund verwenden
-
-
- Acryl
-
-
- Für die Anwendung wird ein Acrylhintergrund verwendet
-
-
- Glimmer
-
-
- Keine
-
-
- Tabbed
-
-
- Nach Updates suchen
-
-
- Minimiert schließen
-
-
- Die Anwendung wird minimiert und nicht geschlossen
-
-
- Download
-
-
- Downloaden -
-
-
- EcoQoS
-
-
- Inaktive oder im Hintergrund ablaufende Prozesse und Anwendungen drosseln, um die Energieeffizienz zu verbessern
-
-
- Allgemeine Optionen
-
-
- Jetzt installieren
-
-
- Zuletzt geprüft:
-
-
- Optionen für Benachrichtigungen
-
-
- Anwendung im Hintergrund öffnen
-
-
- Die Anwendung wird minimiert gestartet und erscheint in der Taskleiste
-
-
- Extern
-
-
- Intern
-
-
- Sensor-Optionen
-
-
- Externer Sensor-Ausrichtung
-
-
- Wählen Sie aus, auf welcher Seite des Geräts der Sensor montiert wurde
-
-
- Externer Sensor kopfüber
-
-
- Der Sensor wurde verkehrt herum montiert, möglich mit USB-C-Konvertern
-
-
- Sensorauswahl
-
-
- Wählen Sie den gewünschten Sensor für die Bewegungseingabe aus
-
-
- Einstellungen
-
-
- Starttyp
-
-
- Wird vom Dienstmanager verwendet, um den Starttyp des Dienstes zu definieren
-
-
- Maximale Leistung
-
-
- Die maximale Leistung in Watt, die dem Prozessor zugeführt wird
-
-
- Minimale Leistung
-
-
- Die Mindestleistung in Watt, die dem Prozessor zugeführt wird
-
-
- Configurable Power (cTDP) konfigurieren
-
-
- Ermöglicht die Änderung der minimalen und maximalen Leistungswerte (TDP) über die CPU-Spezifikationen hinaus
-
-
- Dunkel
-
-
- Hell
-
-
- Toast-Benachrichtigung
-
-
- Benachrichtigungen von der Anwendung im Info-Center abrufen
-
-
- Update verfügbar
-
-
- Suche nach Updates...
-
-
- Wir konnten das Update nicht downloaden.
-
-
- Wir konnten GitHub nicht erreichen
-
-
- Wir konnten die Update-Datei nicht finden
-
-
- Ups. Es gab ein Problem.
-
-
- Sie sind auf dem neusten Stand
-
-
- Dein Controller ist nun versteckt. Eingaben werden an den Virtuellen Controller weitergeleitet
-
-
- Nutzer
-
-
- Führen Sie dieses Tool als Administrator aus, um diese Einstellungen freizugeben
-
-
- ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
-
-
- Virtuellen Controller stummschalten
-
-
- Viertuellen Controller in Steam-Applikationen stummschalten
-
-
- Controller-Einstellungen
-
-
- Ändern Sie die Einstellungen der virtuellen Steuerung
-
-
- Bewegungs-Anti-Deadzone
-
-
- Kompensierung der Deadzone im Spiel, verbesserte Registrierung kleiner Bewegungen
-
-
- ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Verbessern Sie die Zirkularität des Joysticks
-
-
- Zirkularität linker Stick
-
-
- Zirkularität rechter Stick
-
-
- Joystick Deadzone % links
-
-
- Einstellen der inneren und äußeren Deadzone (Prozent) des linken Joysticks
-
-
- Joystick Deadzone % rechts
-
-
- Einstellen der inneren und äußeren Deadzone (Prozent) des rechten Joysticks
-
-
- Linke Analog-Deadzone %
-
-
- Einstellen der inneren und äußeren Deadzone (Prozent) des linken Joysticks
-
-
- Rechter Trigger Deadzone %
-
-
- Einstellen der inneren und äußeren Deadzone (Prozent) des rechten Joysticks
-
-
- Zusätzliche Einstellungen
-
-
- Multiplikator für Bewegungen beim Zielen
-
-
-
- Aktivierungstaste
-
-
- Ein zusätzlicher Multiplikator für die Bewegungsempfindlichkeit beim Anvisieren der Visierung oder des Zielfernrohrs durch die Verwendung der konfigurierten Aktivierungstaste
-
-
- Multiplikatorwert
-
-
- Kamera-Optionen
-
-
- Benutzerdefinierte Reaktionskurve
-
-
- Ausgabe an das Spiel gesendet
-
-
- Bewegungsintensität
-
-
- Aggressiv
-
-
- Standard
-
-
- Voreinstellungs-Optionen
-
-
- Präzise
-
-
- Streifendauer
-
-
- Ändern Sie die Streifendauer, kalibrieren Sie auf eine 180-Grad-Drehung, in Millisekunden
-
-
- Flick-Stick (Experimental)
-
-
- Richten Sie die Kamera in Richtung des (rechten) Joysticks, drehen Sie die Kamera rein in der horizontalen Ebene durch Drehen
-
-
- Aktiviere Flick-Stick
-
-
- Empfindlichkeit
-
-
- Ändern Sie die Bewegungsempfindlichkeit der horizontalen und vertikalen Achse
-
-
- Empfindlichkeit X
-
-
- Ändern Sie die Bewegungsempfindlichkeit der horizontalen Achse
-
-
- Empfindlichkeit Y
-
-
- Ändern Sie die Bewegungsempfindlichkeit der vertikalen Achse
-
-
- Stick-Empfindlichkeit
-
-
- Drehrate ändern
-
-
- Zusätzliche Einstellungen
-
-
- Deadzone
-
-
- Ändern Sie die Deadzone in Grad. Verbessert das Geradeauslaufen
-
-
- Joystick-Spiel Eingabe
-
-
- Joystick-Lenkung
-
-
- Joystick-Lenkung-Optionen
-
-
- Joystick-Lenkung-Vorschau
-
-
- Maximaler Lenkwinkel
-
-
- Den maximalen Lenkwinkelwert in Grad ändern
-
-
- Linearität der Lenkung
-
-
- Zuordnung zwischen Eingabe und Lenkung. Niedrigere Werte bieten mehr Genauigkeit in der Nähe des vollen Lenkausschlags, aber weniger Genauigkeit in der Nähe der Mittellage. Höhere Werte bieten mehr Genauigkeit in der Nähe der Mittellage, aber weniger Genauigkeit beim vollen Lenkausschlag. Ein Wert von 1,0 entspricht einer linearen Zuordnung.
-
-
- Hersteller
-
-
- Partner
-
-
- Produktname
-
-
- A,B,X,Y
-
-
- BACK GRIPS
-
-
- Schultertasten
-
-
- MENÜ
-
-
- OEM
-
-
- Desktop-Layout
-
-
- Desktop-Layout festlegen
-
-
- Controller-Layout im Desktop festlegen
-
-
- Bearbeiten
-
-
- Desktop-Layout aktivieren
-
-
- Non-Spiel Controller-Layouts
-
-
- Klicken Sie auf Verbinden neben Ihrem angeschlossenen Controller.
-
-
- Sie haben keinen physischen Controller angeschlossen. Es werden keine Eingaben an HC oder seinen Dienst gesendet.
-
-
- Bitte stellen Sie sicher, dass Sie ein kompatibles XInput- oder DInput-Gerät angeschlossen haben.
-
-
- Kein physischer Controller gefunden
-
-
- Kein physischer Controller gefunden
-
-
- Starten Sie den Begleitdienst oder stellen Sie sicher, dass der Status Ihrer virtuellen Steuerung auf "Verbunden" eingestellt ist.
-
-
- Ihr physischer Controller ist versteckt, aber sie haben keinen Virtuellen Controller. Keine Eingaben werden an das Spiel geschickt.
-
-
- Kein virtueller Controller gefunden
-
-
- Heben Sie die Stummschaltung Ihres virtuellen Controllers auf oder zeigen Sie Ihren physischen Controller an.
-
-
- Ihr physischer Controller ist versteckt, aber ihr Virtueller Controller ist stumm.
-
-
- Physischer Controller ist versteckt
-
-
- Verstecken Sie Ihren physischen Controller oder schalten Sie Ihren virtuellen Controller stumm.
-
-
- Ihr physischer Controller ist nicht versteckt, jedoch haben sie ihren virtuellen Controller stummgeschaltet. Es kann Doppelte Tasteneingaben geben.
-
-
- Physischer Controller ist nicht versteckt
-
-
- HD-Rumble
-
-
- Verwendung einer HD-Rumble-Engine, auf Kosten einer höheren CPU-Auslastung
-
-
- Controller Einstellungen
-
-
- Vibrieren, wenn Controller verbunden ist
-
-
- Physischen Kontroller vibrieren, wenn verbunden
-
-
- STEUERKREUZ
-
-
- Helligkeit verringern
-
-
- Systemhelligkeit um 5% verringern
-
-
- Lautstärke verringern
-
-
- Systemlautstärke um 5% verringern
-
-
- Desktop-Controllerlayout schalten
-
-
- Helligkeit erhöhen
-
-
- Erhöhe die Bildschirmhelligkeit um 5%
-
-
- Lautstärke erhöhen
-
-
- Erhöhe die Lautstärke um 5%
-
-
- Bildschirmanzeige
-
-
- Display-Unterstützung aktivieren
-
-
- Lüftersteuerung
-
-
- Einstellen des Lüfterbetriebszyklus auf einen benutzerdefinierten Wert
-
-
- Info-Center anzeigen und ausblenden
-
-
- Desktop-Layout
-
-
- Info-Center anzeigen
-
-
- Snipping-Tool öffnen
-
-
- Press this key: Windows + Shift + S
-
-
- LINKER JOYSTICK
-
-
- LINKE JOYSTICK BUTTONS
-
-
- RECHTER JOYSTICK
-
-
- RECHTE JOYSTICK BUTTONS
-
-
- Vorlage anwenden
-
-
- Tasten
-
-
- Abbrechen
-
-
- COMMUNITY
-
-
- Bestätigen
-
-
- Steuerkreuz
-
-
- Für aktuellen Controller exportieren
-
-
- Layout exportieren
-
-
- Gyro
-
-
- Joysticks
-
-
- Layout-Autor
-
-
- Layout-Beschreibung
-
-
- Layout-Titel
-
-
- Spielinformationen mit Layout speichern
-
-
- Layout-Vorlagen auswählen
-
-
- VORLAGEN
-
-
- Trackpads
-
-
- Trigger
-
-
- Hotkeys
-
-
- ms
-
-
- Overlay-Anzeigenlevel
-
-
- Deaktiviert
-
-
- Erweitert
-
-
- Komplett
-
-
- Minimal
-
-
- Verändere die Menge der Statistikwerten
-
-
- Aktualisierungsrate
-
-
- Verändere die Update-Rate der Statistikwerte
-
-
- Automatische TDP
-
-
- Automatische Anpassung des TDP auf der Grundlage der gemessenen FPS und des gewünschten FPS-Ziels
-
-
- Framerate-Ziel
-
-
- Gewünschtes FPS-Ziel für Auto-TDP-Controller
-
-
- Controller-Layout
-
-
- Ändern Sie das virtuelle Steuerungslayout
-
-
- CPU
-
-
- Bevorzugte Energieleistung (EPP)
-
-
- CPU/GPU-Leistungsbalance
-
-
- Legt die Stromverteilungsrichtlinien zwischen CPU und GPU fest
-
-
- Framerate-Limit
-
-
- Begrenzt FPS für 3D-Programme
-
-
- GPU
-
-
- Maximale GPU-Taktfrequenz
-
-
- Maximale Taktgeschwindigkeit des GPU in MHz
-
-
- Leistungsgrenze-Ziel
-
-
- Getrennt
-
-
- FPS
-
-
- Desktop-Profil beim Start aktivieren
-
-
- Das Desktop-Profil wird beim Start der Anwendung automatisch aktiviert.
-
-
- Native Display-Orientierung
-
-
- Einige Funktionen hängen davon ab, dass Sie die ursprüngliche Ausrichtung des Bildschirms kennen, damit sie richtig funktionieren. Wenn dies nicht richtig erkannt wurde, stellen Sie die Ausrichtung Ihres Bildschirms so ein, dass sie mit der Ausrichtung Ihres Controllers übereinstimmt, und klicken Sie dann auf Erkennen
-
-
- Erkennen
-
-
- Nicht belegt
-
-
- Systemeinstellung benutzen
-
-
- LINKER TRACKPAD
-
-
- LINKE TRACKPAD-TASTEN
-
-
- RECHTER TRACKPAD
-
-
- RECHTE TRACKPAD-TASTEN
-
-
- LINKE ANALOGTASTE
-
-
- LINKE ANALOGTASTE
-
-
- RECHTER TRIGGER
-
-
- RECHTE TRIGGER-TASTEN
-
-
- Leistungsgrenze-Ziel
-
-
- QuickTools-Optionen
-
-
- %
-
-
- Aktuellen CPU-Boost-Modus einstellen
-
-
- CPU-Boost-Modus
-
-
- Einstellen des Lüfterbetriebszyklus auf einen benutzerdefinierten Wert
-
-
- Lüfter-Steuerung
-
-
- Hauptdisplay-Auflösung und Bildwiederholrate anpassen
-
-
- Display-Auflösung und Bildwiederholrate
-
-
- Oben Rechts
-
-
- Oben links
-
-
- Fensterplatzierung
-
-
- Unten Rechts
-
-
- Unten Links
-
-
- Energie-Optionen
-
-
- Standort des QuickTools-Fenster festlegen
-
-
- Drittanbieter-Programme
-
-
- Keine
-
-
- QuickTools-Hintergrund, Keine, Glimmer, Tabbed, Akryl
-
-
- Automatically turn RTSS off when companion is closed
-
-
- Automatically turn HWiNFO off when companion is closed
-
-
- HWiNFO
-
-
- Standard
-
-
- Aktuelles Profil:
-
-
- RivaTuner Statistics Server
-
-
- Automatically hide quick tools when the user clicks outside of window
-
-
- Bei Fokusverlust ausblenden
-
-
- Dieser Eingang funktioniert wie ein einfacher Joystick. Ideal für Laptops und Clamshell-Handhelds, automatischer Yaw-Roll-Wechsel je nachdem, wie das Gerät gehalten wird (90 oder 180 Grad geöffnet).
-
-
- Taste A
-
-
- Immer an
-
-
- Button B
-
-
- Zurück
-
-
- Unten
-
-
- Links
-
-
- Rechts
-
-
- Hoch
-
-
- Linke Schultertaste
-
-
- Linker Stick
-
-
- Linke Analogtaste
-
-
- Rechte Schultertaste
-
-
- Rechter Stick
-
-
- Rechte Triggertaste
-
-
- Start
-
-
- X-Taste
-
-
- Y-Taste
-
-
- Emulierter DualShock 4 Controller
-
-
- Kein emulierter Controller
-
-
- Emulierter XBOX 360 Controller
-
-
- Verbunden
-
-
- Getrennt
-
-
- Auto-Roll-Gier-Swap
-
-
- Joystick-Kamera
-
-
- Joystick-Lenkung
-
-
- Player space
-
-
- Handheld Companion
-
-
- Overlay
-
-
- QuickTools
-
-
- Windows
-
-
- Linker Joystick
-
-
- Rechter Joystick
-
-
- Hoppla. Es scheint, dass dieses Profil ausgeführt wird. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
-
-
- Hoppla. Es scheint, dass dieses Profil keine ausführbare Datei hat. Wie ist das überhaupt möglich?
-
-
- Hoppla, Es scheint, dass dieses Profil keinen Pfad zu der Anwendung enthält. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
-
-
- Hoppla. Es scheint, dass Sie nicht über die erforderliche Berechtigungsstufe verfügen, um den Inhalt dieser Anwendung zu ändern. Vergewissern Sie sich, dass Sie das Programm im Administratormodus gestartet haben.
-
-
- Hier gibt es nichts zu sehen.
-
-
- Standard
-
-
- Eco
-
-
- Hoch
-
-
- Automatisch
-
-
- Deaktiviert
-
-
- Manuell
-
-
- Dieser Eingang funktioniert wie ein einfacher Joystick. Er ist für traditionelle Joystick-Anwendungen gedacht
-
-
- Dieser Eingang funktioniert wie ein Joystick, der für die Steuerung eines Lenkrads oder eines Rennspiels optimiert ist.
-
-
- Diese Eingabe funktioniert wie ein Joystick, der für die Steuerung einer First- oder Third-Person-Kamera optimiert ist
-
-
- Handheld Companion
-
-
- ≈
-
-
- ≈
-
-
- ≈
-
-
- ≈
-
-
- AYA
-
-
- AYA
-
-
- AYA
-
-
- AYA
-
-
- KB
-
-
- RC
-
-
- LC
-
-
- RC
-
-
- LC
-
-
- RC
-
-
- LC
-
-
- Win
-
-
- Esc
-
-
- RC
-
-
- LC
-
-
- Dies ist Ihr Standard-Controller-Profil. Dieses Profil wird für alle Ihre Anwendungen verwendet, die kein spezifisches Profil haben. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
-
-
- M1
-
-
- Kreuz
-
-
- Kreis
-
-
- Viereck
-
-
- Dreieck
-
-
- Teilen
-
-
- Sony
-
-
- Optionen
-
-
- Benutzerdefiniert
-
-
- Gerät
-
-
- Auto-Roll-Gier-Swap
-
-
- Joystick Camera
-
-
- Joystick Steering
-
-
- Player Space
-
-
- Linker Stick
-
-
- Rechter Stick
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- Anzeigen
-
-
- STEAM
-
-
- Menü
-
-
- Hoppla, It seems this profile excutable is running. Some options requiring an executable might be disabled.
-
-
- Command Center
-
-
- Armory Crate
-
-
- Optionen
-
-
- L2
-
-
- Linker Stick
-
-
- R2
-
-
- Rechter Stick
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- Anzeigen
-
-
- Unten
-
-
- Links
-
-
- PPad Rechts
-
-
- Hoch
-
-
- LB
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Linker Stick
-
-
- Linker Stick unten
-
-
- Linker Stick links
-
-
- Linker Stick rechts
-
-
- Linker Stick oben
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- RB
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Rechter Stick
-
-
- Rechter Stick unten
-
-
- Rechter Stick links
-
-
- Rechter Stick rechts
-
-
- Rechter Stick oben
-
-
- XBOX-Taste
-
-
- Menü
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- LeftStick
-
-
- RightStick
-
-
- Yes
-
-
- No
-
-
- Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
-
-
- Warning
-
-
- Disabled
-
-
- Injection (recommended)
-
-
- Redirection
-
-
- Improve virtual controller detection
-
-
- Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
-
-
- Yes
-
-
- No
-
-
- Your device must be restarted in order for the changes to take effect. Would you like to restart now?
-
-
- Restart required
-
-
- Yes
-
-
- No
-
-
- Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
-
-
- Warning
-
-
- S
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Accelerometer
-
-
- Back
-
-
- Exit
-
-
- Show current controller templates only
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- External
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- Waiting for foreground process...
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Über
+
+
+ Eine Kombination aus einem Windows-Dienst und einer für das Touch-Overlay optimierten GUI, um Ihr Handheld-Gaming-Computer-Erlebnis zu verbessern. Zu den Funktionen gehören: Bewegungssteuerung (Gyrometer), virtuelle Controller-Simulation, Quick-Tools-Overlay, virtuelle Touchpads, 3D-Controller-Modell, anwendungsbasiertes Profileinstellungssystem. Handheld Companion basiert auf dem ViGEmBus-Treiber und den ViGEmClient-Bibliotheken sowie dem HidHide-Filtertreiber für den Kernel-Modus. Die Algorithmen zur Bewegungssteuerung basieren auf der Arbeit von Jibbsmart und den verfügbaren Informationen im GyroWiki.
+
+
+ Autor
+
+
+ Mitwirkende
+
+
+ Beschreibung
+
+
+ Spenden
+
+
+ Gyrometer
+
+
+ Neigungssensor
+
+
+ N/A
+
+
+ Weitere Links
+
+
+ Extern
+
+
+ Intern
+
+
+ Sensor-Name
+
+
+ Sensor-Spezifikation
+
+
+ Service
+
+
+ Quellcode
+
+
+ Version
+
+
+ Wiki
+
+
+ Administrator
+
+
+ Verbundene Controller verstecken
+
+
+ Änderung der Sichtbarkeit des physischen Controllers für andere Anwendungen
+
+
+ Verbinden
+
+
+ Controller
+
+
+ Controller verstecken
+
+
+ Controller-Einstellungen
+
+
+ Getrennt
+
+
+ Eingabegeräte
+
+
+ Controller beim Schließen anzeigen
+
+
+ Wiederherstellung der Sichtbarkeit aller physischen Steuerungen für andere Anwendungen bei Beendigung des Dienstes
+
+
+ Vibrations-Intensität
+
+
+ Vibrationsstärke des Controllers ändern
+
+
+
+ ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Thermische Leistungsbregrenzung (TDP) verringern
+
+
+ TDP um einen Watt senken
+
+
+ Drücken, um die Hotkey-Eingabe zu definieren
+
+
+ Drücken, um die Hotkey-Ausgabe zu definieren
+
+
+ Thermische Leistungsgrenze (TDP) erhöhen
+
+
+ Erhöhen Sie den TDP des Systems oder des aktuell verwendeten Profils um ein Watt
+
+
+ 3D-Controller anzeigen
+
+
+ Ändern des 3D-Hotkeys durch Drücken eines Hotkeys oder einer speziellen Taste
+
+
+ Virtuelle Trackpads anzeigen
+
+
+ Hotkey durch Drücken eines Buttons oder einer speziellen Taste ändern
+
+
+ Fenster für QuickTools aufrufen
+
+
+ Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
+
+
+ Benutzerdefinierte Verknüpfung
+
+
+ Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
+
+
+ Desktop anzeigen und ausblenden
+
+
+ Drücke diese Tasten: Windows + D
+
+
+ Escape
+
+
+ Drücke diese Tasten: Escape
+
+
+ Zwischen Fenster und Vollbild wechseln
+
+
+ Drücke diese Tasten: Alt + Enter
+
+
+ XBOX- oder PS-Taste
+
+
+ XBOX- oder PS-Taste simulieren
+
+
+ Bildschirmtastatur anzeigen
+
+
+ Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
+
+
+ Beenden der Anwendung erzwingen
+
+
+ Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
+
+
+ Hauptfenster anzeigen und ausblenden
+
+
+ Hotkey durch Drücken einer Schaltfläche oder einer speziellen Taste ändern
+
+
+ Task-Manager öffnen
+
+
+ Drücke diese Tasten: Strg + Shift + Esc
+
+
+ Aufgabenansicht öffnen
+
+
+ Drücke diese Tasten: Windows + Tab
+
+
+ Suspendierung schalten
+
+
+ Unterbrechen oder Fortsetzen der Vordergrundanwendung
+
+
+ Handheld Companion
+
+
+ Über
+
+
+ Controller
+
+
+ Overlay
+
+
+ Profile
+
+
+ OK
+
+
+ Einstellungen
+
+
+ 8BitDo Lite 2
+
+
+ Ausrichtung
+
+
+ Ausrichtung des 3D-Controller-Overlays ändern
+
+
+ Trackpad-Overlay-Ausrichtung ändern
+
+
+ Immer ganz oben
+
+
+ Wenn umgeschaltet, bleibt das 3D-Controller-Overlay über anderen Fenstern.
+
+
+ Zurück
+
+
+ Kamera-Ausrichtung
+
+
+ Ändern Sie das Verhalten des 3D-Controller-Overlay-Modells für die Ausrichtung der Kamera
+
+
+ Statische Kameraneigung
+
+
+ Ändern Sie den Winkel, in Grad
+
+
+ Hintergrundfarbe
+
+
+ Hintergrundfarbe des 3D-Controller-Overlays ändern
+
+
+ Controller-Optionen
+
+
+ PlayStation DualSense
+
+
+ Emulierter Controller
+
+
+ Kamera-Ausrichtung
+
+
+ 3D-Modell dreht sich langsam in Richtung Kamera als Standardposition
+
+
+ Warten...
+
+
+ MACHENIKE HG510
+
+
+ Hauptschalter
+
+
+ 3D-Controller-Overlay-Hauptschalter ändern
+
+
+ Bewegung
+
+
+ Das Modell bewegt sich entsprechend den Bewegungen des Benutzers auf der Grundlage von Sensorinformationen
+
+
+ N64
+
+
+ OEM-Controller
+
+
+ Deckkraft
+
+
+ Deckkraft der 3D-Controller-Überlagerung ändern
+
+
+ Trackpad-Overlay-Transparent ändern
+
+
+ Overlay
+
+
+ Overlay-Modell
+
+
+ 3D-Overlay-Modell ändern
+
+
+ Overlay-Vorschau
+
+
+ Render-Einstellungen
+
+
+ Anti-Aliasing
+
+
+ Ändern des Rendering-Anti-Aliasing-Status
+
+
+ Ändern Sie die Rendereinstellungen Ihres stationären 3D-Overlay-Controller-Modells
+
+
+ Aktualisierungsrate
+
+
+ Ändern Sie die Render-Update-Rate, in Update pro Sekunde
+
+
+ Größe
+
+
+ Größe des 3D-Controller-Overlays ändern
+
+
+ Trackpad-Overlay-Größe ändern
+
+
+ Start
+
+
+ Fisher-Price Controller
+
+
+ Optionen für Trackpads
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ Overlay
+
+
+ Fortsetzen
+
+
+ Pausieren
+
+
+ Beschleunigungssensor-Multiplikator
+
+
+ Ändern Sie den vom System gemeldeten Beschleunigungssensorwert
+
+
+ Zusätzliche Einstellungen
+
+
+ Anti-Deadzone
+
+
+ Ändern Sie die Anti-Deadzone im Spiel, in Prozent
+
+
+ %
+
+
+ Sind Sie sicher, dass Sie dies löschen wollen?
+
+
+ Dieses Element wird sofort gelöscht. Sie können diese Aktion nicht rückgängig machen.
+
+
+ Sind Sie sicher, dass Sie das Profil überschreiben wollen?
+
+
+ {0} wird überschrieben. Sie können diese Aktion nicht rückgängig machen.
+
+
+ Schub-Begrenzung
+
+
+ Ändere TDP-Boost-Begrenzung
+
+
+ Abbrechen
+
+
+ Neues Profil erstellen
+
+
+ Löschen
+
+
+ Profil löschen
+
+
+ Profil aktivieren
+
+
+ Das Profil wird automatisch angewendet, wenn die zugehörige Anwendung erkannt wird.
+
+
+ Globale Einstellungen
+
+
+ Ändern Sie die globalen Profileinstellungen
+
+
+ Gyrometer-Multiplikator
+
+
+ Ändern Sie den vom System gemeldeten Gyrometerwert
+
+
+ Gyro-Lenkachse
+
+
+ Zur Steuerung der horizontalen Bewegung des Controllers können Sie entweder die Gier- oder die Rollachse verwenden
+
+
+ Horizontale Achse invertieren
+
+
+ Vertikale Achse invertieren
+
+
+ Einstellungen der Bewegungssteuerung
+
+
+ Ändern Sie die globalen Bewegungssteuerungseinstellungen
+
+
+ OK
+
+
+ Energie-Einstellungen
+
+
+ Ändern Sie die Energieeinstellungen
+
+
+ Profil-Details
+
+
+ Profilname
+
+
+ Profilpfad
+
+
+ Profile
+
+
+ Profilauswahl
+
+
+ Wählen Sie das Profil, das Sie bearbeiten möchten
+
+
+ Profileinstellungen
+
+
+ Profil aktualisieren
+
+
+ wurden aktualisiert.
+
+
+ Roll
+
+
+ X
+
+
+ Y
+
+
+ Eingabeart
+
+
+ Die physikalischen Controllereingaben können so programmiert werden, dass sie sich wie verschiedene Gerätetypen verhalten
+
+
+ Ausgabegerät
+
+
+ Wählen Sie das Gerät, das die Bewegungsbefehle empfangen soll
+
+
+ Anhaltende Leistungsgrenze
+
+
+ Änderung der Dauerwärmeleistungsgrenze
+
+
+ Thermische Leistung (TDP) überschreiben
+
+
+ Überschreiben Sie das thermal power limit des Prozessors
+
+
+ Aktivieren der universellen Bewegungssteuerung
+
+
+ Deaktiviert, einschalten mit Taste(n)
+
+
+ Aktiviert, ausschalten mit Taste(n)
+
+
+ Bewegungsaktivierung
+
+
+ Wenn die Bewegungseingabe deaktiviert ist, verwenden Sie die ausgewählte(n) Taste(n), um die Bewegung zu aktivieren,
+Wenn die Bewegungseingabe aktiviert ist, verwenden Sie die ausgewählte(n) Taste(n), um die Bewegung zu deaktivieren.
+
+
+ Wählen Sie das Gerät, das die Bewegungsbefehle empfangen soll
+
+
+ Universelle Einstellungen für die Bewegungssteuerung
+
+
+ Übersetzen von Gerätebewegungen in Controllereingaben
+
+
+ Profil aktualisieren
+
+
+ Der Anwendung den Zugriff auf den physischen Controller des Geräts ermöglichen
+
+
+ Erweiterte Kompatibilität (XInputPlus)
+
+
+ Gier
+
+
+ Ja
+
+
+ Manuelle GPU-Takteinstellungen
+
+
+ Setzt die GPU auf einen festen Takt
+
+
+ MHz
+
+
+ Leistungsmodus
+
+
+ Ausgeglichen
+
+
+ Optimieren Sie Ihr Gerät auf der Grundlage von Stromverbrauch und Leistung
+
+
+ Effizienz
+
+
+ Leistung
+
+
+ Schub
+
+
+ Thermische Leistungsgrenze (TDP)
+
+
+ Begrenze Prozessorleistung für weniger Gesamtleistung
+
+
+ Thermal Power Limit wird von einem Profil überschrieben
+
+
+ Anhaltend
+
+
+ W
+
+
+ Profil erstellen
+
+
+ Bietet Gyroskop- und Beschleunigungssensor-Unterstützung für Windows-Handheld-Gamingcomputer über einen virtuellen Controller. Wenn der Dienst aktiviert ist, wird der eingebettete Controller für Anwendungen außerhalb der Whitelist getarnt. Wenn der Dienst deaktiviert ist, wird der eingebettete Controller enttarnt und der virtuelle Controller deaktiviert.
+
+
+ Controller-Service
+
+
+ Sprache
+
+
+ Die Anwendungssprache
+
+
+ Neustart erforderlich
+
+
+ Damit die Änderungen wirksam werden, starten Sie bitte die Anwendung neu
+
+
+ Anwendungs-Theme
+
+
+ Das Anwednungs-Theme, light oder dark mode
+
+
+ Anwendung mit Windows starten
+
+
+ Die Anwendung wird automatisch gestartet, wenn ich mich bei Windows anmelde
+
+
+ Acrylhintergrund verwenden
+
+
+ Acryl
+
+
+ Für die Anwendung wird ein Acrylhintergrund verwendet
+
+
+ Glimmer
+
+
+ Keine
+
+
+ Tabbed
+
+
+ Nach Updates suchen
+
+
+ Minimiert schließen
+
+
+ Die Anwendung wird minimiert und nicht geschlossen
+
+
+ Download
+
+
+ Downloaden -
+
+
+ EcoQoS
+
+
+ Inaktive oder im Hintergrund ablaufende Prozesse und Anwendungen drosseln, um die Energieeffizienz zu verbessern
+
+
+ Allgemeine Optionen
+
+
+ Jetzt installieren
+
+
+ Zuletzt geprüft:
+
+
+ Optionen für Benachrichtigungen
+
+
+ Anwendung im Hintergrund öffnen
+
+
+ Die Anwendung wird minimiert gestartet und erscheint in der Taskleiste
+
+
+ Extern
+
+
+ Intern
+
+
+ Sensor-Optionen
+
+
+ Externer Sensor-Ausrichtung
+
+
+ Wählen Sie aus, auf welcher Seite des Geräts der Sensor montiert wurde
+
+
+ Externer Sensor kopfüber
+
+
+ Der Sensor wurde verkehrt herum montiert, möglich mit USB-C-Konvertern
+
+
+ Sensorauswahl
+
+
+ Wählen Sie den gewünschten Sensor für die Bewegungseingabe aus
+
+
+ Einstellungen
+
+
+ Starttyp
+
+
+ Wird vom Dienstmanager verwendet, um den Starttyp des Dienstes zu definieren
+
+
+ Maximale Leistung
+
+
+ Die maximale Leistung in Watt, die dem Prozessor zugeführt wird
+
+
+ Minimale Leistung
+
+
+ Die Mindestleistung in Watt, die dem Prozessor zugeführt wird
+
+
+ Configurable Power (cTDP) konfigurieren
+
+
+ Ermöglicht die Änderung der minimalen und maximalen Leistungswerte (TDP) über die CPU-Spezifikationen hinaus
+
+
+ Dunkel
+
+
+ Hell
+
+
+ Toast-Benachrichtigung
+
+
+ Benachrichtigungen von der Anwendung im Info-Center abrufen
+
+
+ Update verfügbar
+
+
+ Suche nach Updates...
+
+
+ Wir konnten das Update nicht downloaden.
+
+
+ Wir konnten GitHub nicht erreichen
+
+
+ Wir konnten die Update-Datei nicht finden
+
+
+ Ups. Es gab ein Problem.
+
+
+ Sie sind auf dem neusten Stand
+
+
+ Dein Controller ist nun versteckt. Eingaben werden an den Virtuellen Controller weitergeleitet
+
+
+ Nutzer
+
+
+ Führen Sie dieses Tool als Administrator aus, um diese Einstellungen freizugeben
+
+
+ ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+
+ Virtuellen Controller stummschalten
+
+
+ Viertuellen Controller in Steam-Applikationen stummschalten
+
+
+ Controller-Einstellungen
+
+
+ Ändern Sie die Einstellungen der virtuellen Steuerung
+
+
+ Bewegungs-Anti-Deadzone
+
+
+ Kompensierung der Deadzone im Spiel, verbesserte Registrierung kleiner Bewegungen
+
+
+ ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Verbessern Sie die Zirkularität des Joysticks
+
+
+ Zirkularität linker Stick
+
+
+ Zirkularität rechter Stick
+
+
+ Joystick Deadzone % links
+
+
+ Einstellen der inneren und äußeren Deadzone (Prozent) des linken Joysticks
+
+
+ Joystick Deadzone % rechts
+
+
+ Einstellen der inneren und äußeren Deadzone (Prozent) des rechten Joysticks
+
+
+ Linke Analog-Deadzone %
+
+
+ Einstellen der inneren und äußeren Deadzone (Prozent) des linken Joysticks
+
+
+ Rechter Trigger Deadzone %
+
+
+ Einstellen der inneren und äußeren Deadzone (Prozent) des rechten Joysticks
+
+
+ Zusätzliche Einstellungen
+
+
+ Multiplikator für Bewegungen beim Zielen
+
+
+
+ Aktivierungstaste
+
+
+ Ein zusätzlicher Multiplikator für die Bewegungsempfindlichkeit beim Anvisieren der Visierung oder des Zielfernrohrs durch die Verwendung der konfigurierten Aktivierungstaste
+
+
+ Multiplikatorwert
+
+
+ Kamera-Optionen
+
+
+ Benutzerdefinierte Reaktionskurve
+
+
+ Ausgabe an das Spiel gesendet
+
+
+ Bewegungsintensität
+
+
+ Aggressiv
+
+
+ Standard
+
+
+ Voreinstellungs-Optionen
+
+
+ Präzise
+
+
+ Streifendauer
+
+
+ Ändern Sie die Streifendauer, kalibrieren Sie auf eine 180-Grad-Drehung, in Millisekunden
+
+
+ Flick-Stick (Experimental)
+
+
+ Richten Sie die Kamera in Richtung des (rechten) Joysticks, drehen Sie die Kamera rein in der horizontalen Ebene durch Drehen
+
+
+ Aktiviere Flick-Stick
+
+
+ Empfindlichkeit
+
+
+ Ändern Sie die Bewegungsempfindlichkeit der horizontalen und vertikalen Achse
+
+
+ Empfindlichkeit X
+
+
+ Ändern Sie die Bewegungsempfindlichkeit der horizontalen Achse
+
+
+ Empfindlichkeit Y
+
+
+ Ändern Sie die Bewegungsempfindlichkeit der vertikalen Achse
+
+
+ Stick-Empfindlichkeit
+
+
+ Drehrate ändern
+
+
+ Zusätzliche Einstellungen
+
+
+ Deadzone
+
+
+ Ändern Sie die Deadzone in Grad. Verbessert das Geradeauslaufen
+
+
+ Joystick-Spiel Eingabe
+
+
+ Joystick-Lenkung
+
+
+ Joystick-Lenkung-Optionen
+
+
+ Joystick-Lenkung-Vorschau
+
+
+ Maximaler Lenkwinkel
+
+
+ Den maximalen Lenkwinkelwert in Grad ändern
+
+
+ Linearität der Lenkung
+
+
+ Zuordnung zwischen Eingabe und Lenkung. Niedrigere Werte bieten mehr Genauigkeit in der Nähe des vollen Lenkausschlags, aber weniger Genauigkeit in der Nähe der Mittellage. Höhere Werte bieten mehr Genauigkeit in der Nähe der Mittellage, aber weniger Genauigkeit beim vollen Lenkausschlag. Ein Wert von 1,0 entspricht einer linearen Zuordnung.
+
+
+ Hersteller
+
+
+ Partner
+
+
+ Produktname
+
+
+ A,B,X,Y
+
+
+ BACK GRIPS
+
+
+ Schultertasten
+
+
+ MENÜ
+
+
+ OEM
+
+
+ Desktop-Layout
+
+
+ Desktop-Layout festlegen
+
+
+ Controller-Layout im Desktop festlegen
+
+
+ Bearbeiten
+
+
+ Desktop-Layout aktivieren
+
+
+ Non-Spiel Controller-Layouts
+
+
+ Klicken Sie auf Verbinden neben Ihrem angeschlossenen Controller.
+
+
+ Sie haben keinen physischen Controller angeschlossen. Es werden keine Eingaben an HC oder seinen Dienst gesendet.
+
+
+ Bitte stellen Sie sicher, dass Sie ein kompatibles XInput- oder DInput-Gerät angeschlossen haben.
+
+
+ Kein physischer Controller gefunden
+
+
+ Kein physischer Controller gefunden
+
+
+ Starten Sie den Begleitdienst oder stellen Sie sicher, dass der Status Ihrer virtuellen Steuerung auf "Verbunden" eingestellt ist.
+
+
+ Ihr physischer Controller ist versteckt, aber sie haben keinen Virtuellen Controller. Keine Eingaben werden an das Spiel geschickt.
+
+
+ Kein virtueller Controller gefunden
+
+
+ Heben Sie die Stummschaltung Ihres virtuellen Controllers auf oder zeigen Sie Ihren physischen Controller an.
+
+
+ Ihr physischer Controller ist versteckt, aber ihr Virtueller Controller ist stumm.
+
+
+ Physischer Controller ist versteckt
+
+
+ Verstecken Sie Ihren physischen Controller oder schalten Sie Ihren virtuellen Controller stumm.
+
+
+ Ihr physischer Controller ist nicht versteckt, jedoch haben sie ihren virtuellen Controller stummgeschaltet. Es kann Doppelte Tasteneingaben geben.
+
+
+ Physischer Controller ist nicht versteckt
+
+
+ HD-Rumble
+
+
+ Verwendung einer HD-Rumble-Engine, auf Kosten einer höheren CPU-Auslastung
+
+
+ Controller Einstellungen
+
+
+ Vibrieren, wenn Controller verbunden ist
+
+
+ Physischen Kontroller vibrieren, wenn verbunden
+
+
+ STEUERKREUZ
+
+
+ Helligkeit verringern
+
+
+ Systemhelligkeit um 5% verringern
+
+
+ Lautstärke verringern
+
+
+ Systemlautstärke um 5% verringern
+
+
+ Desktop-Controllerlayout schalten
+
+
+ Helligkeit erhöhen
+
+
+ Erhöhe die Bildschirmhelligkeit um 5%
+
+
+ Lautstärke erhöhen
+
+
+ Erhöhe die Lautstärke um 5%
+
+
+ Bildschirmanzeige
+
+
+ Display-Unterstützung aktivieren
+
+
+ Lüftersteuerung
+
+
+ Einstellen des Lüfterbetriebszyklus auf einen benutzerdefinierten Wert
+
+
+ Info-Center anzeigen und ausblenden
+
+
+ Desktop-Layout
+
+
+ Info-Center anzeigen
+
+
+ Snipping-Tool öffnen
+
+
+ Press this key: Windows + Shift + S
+
+
+ LINKER JOYSTICK
+
+
+ LINKE JOYSTICK BUTTONS
+
+
+ RECHTER JOYSTICK
+
+
+ RECHTE JOYSTICK BUTTONS
+
+
+ Vorlage anwenden
+
+
+ Tasten
+
+
+ Abbrechen
+
+
+ COMMUNITY
+
+
+ Bestätigen
+
+
+ Steuerkreuz
+
+
+ Für aktuellen Controller exportieren
+
+
+ Layout exportieren
+
+
+ Gyro
+
+
+ Joysticks
+
+
+ Layout-Autor
+
+
+ Layout-Beschreibung
+
+
+ Layout-Titel
+
+
+ Spielinformationen mit Layout speichern
+
+
+ Layout-Vorlagen auswählen
+
+
+ VORLAGEN
+
+
+ Trackpads
+
+
+ Trigger
+
+
+ Hotkeys
+
+
+ ms
+
+
+ Overlay-Anzeigenlevel
+
+
+ Deaktiviert
+
+
+ Erweitert
+
+
+ Komplett
+
+
+ Minimal
+
+
+ Verändere die Menge der Statistikwerten
+
+
+ Aktualisierungsrate
+
+
+ Verändere die Update-Rate der Statistikwerte
+
+
+ Automatische TDP
+
+
+ Automatische Anpassung des TDP auf der Grundlage der gemessenen FPS und des gewünschten FPS-Ziels
+
+
+ Framerate-Ziel
+
+
+ Gewünschtes FPS-Ziel für Auto-TDP-Controller
+
+
+ Controller-Layout
+
+
+ Ändern Sie das virtuelle Steuerungslayout
+
+
+ CPU
+
+
+ Bevorzugte Energieleistung (EPP)
+
+
+ CPU/GPU-Leistungsbalance
+
+
+ Legt die Stromverteilungsrichtlinien zwischen CPU und GPU fest
+
+
+ Framerate-Limit
+
+
+ Begrenzt FPS für 3D-Programme
+
+
+ GPU
+
+
+ Maximale GPU-Taktfrequenz
+
+
+ Maximale Taktgeschwindigkeit des GPU in MHz
+
+
+ Leistungsgrenze-Ziel
+
+
+ Getrennt
+
+
+ FPS
+
+
+ Desktop-Profil beim Start aktivieren
+
+
+ Das Desktop-Profil wird beim Start der Anwendung automatisch aktiviert.
+
+
+ Native Display-Orientierung
+
+
+ Einige Funktionen hängen davon ab, dass Sie die ursprüngliche Ausrichtung des Bildschirms kennen, damit sie richtig funktionieren. Wenn dies nicht richtig erkannt wurde, stellen Sie die Ausrichtung Ihres Bildschirms so ein, dass sie mit der Ausrichtung Ihres Controllers übereinstimmt, und klicken Sie dann auf Erkennen
+
+
+ Erkennen
+
+
+ Nicht belegt
+
+
+ Systemeinstellung benutzen
+
+
+ LINKER TRACKPAD
+
+
+ LINKE TRACKPAD-TASTEN
+
+
+ RECHTER TRACKPAD
+
+
+ RECHTE TRACKPAD-TASTEN
+
+
+ LINKE ANALOGTASTE
+
+
+ LINKE ANALOGTASTE
+
+
+ RECHTER TRIGGER
+
+
+ RECHTE TRIGGER-TASTEN
+
+
+ Leistungsgrenze-Ziel
+
+
+ QuickTools-Optionen
+
+
+ %
+
+
+ Aktuellen CPU-Boost-Modus einstellen
+
+
+ CPU-Boost-Modus
+
+
+ Einstellen des Lüfterbetriebszyklus auf einen benutzerdefinierten Wert
+
+
+ Lüfter-Steuerung
+
+
+ Hauptdisplay-Auflösung und Bildwiederholrate anpassen
+
+
+ Display-Auflösung und Bildwiederholrate
+
+
+ Oben Rechts
+
+
+ Oben links
+
+
+ Fensterplatzierung
+
+
+ Unten Rechts
+
+
+ Unten Links
+
+
+ Energie-Optionen
+
+
+ Standort des QuickTools-Fenster festlegen
+
+
+ Drittanbieter-Programme
+
+
+ Keine
+
+
+ QuickTools-Hintergrund, Keine, Glimmer, Tabbed, Akryl
+
+
+ Automatically turn RTSS off when companion is closed
+
+
+ Standard
+
+
+ Aktuelles Profil:
+
+
+ RivaTuner Statistics Server
+
+
+ Automatically hide quick tools when the user clicks outside of window
+
+
+ Bei Fokusverlust ausblenden
+
+
+ Dieser Eingang funktioniert wie ein einfacher Joystick. Ideal für Laptops und Clamshell-Handhelds, automatischer Yaw-Roll-Wechsel je nachdem, wie das Gerät gehalten wird (90 oder 180 Grad geöffnet).
+
+
+ Taste A
+
+
+ Immer an
+
+
+ Button B
+
+
+ Zurück
+
+
+ Unten
+
+
+ Links
+
+
+ Rechts
+
+
+ Hoch
+
+
+ Linke Schultertaste
+
+
+ Linker Stick
+
+
+ Linke Analogtaste
+
+
+ Rechte Schultertaste
+
+
+ Rechter Stick
+
+
+ Rechte Triggertaste
+
+
+ Start
+
+
+ X-Taste
+
+
+ Y-Taste
+
+
+ Emulierter DualShock 4 Controller
+
+
+ Kein emulierter Controller
+
+
+ Emulierter XBOX 360 Controller
+
+
+ Verbunden
+
+
+ Getrennt
+
+
+ Auto-Roll-Gier-Swap
+
+
+ Joystick-Kamera
+
+
+ Joystick-Lenkung
+
+
+ Player space
+
+
+ Handheld Companion
+
+
+ Overlay
+
+
+ QuickTools
+
+
+ Windows
+
+
+ Linker Joystick
+
+
+ Rechter Joystick
+
+
+ Hoppla. Es scheint, dass dieses Profil ausgeführt wird. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
+
+
+ Hoppla. Es scheint, dass dieses Profil keine ausführbare Datei hat. Wie ist das überhaupt möglich?
+
+
+ Hoppla, Es scheint, dass dieses Profil keinen Pfad zu der Anwendung enthält. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
+
+
+ Hoppla. Es scheint, dass Sie nicht über die erforderliche Berechtigungsstufe verfügen, um den Inhalt dieser Anwendung zu ändern. Vergewissern Sie sich, dass Sie das Programm im Administratormodus gestartet haben.
+
+
+ Hier gibt es nichts zu sehen.
+
+
+ Standard
+
+
+ Eco
+
+
+ Hoch
+
+
+ Automatisch
+
+
+ Deaktiviert
+
+
+ Manuell
+
+
+ Dieser Eingang funktioniert wie ein einfacher Joystick. Er ist für traditionelle Joystick-Anwendungen gedacht
+
+
+ Dieser Eingang funktioniert wie ein Joystick, der für die Steuerung eines Lenkrads oder eines Rennspiels optimiert ist.
+
+
+ Diese Eingabe funktioniert wie ein Joystick, der für die Steuerung einer First- oder Third-Person-Kamera optimiert ist
+
+
+ Handheld Companion
+
+
+ ≈
+
+
+ ≈
+
+
+ ≈
+
+
+ ≈
+
+
+ AYA
+
+
+ AYA
+
+
+ AYA
+
+
+ AYA
+
+
+ KB
+
+
+ RC
+
+
+ LC
+
+
+ RC
+
+
+ LC
+
+
+ RC
+
+
+ LC
+
+
+ Win
+
+
+ Esc
+
+
+ RC
+
+
+ LC
+
+
+ Dies ist Ihr Standard-Controller-Profil. Dieses Profil wird für alle Ihre Anwendungen verwendet, die kein spezifisches Profil haben. Einige Optionen, die eine ausführbare Datei erfordern, sind möglicherweise deaktiviert.
+
+
+ M1
+
+
+ Kreuz
+
+
+ Kreis
+
+
+ Viereck
+
+
+ Dreieck
+
+
+ Teilen
+
+
+ Sony
+
+
+ Optionen
+
+
+ Benutzerdefiniert
+
+
+ Gerät
+
+
+ Auto-Roll-Gier-Swap
+
+
+ Joystick Camera
+
+
+ Joystick Steering
+
+
+ Player Space
+
+
+ Linker Stick
+
+
+ Rechter Stick
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ Anzeigen
+
+
+ STEAM
+
+
+ Menü
+
+
+ Hoppla, It seems this profile excutable is running. Some options requiring an executable might be disabled.
+
+
+ Command Center
+
+
+ Armory Crate
+
+
+ Optionen
+
+
+ L2
+
+
+ Linker Stick
+
+
+ R2
+
+
+ Rechter Stick
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ Anzeigen
+
+
+ Unten
+
+
+ Links
+
+
+ DPad Rechts
+
+
+ Hoch
+
+
+ LB
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Linker Stick
+
+
+ Linker Stick unten
+
+
+ Linker Stick links
+
+
+ Linker Stick rechts
+
+
+ Linker Stick oben
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ RB
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Rechter Stick
+
+
+ Rechter Stick unten
+
+
+ Rechter Stick links
+
+
+ Rechter Stick rechts
+
+
+ Rechter Stick oben
+
+
+ XBOX-Taste
+
+
+ Menü
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ LeftStick
+
+
+ RightStick
+
+
+ Yes
+
+
+ No
+
+
+ Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
+
+
+ Warning
+
+
+ Disabled
+
+
+ Injection (recommended)
+
+
+ Redirection
+
+
+ Improve virtual controller detection
+
+
+ Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
+
+
+ Yes
+
+
+ No
+
+
+ Your device must be restarted in order for the changes to take effect. Would you like to restart now?
+
+
+ Restart required
+
+
+ Yes
+
+
+ No
+
+
+ Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
+
+
+ Warning
+
+
+ S
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Accelerometer
+
+
+ Back
+
+
+ Exit
+
+
+ Show current controller templates only
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ External
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ Waiting for foreground process...
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.es-ES.resx b/HandheldCompanion/Properties/Resources.es-ES.resx
index b592cd223..84362b7a5 100644
--- a/HandheldCompanion/Properties/Resources.es-ES.resx
+++ b/HandheldCompanion/Properties/Resources.es-ES.resx
@@ -1,2359 +1,2353 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Acerca de
-
-
- Una combinación de un servicio de Windows y una interfaz gráfica de usuario optimizada para aumentar la experiencia de su computadora portátil para juegos. Las características incluyen: control de movimiento, también conocido como control giroscópico, simulación de controlador virtual, superposición de herramientas rápidas, paneles táctiles virtuales, modelo de controlador 3D, sistema de configuración de perfil basado en la aplicación. Handheld Companion se basa en el controlador ViGEmBus y las bibliotecas ViGEmClient, así como en el controlador de filtro en modo kernel HidHide. Los algoritmos de control de movimiento se basan en el trabajo de Jibbsmart y en la información disponible en GyroWiki.
-
-
- Acelerometro
-
-
- Autor
-
-
- Contribuyentes
-
-
- Descripcion
-
-
- Donar
-
-
- Inclinómetro
-
-
- Clinómetro
-
-
- N/A
-
-
- Enlaces Relacionados
-
-
- External
-
-
- Internal
-
-
- Nombre del Sensor
-
-
- Especificaciones del Sensor
-
-
- Servicio
-
-
- Codigo Fuente
-
-
- Version
-
-
- Wiki
-
-
- Administrador
-
-
- Ocultar mando al conectar
-
-
- Ocultar el mando físico cuando está conectado
-
-
- Conectar
-
-
- Mando
-
-
- Encubrimiento del controlador
-
-
- Opciones del mando
-
-
- Desconectar
-
-
- Dispositivos de entrada
-
-
- Esconder mando o cerrar
-
-
- Restaurar la visibilidad de todos los mandos físicos cuando se sale de la aplicación
-
-
- Intensidad de vibración
-
-
- Cambiar intensidad de vibración del mando
-
-
-
- ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- Reducir el límite de potencia térmica (TDP)
-
-
- Disminuya el TDP del sistema o del perfil actualmente aplicado en 1W
-
-
- Presione para definir el gatillo
-
-
- Presione para definir la salida del teclado
-
-
- Aumentar el límite de potencia térmica (TDP)
-
-
- Aumente el TDP del sistema o del perfil actualmente aplicado en 1W
-
-
- Controlador de pantalla 3D
-
-
- Cambie la tecla de acceso rápido 3D presionando un botón o una tecla especial
-
-
- Mostrar trackpads virtuales
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Abrir ventana de herramientas rápidas
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Acceso directo personalizado
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Mostrar y ocultar el escritorio
-
-
- Presiona esta tecla: Windows + D
-
-
- Esc
-
-
- Presiona la tecla: Esc
-
-
- Cambia entre ventana y pantalla completa
-
-
- Presiona la tecla: Enter
-
-
- Boton Guia o Boton PS
-
-
- Simular boton Xbox Guia o boton Sony PS
-
-
- Mostrar teclado
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Forzar el cierre de la aplicación
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Mostrar y ocultar la menú principal
-
-
- Cambie la tecla de acceso rápido presionando un botón o una tecla especial
-
-
- Abrir administrador de tareas
-
-
- Presiona las teclas: Ctrl + Shift + Esc
-
-
- Abrir vista de tareas
-
-
- Pulsa las teclas: Windows + Tab
-
-
- Toggle Suspender
-
-
- Suspender o reanudar la aplicación en primer plano
-
-
- Handheld Companion
-
-
- Acerca de
-
-
- Mando
-
-
- Superposicion
-
-
- Perfiles
-
-
- OK
-
-
- Opciones
-
-
- 8BitDo Lite 2
-
-
- Alineación
-
-
- Cambiar la alineación de la superposición del controlador 3D
-
-
- Cambiar la alineación de la superposición de los trackpads
-
-
- Siempre arriba
-
-
- Cuando se activa, la superposición del controlador 3D se sobrepondrá encima de otras ventanas
-
-
- Atras
-
-
- Reconocimiento facial
-
-
- Cambie el comportamiento del modelo de superposición del controlador 3D para mirar hacia la cámara
-
-
- Inmovilizar angulo de la camara
-
-
- Cambiar el ángulo, en grados
-
-
- Color de fondo
-
-
- Cambiar el color de fondo de la superposición del controlador 3D
-
-
- Opciones del Mando
-
-
- PlayStation DualSense
-
-
- Emulacion mando
-
-
- Camara facial
-
-
- El modelo 3D gira lentamente para mirar a la cámara como posición predeterminada
-
-
- Escuchando...
-
-
- MACHENIKE HG510
-
-
- Gatillo Principal
-
-
- Cambiar el gatillo principal de superposición del mando 3D
-
-
- Movimiento
-
-
- El modelo se moverá de acuerdo con los movimientos del usuario según la información del sensor
-
-
- N64
-
-
- Controlador OEM
-
-
- Opacidad
-
-
- Cambiar la opacidad de superposición del mando 3D
-
-
- Cambiar la opacidad de la superposición de los trackpads
-
-
- Sobreposicion
-
-
- Modelo de sobreposicion
-
-
- Cambiar el modelo de sobreposicion del mando 3D
-
-
- Vista previa sobreposicion
-
-
- Configuración de procesamiento
-
-
- Anti-Aliasing
-
-
- Cambiar el estado del suavizado de renderizado
-
-
- Cambie la configuración de procesamiento de su modelo de mando de superposición 3D
-
-
- Frecuencia de actualización
-
-
- Cambiar la tasa de actualización de procesamiento, en actualización por segundo
-
-
- Tamaño
-
-
- Cambiar el tamaño de superposición del mando 3D
-
-
- Cambiar el tamaño de superposición de los trackpads
-
-
- Start
-
-
- Controlador de Fisher-Price
-
-
- Opciones de Trackpads
-
-
- Xbox One
-
-
- ZD O+
-
-
- Superponer
-
-
- Reanudar
-
-
- Suspender
-
-
- Opciones adicionales
-
-
- Multiplicador de movimiento apuntando hacia abajo
-
-
- Boton de activación
-
-
- Un multiplicador de sensibilidad de movimiento adicional al apuntar hacia abajo o el alcance mediante el uso del botón de activación configurado
-
-
- Valor multiplicador
-
-
- Opciones de camara
-
-
- Curva de respuesta personalizada
-
-
- Salida enviada al juego
-
-
- Intensidad de movimiento
-
-
- Agresivo
-
-
- Por defecto
-
-
- Opciones preestablecidas
-
-
- Precisa
-
-
- Duración del movimiento
-
-
- Cambie la duración del movimiento rápido, calibre a un giro de 180 grados, en milisegundos
-
-
- Flick stick (experimental)
-
-
- Apunte la cámara en la dirección del movimiento del joystick (derecho), gire la cámara puramente en el plano horizontal girando
-
-
- Habilitar dispositivo móvil
-
-
- Sensibilidad
-
-
- Cambiar la sensibilidad de movimiento del eje horizontal y vertical
-
-
- Sensibilidad X
-
-
- Cambiar la sensibilidad de movimiento del eje horizontal
-
-
- Sensibilidad Y
-
-
- Cambiar la sensibilidad de movimiento del eje vertical
-
-
- Sensibilidad del stick
-
-
- Cambiar la sensibilidad de movimiento del eje vertical
-
-
- Opciones adicionales
-
-
- Zona muerta
-
-
- Cambia la zona muerta de la dirección, en grados. Mejora la dirección recta
-
-
- Joystick game Input
-
-
- Dirección con joystick
-
-
- Opciones de dirección con joystick
-
-
- Vista previa de la dirección con joystick
-
-
- Ángulo de dirección máximo
-
-
- Cambiar el valor máximo del ángulo de dirección, en grados
-
-
- Linealidad de dirección
-
-
- Mapeo entre entrada y dirección. Los valores más bajos proporcionan más precisión cerca del enganche completo pero menos precisión cerca del centro. Los valores más altos proporcionan más precisión cerca del centro pero menos precisión cerca del enganche completo. 1.0 es un mapeo lineal
-
-
- Multiplicador de acelerómetro
-
-
- Cambiar el valor del acelerómetro informado por el sistema
-
-
- Opciones adicionales
-
-
- Anti-zona muerta
-
-
- Cambiar la anti-zona muerta del juego, en porcentaje
-
-
- %
-
-
- Estás seguro de que quieres eliminar?
-
-
- Este artículo será eliminado inmediatamente. No puede deshacer esta acción.
-
-
- Estás seguro de que quieres sobrescribir este perfil?
-
-
- {0} se sobrescribirá. No puede deshacer esta acción.
-
-
- Aumento del limite de potencia
-
-
- Cambiar el límite de potencia térmica de impulso
-
-
- Cancelar
-
-
- Crear un nuevo perfil
-
-
- Eliminar
-
-
- Eliminar perfil
-
-
- Perfil de usuario por juego
-
-
- El perfil se aplicará automáticamente cuando se detecte la aplicación asociada
-
-
- Opciones globales
-
-
- Cambiar la configuración de perfiles globales
-
-
- Multiplicador de girómetro
-
-
- Cambiar el valor del girómetro informado por el sistema
-
-
- Eje de dirección del giroscopio
-
-
- Para controlar el movimiento horizontal del controlador,puede usar el eje de yaw o balanceo
-
-
- Invertir el eje horizontal
-
-
- Invertir el eje vertical
-
-
- Ajustes de control de movimiento
-
-
- Cambiar la configuración de control de movimiento global
-
-
- OK
-
-
- configuración de energía
-
-
- Cambiar la configuración de energía
-
-
- Detalles del perfil
-
-
- Nombre del perfil
-
-
- Ruta del perfil
-
-
- Perfiles
-
-
- Seleccion de perfil
-
-
- Selecciona el perfil que quieres modificar
-
-
- Detalles del perfil
-
-
- Perfil actualizado
-
-
- Fue actualizado
-
-
- Balanceo
-
-
- X
-
-
- Y
-
-
- Estilo de entrada
-
-
- Las entradas físicas del controlador se pueden programar para actuar como diferentes tipos de dispositivos
-
-
- Dispositivo de salida
-
-
- Seleccione el dispositivo que recibirá los comandos de movimiento
-
-
- Límite de potencia sostenida
-
-
- Cambiar límite de potencia térmica sostenida
-
-
- Límite de potencia térmica (TDP)
-
-
- Limita la potencia del procesador para reducir la potencia total
-
-
- Habilitar controlador de movimiento universal
-
-
- Deshabilitado, encender con botón(es)
-
-
- Habilitado, apaga con botón(es)
-
-
- Activación de movimiento
-
-
- Compensa la zona muerta del juego, mejora el registro de pequeños movimientos
-
-
- Seleccione el dispositivo que recibirá los comandos de movimiento
-
-
- Ajustes de control de movimiento universal
-
-
- Traducir los movimientos del dispositivo en entradas del controlador
-
-
- Actualización del perfil
-
-
- Permitir que la aplicación acceda al controlador físico del dispositivo
-
-
- Compatibilidad extendida (XInputPlus)
-
-
- Yaw
-
-
- Si
-
-
- Desconectar
-
-
- Control manual del reloj de la GPU
-
-
- Establece la GPU en un reloj fijo
-
-
- MHz
-
-
- Modo de energia
-
-
- Equilibrado
-
-
- Optimice su dispositivo según el uso de energía y el rendimiento
-
-
- Eficiencia
-
-
- Rendimiento
-
-
- Aumentar
-
-
- Límite de potencia térmica (TDP)
-
-
- Limita la potencia del procesador para reducir la potencia total
-
-
- El límite de potencia térmica se sobrescribe con un perfil
-
-
- Sostenido
-
-
- W
-
-
- Crear perfil
-
-
- Esperando el proceso de primer plano...
-
-
- Brinda soporte de giroscopio y acelerómetro a las computadoras de juegos portátiles de Windows a través de un controlador virtual. Si el servicio está habilitado, el controlador incorporado se ocultará a las aplicaciones fuera de la lista blanca. Si el servicio está deshabilitado, el controlador integrado se desenmascarará y el controlador virtual se deshabilitará.
-
-
- Servicio del controlador
-
-
- Idioma
-
-
- Idioma de la aplicacion
-
-
- Reinicio necesario
-
-
- Para que los cambios surtan efecto, por favor reinicie la aplicación
-
-
- Tema de la aplicacion
-
-
- Tema de aplicacion, oscuro o claro
-
-
- Auto-inicio de la aplicacion
-
-
- La aplicacion iniciara al iniciar windows
-
-
- Aplicacion de fondo
-
-
- Acrilico
-
-
- El fondo de la aplicación, ninguno, mica, tabulado, acrílico
-
-
- Mica
-
-
- Ninguno
-
-
- Pestañas
-
-
- Buscar actualizaciones
-
-
- Cerrar, minimiza el programa
-
-
- La aplicación se minimizará en lugar de cerrarse
-
-
- Habilitar perfil de escritorio al inicio
-
-
- El perfil de escritorio se habilitará automáticamente al iniciar la aplicación
-
-
- Descargar
-
-
- Descargando
-
-
- Eficiencia inteligente
-
-
- El modo de eficiencia inteligente reduce la prioridad de los procesos en segundo plano y mejora la eficiencia energética
-
-
- Opciones generales
-
-
- Instalar ahora
-
-
- Ultima comprobación:
-
-
- Opciones de notificación
-
-
- Abrir aplicacion en segundo plano
-
-
- La aplicación inicialmente comenzará minimizada y aparecerá en la barra de tareas
-
-
- Externo
-
-
- Interno
-
-
- Opciones del sensor
-
-
- Dirección de colocación del sensor externo
-
-
- Seleccione en qué lado del dispositivo se ha montado el sensor
-
-
- Sensor externo al revés
-
-
- El sensor se ha montado al revés, posible con convertidor USB-C
-
-
- Seleccion de sensores
-
-
- Seleccione el sensor deseado utilizado para la entrada de movimiento
-
-
- Opciones
-
-
- Tipo de inicio
-
-
- Utilizado por el administrador de servicios para definir el tipo de inicio del servicio
-
-
- Maximo poder
-
-
- La potencia máxima en vatios suministrada al procesador
-
-
- Poder minimo
-
-
- La potencia mínima en vatios suministrada al procesador
-
-
- Anulación de potencia configurable (cTDP)
-
-
- Permite modificar los valores mínimo y máximo de potencia (TDP) más allá de las especificaciones de la CPU
-
-
- Oscuro
-
-
- Claro
-
-
- Notificacion flotante
-
-
- Recibe notificaciones de la aplicación en el centro de acción de Windows
-
-
- Actualizaciones disponibles
-
-
- Comprobando actualizaciones...
-
-
- No pudimos descargar el archivo de actualización.
-
-
- No se pudo acceder a Github
-
-
- No pudimos localizar el archivo de actualización.
-
-
- Ups. Hubo un problema
-
-
- Esta todo actualizado
-
-
- El controlador ahora está oculto y las entradas se reenvían al controlador virtual
-
-
- Usuario
-
-
- Ejecute esta herramienta como administrador para desbloquear esta configuración
-
-
- ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
-
-
- Silenciar controlador virtual
-
-
- Silenciar el controlador virtual en aplicaciones relacionadas con Steam
-
-
- Opciones del mando
-
-
- Cambiar la configuración del mando virtual
-
-
- Movimiento anti-zona muerta
-
-
- Compensa la zona muerta del juego, mejora el registro de pequeños movimientos
-
-
- ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Mejorar la circularidad de el stick.
-
-
- Circularidad stick izquierdo
-
-
- Circularidad stick derecho
-
-
- Joystick zona muerta % izquierdo
-
-
- Ajuste el porcentaje de zona muerta interior y exterior del joystick izquierdo
-
-
- Joystick zona muerta % derecho
-
-
- Ajuste el porcentaje de zona muerta interior y exterior del joystick derecho
-
-
- Gatillo izquierdo deadzone %
-
-
- Ajuste el porcentaje de zona muerta interior y exterior del gatillo izquierdo
-
-
- Gatillo derecho deadzone %
-
-
- Ajuste el porcentaje de zona muerta interior y exterior del gatillo derecho
-
-
- Controlador de vibración al conectar
-
-
- Vibración del mando cuando esta conectado
-
-
- Diseño de escritorio
-
-
- Cambiar el diseño del controlador de escritorio
-
-
- Mostrar Centro de acción
-
-
- Mostrar y ocultar Centro de acción de Windows
-
-
- Disposicion del mando
-
-
- Anulación del ventilador
-
-
- Establezca el ciclo de trabajo del ventilador en un valor definido por el usuario
-
-
- Visualización en pantalla
-
-
- Habilitar soporte de visualización en pantalla
-
-
- Reducir el brillo
-
-
- Reducir el brillo de la pantalla actual en un 5%
-
-
- Reducir volumen
-
-
- Reducir el volumen del sistema en un 5%
-
-
- Aumentar brillo
-
-
- Aumentar el brillo de la pantalla actual en un 5%
-
-
- Aumentar volumen
-
-
- Aumentar volumen actual en un 5%
-
-
- TDP Automático
-
-
- Ajuste automático de TDP basado en FPS medido y objetivo de FPS solicitado
-
-
- FPS objetivo
-
-
- Valor objetivo de FPS deseado para el controlador TDP automático
-
-
- GPU Clock maxima frecuencia
-
-
- Velocidad máxima de reloj de la GPU en Mhz
-
-
- FPS
-
-
- Nivel de visualización de sobreposicion
-
-
- Cambiar el nivel de visualización de la información en pantalla
-
-
- Frecuencia de actualización
-
-
- Cambiar la frecuencia de actualización de visualización en pantalla
-
-
- Limite de FPS
-
-
- Limite de FPS para aplicaciones 3D
-
-
- Abra la herramienta Recortes
-
-
- Presiona las teclas: Windows + Shift
-
-
- Teclas acceso rapido
-
-
- Usar la configuración del sistema
-
-
- Aplicaciones de terceros
-
-
- Exportar disposicion
-
-
- No se detectó ningún controlador físico
-
-
- Exportar para el controlador actual
-
-
- Es posible que desee iniciar el servicio complementario o asegurarse de que el estado de su controlador virtual esté configurado en: Conectado
-
-
- Dpad
-
-
- Su controlador físico está oculto, pero no tiene ningún controlador virtual disponible. No se enviarán entradas a los juegos.
-
-
- No se detectó ningún controlador virtual
-
-
- Confirmar
-
-
- Comunidad
-
-
- Es posible que desee activar el silencio de su controlador virtual o mostrar su controlador físico.
-
-
- Cancelar
-
-
- Su controlador físico está oculto, pero ha silenciado su controlador virtual.
-
-
- Botones
-
-
- Aplicar plantilla
-
-
- El controlador físico está oculto.
-
-
- Es posible que desee ocultar su controlador físico o silenciar su controlador virtual.
-
-
- Su controlador físico no está oculto, pero tiene un controlador virtual activado. Es posible que encuentres entradas dobles en los juegos.
-
-
- El controlador físico no está oculto.
-
-
- Opciones del controlador
-
-
- Girómetro
-
-
- Asegúrese de haber conectado un dispositivo XInput o DInput compatible.
-
-
- Autor de el diseño
-
-
- Socio
-
-
- Fabricante
-
-
- Nombre del producto
-
-
- Trackpads
-
-
- No hay ningún controlador físico conectado
-
-
- Diseño de escritorio
-
-
- Definir el diseño de escritorio
-
-
- Definir el diseño del controlador cuando esté en modo de escritorio
-
-
- Editar
-
-
- Plantillas
-
-
- Habilitar diseño de escritorio
-
-
- Selector de plantilla de diseño
-
-
- Diseños de controladores que no son de juegos
-
-
- Mostrar solo las plantillas de controlador actuales
-
-
- Guardar información del juego con el diseño.
-
-
- Título del diseño
-
-
- Es posible que desees hacer clic en Conectar junto a tu controlador conectado.
-
-
- Descripción del diseño
-
-
- No tienes ningún controlador físico conectado. No se enviarán insumos a HC ni a su servicio.
-
-
- Joysticks
-
-
- Vibración HD
-
-
- JOYSTICK IZQUIERDO
-
-
- BOTONES JOYSTICK IZQUIERDO
-
-
- Ocultar automáticamente herramientas rápidas cuando el usuario hace click fuera de la ventana
-
-
- Ocultar cuando pierde el foco
-
-
- Objetivo de límite de potencia
-
-
- Por defecto
-
-
- JOYSTICK DERECHO
-
-
- PAD DIRECCIONAL
-
-
- Perfil Actual:
-
-
- Establezca el ciclo de trabajo del ventilador en un valor definido por el usuario
-
-
- Anulación del ventilador
-
-
- Resolución de pantalla y frecuencia de actualización
-
-
- Establecer modo de refuerzo de CPU actual
-
-
- Modo de refuerzo de CPU
-
-
- No establecido
-
-
- %
-
-
- Detectar
-
-
- OEM
-
-
- BUMPERS
-
-
- Desactiva automáticamente RTSS cuando HC está cerrado
-
-
- RivaTuner Statistics Server
-
-
- Parte superior derecha
-
-
- Parte superior izquierda
-
-
- Definir la ubicación de la ventana de herramientas rápidas
-
-
- Parte inferior derecha
-
-
- Parte inferior izquierda
-
-
- MENU
-
-
- Ubicación de la ventana
-
-
- Opciones de herramientas rápidas
-
-
- Fondo de herramientas rápidas, none, mica, tabbed, acrylic
-
-
- Opciones de energía
-
-
- Desactiva automáticamente HWiNFO cuando HC está cerrado
-
-
- A,B,X,Y
-
-
- HWiNFO
-
-
- CONTROLES TRASEROS
-
-
- Ninguno
-
-
- Algunas funciones dependen de conocer la orientación de la pantalla nativa para funcionar correctamente. Si esto no se detectó correctamente, configure la orientación de su pantalla en la orientación que coincida con su controlador, luego haga clic en Detectar
-
-
- Ajustar la resolución de la pantalla principal y la frecuencia de actualización
-
-
- Objetivo de límite de potencia
-
-
- ms
-
-
- BOTONES GATILLO DERECHO
-
-
- Gatillos
-
-
- Orientación de pantalla nativa
-
-
- Desactivado
-
-
- Extendido
-
-
- BOTONES GATILLO IZQUIERDO
-
-
- BOTONES JOYSTICK DERECHOS
-
-
- TRACKPAD IZUIERDO
-
-
- BOTONES TRACKPAD IZQUIERDO
-
-
- TRACKPAD DERECHO
-
-
- GPU
-
-
- GATILLO DERECHO
-
-
- BOTONES TRACKPAD DERECHO
-
-
- Especifica la política de distribución de energía entre CPU y GPU.
-
-
- Equilibrio de potencia CPU/GPU
-
-
- Utilice un motor de vibración de alta definición, a costa de un mayor uso de CPU
-
-
- Preferencia de rendimiento energético (EPP)
-
-
- GATILLO IZQUIERDO
-
-
- CPU
-
-
- Completo
-
-
- Cambiar el diseño del controlador virtual
-
-
- Mínimo
-
-
- Esta entrada funcionará como un simple joystick. Ideal para portátiles y dispositivos de mano tipo clamshell, cambio automático de balanceo de guiñada en función de cómo se sostenga el dispositivo (90 o 180 grados abiertos).
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Equis
-
-
- Circulo
-
-
- Cuadrado
-
-
- Triangulo
-
-
- Share
-
-
- Sony
-
-
- Opciones
-
-
- Controlador DualShock 4 emulado
-
-
- Sin controlador emulado
-
-
- Controlador XBOX 360 emulado
-
-
- Conectado
-
-
- Desconectado
-
-
- Auto Roll Yaw Swap
-
-
- Cámara con joystick
-
-
- Dirección con joystick
-
-
- Espacio del jugador
-
-
- Handheld Companion
-
-
- Sobreposicion
-
-
- Herramientas rápidas
-
-
- Windows
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- Vista
-
-
- Menu
-
-
- Joystick izquierdo
-
-
- Joystick derecho
-
-
- Este es su perfil de controlador predeterminado. Este perfil se aplicará a todas tus aplicaciones que no tengan un perfil específico. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
-
-
- Ups. Parece que este perfil no tiene un ejecutable. Como es esto posible?
-
-
- Ups. Parece que este perfil no tiene una ruta a la aplicación. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
-
-
- Ups. Parece que no tienes el nivel de permiso necesario para modificar el contenido de esta aplicación. Asegúrese de haber iniciado este programa en modo administrador.
-
-
- Nada que ver aqui.
-
-
- Ups. Parece que este perfil ejecutable se está ejecutando. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
-
-
- Por defecto
-
-
- Eco
-
-
- Alta
-
-
- Automático
-
-
- Desactivado
-
-
- Manual
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- Vista
-
-
- LB
-
-
- RB
-
-
- Guide
-
-
- Menu
-
-
- Esta entrada funcionará como un simple joystick. Esto está diseñado para aplicaciones de joystick tradicionales.
-
-
- Esta entrada funcionará como un joystick optimizado para controlar un volante o un juego de carreras.
-
-
- Esta entrada funcionará como un joystick optimizado para controlar una cámara en primera o tercera persona
-
-
- Handheld Companion
-
-
- Opciones
-
-
- STEAM
-
-
- Command center
-
-
- Armory crate
-
-
- M1
-
-
- Right Thumb Down
-
-
- Right Thumb Left
-
-
- Right Thumb Right
-
-
- Right Thumb Up
-
-
- A
-
-
- Siempre encendido
-
-
- B
-
-
- Atrás
-
-
- Right Thumb
-
-
- DPad Abajo
-
-
- DPad Derecho
-
-
- DPad Arriba
-
-
- Shoulder izquierdo
-
-
- Thumb izquierdo
-
-
- Gatillo izquierdo
-
-
- Shoulder Derecho
-
-
- Thumb Derecho
-
-
- Gatillo Derecho
-
-
- DPad Izquierda
-
-
- R5
-
-
- R4
-
-
- R3
-
-
- B7
-
-
- B8
-
-
- DPad Abajo
-
-
- DPad Izquierda
-
-
- PPad Derecha
-
-
- DPad Arriba
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Thumb Izquierdo
-
-
- Left Thumb Down
-
-
- Left Thumb Left
-
-
- Left Thumb Right
-
-
- Left Thumb Up
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- R2
-
-
- Start
-
-
- X
-
-
- Y
-
-
- Ups. Parece que este perfil se está ejecutando. Algunas opciones que requieren un ejecutable pueden estar desactivadas.
-
-
- B6
-
-
- B5
-
-
- R2
-
-
- Thumb Derecho
-
-
- Esc
-
-
- KB
-
-
- Personalizado
-
-
- Dispositivo
-
-
- Joystick Cámara
-
-
- Joystick de dirección
-
-
- Espacio de jugador
-
-
- Stick izquierdo
-
-
- Stick derecho
-
-
- L2
-
-
- Thumb izquierdo
-
-
- Auto Roll Yaw Swap
-
-
- Win
-
-
- Deslizar con una sola pulsación
-
-
- Deslizamiento multitáctil
-
-
- Clic con un solo toque
-
-
- Toque único
-
-
- Clic multitáctil
-
-
- Multitoque
-
-
- Deslizar con una sola pulsación
-
-
- Deslizamiento multitáctil
-
-
- Equis
-
-
- Circulo
-
-
- Cuadrado
-
-
- Triángulo
-
-
- Compartir
-
-
- Clic con un solo toque
-
-
- Toque sencillo
-
-
- Click multitáctil
-
-
- Multitoque
-
-
- Sony
-
-
- Opciones
-
-
- A
-
-
- Alt
-
-
- Apóstrofe
-
-
- B
-
-
- Barra invertida
-
-
- Retroceso
-
-
- C
-
-
- Coma
-
-
- Control
-
-
- D
-
-
- Eliminar
-
-
- E
-
-
- Fin
-
-
- Intro
-
-
- Igual
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Inicio
-
-
- I
-
-
- Insertar
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Menos
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Período
-
-
- Q
-
-
- R
-
-
- S
-
-
- Punto y coma
-
-
- Mayus
-
-
- Barra
-
-
- Espacio
-
-
- T
-
-
- Tabulador
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- Stick izquierdo
-
-
- Mover el cursor
-
-
- Stick Derecho
-
-
- Rueda Ratón
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Menos
-
-
- L
-
-
- R
-
-
- Inicio
-
-
- Captura
-
-
- Además
-
-
- Stick Izquierdo
-
-
- Stick Derecho
-
-
- Sí
-
-
- No
-
-
- Es posible que la mejora de la detección del controlador virtual no funcione si cierras Handheld Companion. ¿Está seguro?
-
-
- Aviso
-
-
- Desactivado
-
-
- Inyección (recomendado)
-
-
- Redirección
-
-
- Mejorar la detección de controladores virtuales
-
-
- Obliga al controlador virtual a ser detectado como primer controlador durante el inicio de Windows. Actívalo si tu aplicación/juego no detecta tus entradas (requiere reiniciar el dispositivo).
-
-
- Sí
-
-
- No
-
-
- Es necesario reiniciar el dispositivo para que los cambios surtan efecto. ¿Quieres reiniciar ahora?
-
-
- Reinicio requerido
-
-
- Sí
-
-
- No
-
-
- Si desactiva esta opción, también desactivará "Mejorar la detección de controladores virtuales". ¿Desea continuar?
-
-
- Aviso
-
-
- Conectar
-
-
- Desconectar
-
-
- Mostrar
-
-
- Virtual
-
-
- Ocultar
-
-
- Atras
-
-
- Salir
-
-
- Ventana principal
-
-
- Navegar
-
-
- Herramientas rápidas
-
-
- Selecciona
-
-
- Externo
-
-
- ¿Está seguro de que desea aplicar esta plantilla? Se anularán todos los ajustes de diseño.
-
-
- No se puede deshacer esta acción. Plantilla aplicada anteriormente: {0}
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Acerca de
+
+
+ Una combinación de un servicio de Windows y una interfaz gráfica de usuario optimizada para aumentar la experiencia de su computadora portátil para juegos. Las características incluyen: control de movimiento, también conocido como control giroscópico, simulación de controlador virtual, superposición de herramientas rápidas, paneles táctiles virtuales, modelo de controlador 3D, sistema de configuración de perfil basado en la aplicación. Handheld Companion se basa en el controlador ViGEmBus y las bibliotecas ViGEmClient, así como en el controlador de filtro en modo kernel HidHide. Los algoritmos de control de movimiento se basan en el trabajo de Jibbsmart y en la información disponible en GyroWiki.
+
+
+ Acelerometro
+
+
+ Autor
+
+
+ Contribuyentes
+
+
+ Descripcion
+
+
+ Donar
+
+
+ Inclinómetro
+
+
+ Clinómetro
+
+
+ N/A
+
+
+ Enlaces Relacionados
+
+
+ External
+
+
+ Internal
+
+
+ Nombre del Sensor
+
+
+ Especificaciones del Sensor
+
+
+ Servicio
+
+
+ Codigo Fuente
+
+
+ Version
+
+
+ Wiki
+
+
+ Administrador
+
+
+ Ocultar mando al conectar
+
+
+ Ocultar el mando físico cuando está conectado
+
+
+ Conectar
+
+
+ Mando
+
+
+ Encubrimiento del controlador
+
+
+ Opciones del mando
+
+
+ Desconectar
+
+
+ Dispositivos de entrada
+
+
+ Esconder mando o cerrar
+
+
+ Restaurar la visibilidad de todos los mandos físicos cuando se sale de la aplicación
+
+
+ Intensidad de vibración
+
+
+ Cambiar intensidad de vibración del mando
+
+
+
+ ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Reducir el límite de potencia térmica (TDP)
+
+
+ Disminuya el TDP del sistema o del perfil actualmente aplicado en 1W
+
+
+ Presione para definir el gatillo
+
+
+ Presione para definir la salida del teclado
+
+
+ Aumentar el límite de potencia térmica (TDP)
+
+
+ Aumente el TDP del sistema o del perfil actualmente aplicado en 1W
+
+
+ Controlador de pantalla 3D
+
+
+ Cambie la tecla de acceso rápido 3D presionando un botón o una tecla especial
+
+
+ Mostrar trackpads virtuales
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Abrir ventana de herramientas rápidas
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Acceso directo personalizado
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Mostrar y ocultar el escritorio
+
+
+ Presiona esta tecla: Windows + D
+
+
+ Esc
+
+
+ Presiona la tecla: Esc
+
+
+ Cambia entre ventana y pantalla completa
+
+
+ Presiona la tecla: Enter
+
+
+ Boton Guia o Boton PS
+
+
+ Simular boton Xbox Guia o boton Sony PS
+
+
+ Mostrar teclado
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Forzar el cierre de la aplicación
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Mostrar y ocultar la menú principal
+
+
+ Cambie la tecla de acceso rápido presionando un botón o una tecla especial
+
+
+ Abrir administrador de tareas
+
+
+ Presiona las teclas: Ctrl + Shift + Esc
+
+
+ Abrir vista de tareas
+
+
+ Pulsa las teclas: Windows + Tab
+
+
+ Toggle Suspender
+
+
+ Suspender o reanudar la aplicación en primer plano
+
+
+ Handheld Companion
+
+
+ Acerca de
+
+
+ Mando
+
+
+ Superposicion
+
+
+ Perfiles
+
+
+ OK
+
+
+ Opciones
+
+
+ 8BitDo Lite 2
+
+
+ Alineación
+
+
+ Cambiar la alineación de la superposición del controlador 3D
+
+
+ Cambiar la alineación de la superposición de los trackpads
+
+
+ Siempre arriba
+
+
+ Cuando se activa, la superposición del controlador 3D se sobrepondrá encima de otras ventanas
+
+
+ Atras
+
+
+ Reconocimiento facial
+
+
+ Cambie el comportamiento del modelo de superposición del controlador 3D para mirar hacia la cámara
+
+
+ Inmovilizar angulo de la camara
+
+
+ Cambiar el ángulo, en grados
+
+
+ Color de fondo
+
+
+ Cambiar el color de fondo de la superposición del controlador 3D
+
+
+ Opciones del Mando
+
+
+ PlayStation DualSense
+
+
+ Emulacion mando
+
+
+ Camara facial
+
+
+ El modelo 3D gira lentamente para mirar a la cámara como posición predeterminada
+
+
+ Escuchando...
+
+
+ MACHENIKE HG510
+
+
+ Gatillo Principal
+
+
+ Cambiar el gatillo principal de superposición del mando 3D
+
+
+ Movimiento
+
+
+ El modelo se moverá de acuerdo con los movimientos del usuario según la información del sensor
+
+
+ N64
+
+
+ Controlador OEM
+
+
+ Opacidad
+
+
+ Cambiar la opacidad de superposición del mando 3D
+
+
+ Cambiar la opacidad de la superposición de los trackpads
+
+
+ Sobreposicion
+
+
+ Modelo de sobreposicion
+
+
+ Cambiar el modelo de sobreposicion del mando 3D
+
+
+ Vista previa sobreposicion
+
+
+ Configuración de procesamiento
+
+
+ Anti-Aliasing
+
+
+ Cambiar el estado del suavizado de renderizado
+
+
+ Cambie la configuración de procesamiento de su modelo de mando de superposición 3D
+
+
+ Frecuencia de actualización
+
+
+ Cambiar la tasa de actualización de procesamiento, en actualización por segundo
+
+
+ Tamaño
+
+
+ Cambiar el tamaño de superposición del mando 3D
+
+
+ Cambiar el tamaño de superposición de los trackpads
+
+
+ Start
+
+
+ Controlador de Fisher-Price
+
+
+ Opciones de Trackpads
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ Superponer
+
+
+ Reanudar
+
+
+ Suspender
+
+
+ Opciones adicionales
+
+
+ Multiplicador de movimiento apuntando hacia abajo
+
+
+ Boton de activación
+
+
+ Un multiplicador de sensibilidad de movimiento adicional al apuntar hacia abajo o el alcance mediante el uso del botón de activación configurado
+
+
+ Valor multiplicador
+
+
+ Opciones de camara
+
+
+ Curva de respuesta personalizada
+
+
+ Salida enviada al juego
+
+
+ Intensidad de movimiento
+
+
+ Agresivo
+
+
+ Por defecto
+
+
+ Opciones preestablecidas
+
+
+ Precisa
+
+
+ Duración del movimiento
+
+
+ Cambie la duración del movimiento rápido, calibre a un giro de 180 grados, en milisegundos
+
+
+ Flick stick (experimental)
+
+
+ Apunte la cámara en la dirección del movimiento del joystick (derecho), gire la cámara puramente en el plano horizontal girando
+
+
+ Habilitar dispositivo móvil
+
+
+ Sensibilidad
+
+
+ Cambiar la sensibilidad de movimiento del eje horizontal y vertical
+
+
+ Sensibilidad X
+
+
+ Cambiar la sensibilidad de movimiento del eje horizontal
+
+
+ Sensibilidad Y
+
+
+ Cambiar la sensibilidad de movimiento del eje vertical
+
+
+ Sensibilidad del stick
+
+
+ Cambiar la sensibilidad de movimiento del eje vertical
+
+
+ Opciones adicionales
+
+
+ Zona muerta
+
+
+ Cambia la zona muerta de la dirección, en grados. Mejora la dirección recta
+
+
+ Joystick game Input
+
+
+ Dirección con joystick
+
+
+ Opciones de dirección con joystick
+
+
+ Vista previa de la dirección con joystick
+
+
+ Ángulo de dirección máximo
+
+
+ Cambiar el valor máximo del ángulo de dirección, en grados
+
+
+ Linealidad de dirección
+
+
+ Mapeo entre entrada y dirección. Los valores más bajos proporcionan más precisión cerca del enganche completo pero menos precisión cerca del centro. Los valores más altos proporcionan más precisión cerca del centro pero menos precisión cerca del enganche completo. 1.0 es un mapeo lineal
+
+
+ Multiplicador de acelerómetro
+
+
+ Cambiar el valor del acelerómetro informado por el sistema
+
+
+ Opciones adicionales
+
+
+ Anti-zona muerta
+
+
+ Cambiar la anti-zona muerta del juego, en porcentaje
+
+
+ %
+
+
+ Estás seguro de que quieres eliminar?
+
+
+ Este artículo será eliminado inmediatamente. No puede deshacer esta acción.
+
+
+ Estás seguro de que quieres sobrescribir este perfil?
+
+
+ {0} se sobrescribirá. No puede deshacer esta acción.
+
+
+ Aumento del limite de potencia
+
+
+ Cambiar el límite de potencia térmica de impulso
+
+
+ Cancelar
+
+
+ Crear un nuevo perfil
+
+
+ Eliminar
+
+
+ Eliminar perfil
+
+
+ Perfil de usuario por juego
+
+
+ El perfil se aplicará automáticamente cuando se detecte la aplicación asociada
+
+
+ Opciones globales
+
+
+ Cambiar la configuración de perfiles globales
+
+
+ Multiplicador de girómetro
+
+
+ Cambiar el valor del girómetro informado por el sistema
+
+
+ Eje de dirección del giroscopio
+
+
+ Para controlar el movimiento horizontal del controlador,puede usar el eje de yaw o balanceo
+
+
+ Invertir el eje horizontal
+
+
+ Invertir el eje vertical
+
+
+ Ajustes de control de movimiento
+
+
+ Cambiar la configuración de control de movimiento global
+
+
+ OK
+
+
+ configuración de energía
+
+
+ Cambiar la configuración de energía
+
+
+ Detalles del perfil
+
+
+ Nombre del perfil
+
+
+ Ruta del perfil
+
+
+ Perfiles
+
+
+ Seleccion de perfil
+
+
+ Selecciona el perfil que quieres modificar
+
+
+ Detalles del perfil
+
+
+ Perfil actualizado
+
+
+ Fue actualizado
+
+
+ Balanceo
+
+
+ X
+
+
+ Y
+
+
+ Estilo de entrada
+
+
+ Las entradas físicas del controlador se pueden programar para actuar como diferentes tipos de dispositivos
+
+
+ Dispositivo de salida
+
+
+ Seleccione el dispositivo que recibirá los comandos de movimiento
+
+
+ Límite de potencia sostenida
+
+
+ Cambiar límite de potencia térmica sostenida
+
+
+ Límite de potencia térmica (TDP)
+
+
+ Limita la potencia del procesador para reducir la potencia total
+
+
+ Habilitar controlador de movimiento universal
+
+
+ Deshabilitado, encender con botón(es)
+
+
+ Habilitado, apaga con botón(es)
+
+
+ Activación de movimiento
+
+
+ Compensa la zona muerta del juego, mejora el registro de pequeños movimientos
+
+
+ Seleccione el dispositivo que recibirá los comandos de movimiento
+
+
+ Ajustes de control de movimiento universal
+
+
+ Traducir los movimientos del dispositivo en entradas del controlador
+
+
+ Actualización del perfil
+
+
+ Permitir que la aplicación acceda al controlador físico del dispositivo
+
+
+ Compatibilidad extendida (XInputPlus)
+
+
+ Yaw
+
+
+ Si
+
+
+ Desconectar
+
+
+ Control manual del reloj de la GPU
+
+
+ Establece la GPU en un reloj fijo
+
+
+ MHz
+
+
+ Modo de energia
+
+
+ Equilibrado
+
+
+ Optimice su dispositivo según el uso de energía y el rendimiento
+
+
+ Eficiencia
+
+
+ Rendimiento
+
+
+ Aumentar
+
+
+ Límite de potencia térmica (TDP)
+
+
+ Limita la potencia del procesador para reducir la potencia total
+
+
+ El límite de potencia térmica se sobrescribe con un perfil
+
+
+ Sostenido
+
+
+ W
+
+
+ Crear perfil
+
+
+ Esperando el proceso de primer plano...
+
+
+ Brinda soporte de giroscopio y acelerómetro a las computadoras de juegos portátiles de Windows a través de un controlador virtual. Si el servicio está habilitado, el controlador incorporado se ocultará a las aplicaciones fuera de la lista blanca. Si el servicio está deshabilitado, el controlador integrado se desenmascarará y el controlador virtual se deshabilitará.
+
+
+ Servicio del controlador
+
+
+ Idioma
+
+
+ Idioma de la aplicacion
+
+
+ Reinicio necesario
+
+
+ Para que los cambios surtan efecto, por favor reinicie la aplicación
+
+
+ Tema de la aplicacion
+
+
+ Tema de aplicacion, oscuro o claro
+
+
+ Auto-inicio de la aplicacion
+
+
+ La aplicacion iniciara al iniciar windows
+
+
+ Aplicacion de fondo
+
+
+ Acrilico
+
+
+ El fondo de la aplicación, ninguno, mica, tabulado, acrílico
+
+
+ Mica
+
+
+ Ninguno
+
+
+ Pestañas
+
+
+ Buscar actualizaciones
+
+
+ Cerrar, minimiza el programa
+
+
+ La aplicación se minimizará en lugar de cerrarse
+
+
+ Habilitar perfil de escritorio al inicio
+
+
+ El perfil de escritorio se habilitará automáticamente al iniciar la aplicación
+
+
+ Descargar
+
+
+ Descargando
+
+
+ Eficiencia inteligente
+
+
+ El modo de eficiencia inteligente reduce la prioridad de los procesos en segundo plano y mejora la eficiencia energética
+
+
+ Opciones generales
+
+
+ Instalar ahora
+
+
+ Ultima comprobación:
+
+
+ Opciones de notificación
+
+
+ Abrir aplicacion en segundo plano
+
+
+ La aplicación inicialmente comenzará minimizada y aparecerá en la barra de tareas
+
+
+ Externo
+
+
+ Interno
+
+
+ Opciones del sensor
+
+
+ Dirección de colocación del sensor externo
+
+
+ Seleccione en qué lado del dispositivo se ha montado el sensor
+
+
+ Sensor externo al revés
+
+
+ El sensor se ha montado al revés, posible con convertidor USB-C
+
+
+ Seleccion de sensores
+
+
+ Seleccione el sensor deseado utilizado para la entrada de movimiento
+
+
+ Opciones
+
+
+ Tipo de inicio
+
+
+ Utilizado por el administrador de servicios para definir el tipo de inicio del servicio
+
+
+ Maximo poder
+
+
+ La potencia máxima en vatios suministrada al procesador
+
+
+ Poder minimo
+
+
+ La potencia mínima en vatios suministrada al procesador
+
+
+ Anulación de potencia configurable (cTDP)
+
+
+ Permite modificar los valores mínimo y máximo de potencia (TDP) más allá de las especificaciones de la CPU
+
+
+ Oscuro
+
+
+ Claro
+
+
+ Notificacion flotante
+
+
+ Recibe notificaciones de la aplicación en el centro de acción de Windows
+
+
+ Actualizaciones disponibles
+
+
+ Comprobando actualizaciones...
+
+
+ No pudimos descargar el archivo de actualización.
+
+
+ No se pudo acceder a Github
+
+
+ No pudimos localizar el archivo de actualización.
+
+
+ Ups. Hubo un problema
+
+
+ Esta todo actualizado
+
+
+ El controlador ahora está oculto y las entradas se reenvían al controlador virtual
+
+
+ Usuario
+
+
+ Ejecute esta herramienta como administrador para desbloquear esta configuración
+
+
+ ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+
+ Silenciar controlador virtual
+
+
+ Silenciar el controlador virtual en aplicaciones relacionadas con Steam
+
+
+ Opciones del mando
+
+
+ Cambiar la configuración del mando virtual
+
+
+ Movimiento anti-zona muerta
+
+
+ Compensa la zona muerta del juego, mejora el registro de pequeños movimientos
+
+
+ ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Mejorar la circularidad de el stick.
+
+
+ Circularidad stick izquierdo
+
+
+ Circularidad stick derecho
+
+
+ Joystick zona muerta % izquierdo
+
+
+ Ajuste el porcentaje de zona muerta interior y exterior del joystick izquierdo
+
+
+ Joystick zona muerta % derecho
+
+
+ Ajuste el porcentaje de zona muerta interior y exterior del joystick derecho
+
+
+ Gatillo izquierdo deadzone %
+
+
+ Ajuste el porcentaje de zona muerta interior y exterior del gatillo izquierdo
+
+
+ Gatillo derecho deadzone %
+
+
+ Ajuste el porcentaje de zona muerta interior y exterior del gatillo derecho
+
+
+ Controlador de vibración al conectar
+
+
+ Vibración del mando cuando esta conectado
+
+
+ Diseño de escritorio
+
+
+ Cambiar el diseño del controlador de escritorio
+
+
+ Mostrar Centro de acción
+
+
+ Mostrar y ocultar Centro de acción de Windows
+
+
+ Disposicion del mando
+
+
+ Anulación del ventilador
+
+
+ Establezca el ciclo de trabajo del ventilador en un valor definido por el usuario
+
+
+ Visualización en pantalla
+
+
+ Habilitar soporte de visualización en pantalla
+
+
+ Reducir el brillo
+
+
+ Reducir el brillo de la pantalla actual en un 5%
+
+
+ Reducir volumen
+
+
+ Reducir el volumen del sistema en un 5%
+
+
+ Aumentar brillo
+
+
+ Aumentar el brillo de la pantalla actual en un 5%
+
+
+ Aumentar volumen
+
+
+ Aumentar volumen actual en un 5%
+
+
+ TDP Automático
+
+
+ Ajuste automático de TDP basado en FPS medido y objetivo de FPS solicitado
+
+
+ FPS objetivo
+
+
+ Valor objetivo de FPS deseado para el controlador TDP automático
+
+
+ GPU Clock maxima frecuencia
+
+
+ Velocidad máxima de reloj de la GPU en Mhz
+
+
+ FPS
+
+
+ Nivel de visualización de sobreposicion
+
+
+ Cambiar el nivel de visualización de la información en pantalla
+
+
+ Frecuencia de actualización
+
+
+ Cambiar la frecuencia de actualización de visualización en pantalla
+
+
+ Limite de FPS
+
+
+ Limite de FPS para aplicaciones 3D
+
+
+ Abra la herramienta Recortes
+
+
+ Presiona las teclas: Windows + Shift
+
+
+ Teclas acceso rapido
+
+
+ Usar la configuración del sistema
+
+
+ Aplicaciones de terceros
+
+
+ Exportar disposicion
+
+
+ No se detectó ningún controlador físico
+
+
+ Exportar para el controlador actual
+
+
+ Es posible que desee iniciar el servicio complementario o asegurarse de que el estado de su controlador virtual esté configurado en: Conectado
+
+
+ Dpad
+
+
+ Su controlador físico está oculto, pero no tiene ningún controlador virtual disponible. No se enviarán entradas a los juegos.
+
+
+ No se detectó ningún controlador virtual
+
+
+ Confirmar
+
+
+ Comunidad
+
+
+ Es posible que desee activar el silencio de su controlador virtual o mostrar su controlador físico.
+
+
+ Cancelar
+
+
+ Su controlador físico está oculto, pero ha silenciado su controlador virtual.
+
+
+ Botones
+
+
+ Aplicar plantilla
+
+
+ El controlador físico está oculto.
+
+
+ Es posible que desee ocultar su controlador físico o silenciar su controlador virtual.
+
+
+ Su controlador físico no está oculto, pero tiene un controlador virtual activado. Es posible que encuentres entradas dobles en los juegos.
+
+
+ El controlador físico no está oculto.
+
+
+ Opciones del controlador
+
+
+ Girómetro
+
+
+ Asegúrese de haber conectado un dispositivo XInput o DInput compatible.
+
+
+ Autor de el diseño
+
+
+ Socio
+
+
+ Fabricante
+
+
+ Nombre del producto
+
+
+ Trackpads
+
+
+ No hay ningún controlador físico conectado
+
+
+ Diseño de escritorio
+
+
+ Definir el diseño de escritorio
+
+
+ Definir el diseño del controlador cuando esté en modo de escritorio
+
+
+ Editar
+
+
+ Plantillas
+
+
+ Habilitar diseño de escritorio
+
+
+ Selector de plantilla de diseño
+
+
+ Diseños de controladores que no son de juegos
+
+
+ Mostrar solo las plantillas de controlador actuales
+
+
+ Guardar información del juego con el diseño.
+
+
+ Título del diseño
+
+
+ Es posible que desees hacer clic en Conectar junto a tu controlador conectado.
+
+
+ Descripción del diseño
+
+
+ No tienes ningún controlador físico conectado. No se enviarán insumos a HC ni a su servicio.
+
+
+ Joysticks
+
+
+ Vibración HD
+
+
+ JOYSTICK IZQUIERDO
+
+
+ BOTONES JOYSTICK IZQUIERDO
+
+
+ Ocultar automáticamente herramientas rápidas cuando el usuario hace click fuera de la ventana
+
+
+ Ocultar cuando pierde el foco
+
+
+ Objetivo de límite de potencia
+
+
+ Por defecto
+
+
+ JOYSTICK DERECHO
+
+
+ PAD DIRECCIONAL
+
+
+ Perfil Actual:
+
+
+ Establezca el ciclo de trabajo del ventilador en un valor definido por el usuario
+
+
+ Anulación del ventilador
+
+
+ Resolución de pantalla y frecuencia de actualización
+
+
+ Establecer modo de refuerzo de CPU actual
+
+
+ Modo de refuerzo de CPU
+
+
+ No establecido
+
+
+ %
+
+
+ Detectar
+
+
+ OEM
+
+
+ BUMPERS
+
+
+ Desactiva automáticamente RTSS cuando HC está cerrado
+
+
+ RivaTuner Statistics Server
+
+
+ Parte superior derecha
+
+
+ Parte superior izquierda
+
+
+ Definir la ubicación de la ventana de herramientas rápidas
+
+
+ Parte inferior derecha
+
+
+ Parte inferior izquierda
+
+
+ MENU
+
+
+ Ubicación de la ventana
+
+
+ Opciones de herramientas rápidas
+
+
+ Fondo de herramientas rápidas, none, mica, tabbed, acrylic
+
+
+ Opciones de energía
+
+
+ A,B,X,Y
+
+
+ CONTROLES TRASEROS
+
+
+ Ninguno
+
+
+ Algunas funciones dependen de conocer la orientación de la pantalla nativa para funcionar correctamente. Si esto no se detectó correctamente, configure la orientación de su pantalla en la orientación que coincida con su controlador, luego haga clic en Detectar
+
+
+ Ajustar la resolución de la pantalla principal y la frecuencia de actualización
+
+
+ Objetivo de límite de potencia
+
+
+ ms
+
+
+ BOTONES GATILLO DERECHO
+
+
+ Gatillos
+
+
+ Orientación de pantalla nativa
+
+
+ Desactivado
+
+
+ Extendido
+
+
+ BOTONES GATILLO IZQUIERDO
+
+
+ BOTONES JOYSTICK DERECHOS
+
+
+ TRACKPAD IZUIERDO
+
+
+ BOTONES TRACKPAD IZQUIERDO
+
+
+ TRACKPAD DERECHO
+
+
+ GPU
+
+
+ GATILLO DERECHO
+
+
+ BOTONES TRACKPAD DERECHO
+
+
+ Especifica la política de distribución de energía entre CPU y GPU.
+
+
+ Equilibrio de potencia CPU/GPU
+
+
+ Utilice un motor de vibración de alta definición, a costa de un mayor uso de CPU
+
+
+ Preferencia de rendimiento energético (EPP)
+
+
+ GATILLO IZQUIERDO
+
+
+ CPU
+
+
+ Completo
+
+
+ Cambiar el diseño del controlador virtual
+
+
+ Mínimo
+
+
+ Esta entrada funcionará como un simple joystick. Ideal para portátiles y dispositivos de mano tipo clamshell, cambio automático de balanceo de guiñada en función de cómo se sostenga el dispositivo (90 o 180 grados abiertos).
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Equis
+
+
+ Circulo
+
+
+ Cuadrado
+
+
+ Triangulo
+
+
+ Share
+
+
+ Sony
+
+
+ Opciones
+
+
+ Controlador DualShock 4 emulado
+
+
+ Sin controlador emulado
+
+
+ Controlador XBOX 360 emulado
+
+
+ Conectado
+
+
+ Desconectado
+
+
+ Auto Roll Yaw Swap
+
+
+ Cámara con joystick
+
+
+ Dirección con joystick
+
+
+ Espacio del jugador
+
+
+ Handheld Companion
+
+
+ Sobreposicion
+
+
+ Herramientas rápidas
+
+
+ Windows
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ Vista
+
+
+ Menu
+
+
+ Joystick izquierdo
+
+
+ Joystick derecho
+
+
+ Este es su perfil de controlador predeterminado. Este perfil se aplicará a todas tus aplicaciones que no tengan un perfil específico. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
+
+
+ Ups. Parece que este perfil no tiene un ejecutable. Como es esto posible?
+
+
+ Ups. Parece que este perfil no tiene una ruta a la aplicación. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
+
+
+ Ups. Parece que no tienes el nivel de permiso necesario para modificar el contenido de esta aplicación. Asegúrese de haber iniciado este programa en modo administrador.
+
+
+ Nada que ver aqui.
+
+
+ Ups. Parece que este perfil ejecutable se está ejecutando. Algunas opciones que requieren un ejecutable pueden estar deshabilitadas.
+
+
+ Por defecto
+
+
+ Eco
+
+
+ Alta
+
+
+ Automático
+
+
+ Desactivado
+
+
+ Manual
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ Vista
+
+
+ LB
+
+
+ RB
+
+
+ Guide
+
+
+ Menu
+
+
+ Esta entrada funcionará como un simple joystick. Esto está diseñado para aplicaciones de joystick tradicionales.
+
+
+ Esta entrada funcionará como un joystick optimizado para controlar un volante o un juego de carreras.
+
+
+ Esta entrada funcionará como un joystick optimizado para controlar una cámara en primera o tercera persona
+
+
+ Handheld Companion
+
+
+ Opciones
+
+
+ STEAM
+
+
+ Command center
+
+
+ Armory crate
+
+
+ M1
+
+
+ Right Thumb Down
+
+
+ Right Thumb Left
+
+
+ Right Thumb Right
+
+
+ Right Thumb Up
+
+
+ A
+
+
+ Siempre encendido
+
+
+ B
+
+
+ Atrás
+
+
+ Right Thumb
+
+
+ DPad Abajo
+
+
+ DPad Derecho
+
+
+ DPad Arriba
+
+
+ Shoulder izquierdo
+
+
+ Thumb izquierdo
+
+
+ Gatillo izquierdo
+
+
+ Shoulder Derecho
+
+
+ Thumb Derecho
+
+
+ Gatillo Derecho
+
+
+ DPad Izquierda
+
+
+ R5
+
+
+ R4
+
+
+ R3
+
+
+ B7
+
+
+ B8
+
+
+ DPad Abajo
+
+
+ DPad Izquierda
+
+
+ DPad Derecha
+
+
+ DPad Arriba
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Thumb Izquierdo
+
+
+ Left Thumb Down
+
+
+ Left Thumb Left
+
+
+ Left Thumb Right
+
+
+ Left Thumb Up
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ R2
+
+
+ Start
+
+
+ X
+
+
+ Y
+
+
+ Ups. Parece que este perfil se está ejecutando. Algunas opciones que requieren un ejecutable pueden estar desactivadas.
+
+
+ B6
+
+
+ B5
+
+
+ R2
+
+
+ Thumb Derecho
+
+
+ Esc
+
+
+ KB
+
+
+ Personalizado
+
+
+ Dispositivo
+
+
+ Joystick Cámara
+
+
+ Joystick de dirección
+
+
+ Espacio de jugador
+
+
+ Stick izquierdo
+
+
+ Stick derecho
+
+
+ L2
+
+
+ Thumb izquierdo
+
+
+ Auto Roll Yaw Swap
+
+
+ Win
+
+
+ Deslizar con una sola pulsación
+
+
+ Deslizamiento multitáctil
+
+
+ Clic con un solo toque
+
+
+ Toque único
+
+
+ Clic multitáctil
+
+
+ Multitoque
+
+
+ Deslizar con una sola pulsación
+
+
+ Deslizamiento multitáctil
+
+
+ Equis
+
+
+ Circulo
+
+
+ Cuadrado
+
+
+ Triángulo
+
+
+ Compartir
+
+
+ Clic con un solo toque
+
+
+ Toque sencillo
+
+
+ Click multitáctil
+
+
+ Multitoque
+
+
+ Sony
+
+
+ Opciones
+
+
+ A
+
+
+ Alt
+
+
+ Apóstrofe
+
+
+ B
+
+
+ Barra invertida
+
+
+ Retroceso
+
+
+ C
+
+
+ Coma
+
+
+ Control
+
+
+ D
+
+
+ Eliminar
+
+
+ E
+
+
+ Fin
+
+
+ Intro
+
+
+ Igual
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Inicio
+
+
+ I
+
+
+ Insertar
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Menos
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Período
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Punto y coma
+
+
+ Mayus
+
+
+ Barra
+
+
+ Espacio
+
+
+ T
+
+
+ Tabulador
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ Stick izquierdo
+
+
+ Mover el cursor
+
+
+ Stick Derecho
+
+
+ Rueda Ratón
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Menos
+
+
+ L
+
+
+ R
+
+
+ Inicio
+
+
+ Captura
+
+
+ Además
+
+
+ Stick Izquierdo
+
+
+ Stick Derecho
+
+
+ Sí
+
+
+ No
+
+
+ Es posible que la mejora de la detección del controlador virtual no funcione si cierras Handheld Companion. ¿Está seguro?
+
+
+ Aviso
+
+
+ Desactivado
+
+
+ Inyección (recomendado)
+
+
+ Redirección
+
+
+ Mejorar la detección de controladores virtuales
+
+
+ Obliga al controlador virtual a ser detectado como primer controlador durante el inicio de Windows. Actívalo si tu aplicación/juego no detecta tus entradas (requiere reiniciar el dispositivo).
+
+
+ Sí
+
+
+ No
+
+
+ Es necesario reiniciar el dispositivo para que los cambios surtan efecto. ¿Quieres reiniciar ahora?
+
+
+ Reinicio requerido
+
+
+ Sí
+
+
+ No
+
+
+ Si desactiva esta opción, también desactivará "Mejorar la detección de controladores virtuales". ¿Desea continuar?
+
+
+ Aviso
+
+
+ Conectar
+
+
+ Desconectar
+
+
+ Mostrar
+
+
+ Virtual
+
+
+ Ocultar
+
+
+ Atras
+
+
+ Salir
+
+
+ Ventana principal
+
+
+ Navegar
+
+
+ Herramientas rápidas
+
+
+ Selecciona
+
+
+ Externo
+
+
+ ¿Está seguro de que desea aplicar esta plantilla? Se anularán todos los ajustes de diseño.
+
+
+ No se puede deshacer esta acción. Plantilla aplicada anteriormente: {0}
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.fr-FR.resx b/HandheldCompanion/Properties/Resources.fr-FR.resx
index 3c0ba852d..82d8b9989 100644
--- a/HandheldCompanion/Properties/Resources.fr-FR.resx
+++ b/HandheldCompanion/Properties/Resources.fr-FR.resx
@@ -1,2350 +1,2344 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- À propos
-
-
- Handheld Companion fournit une prise en charge du gyroscope et de l'accéléromètre aux modèles AYA NEO 2020 et 2021 par le biais d'un contrôleur DualShock 4 virtuel. Si le service est activé, le contrôleur intégré sera masqué pour les applications en dehors de la liste blanche. Si le service est désactivé, le contrôleur intégré ne sera pas masqué et le contrôleur DualShock 4 virtuel sera désactivé. Handheld Companion s'appuie sur le pilote ViGEmBus et les bibliothèques ViGEmClient ainsi que sur le pilote de filtre en mode noyau HidHide. Les algorithmes de contrôle de mouvement sont basés sur le travail de Jibbsmart et les informations disponibles sur le GyroWiki.
-
-
- Accéléromètre
-
-
- Auteur
-
-
- Contributeurs
-
-
- Description
-
-
- Faire un don
-
-
- Gyromètre
-
-
- Inclinomètre
-
-
- N/A
-
-
- Liens connexes
-
-
- Nom du capteur
-
-
- Spécification du capteur
-
-
- Service
-
-
- Code source
-
-
- Version
-
-
- Wiki
-
-
- Administrateur
-
-
- Masquer le contrôleur physique
-
-
- Modifier la visibilité du contrôleur physique pour les autres applications
-
-
- Connecter
-
-
- Controller
-
-
- Contrôleur
-
-
- Déconnecter
-
-
- Dispositifs d'entrée
-
-
- Dévoiler à la fermeture
-
-
- Rétablissement de la visibilité des contrôleurs physique pour les autres applications à l'arrêt du service
-
-
- Force de vibration
-
-
- Modification de la force de vibration du contrôleur
-
-
- Handheld Companion
-
-
- À propos
-
-
- Contrôleur
-
-
- Overlay
-
-
- Profils
-
-
- OK
-
-
- Paramètres
-
-
- Alignement
-
-
- Modifier l'alignement du contrôleur
-
-
- Modifier l'alignement des trackpads
-
-
- Retour
-
-
- Stationary pitch
-
-
- Change the angle, in degree
-
-
- Options du contrôleur
-
-
- Contrôleur émulé
-
-
- Face camera
-
-
- 3D Model slowly rotates to face camera as default position
-
-
- Déclencheur principal
-
-
- Modifier le déclencheur principal
-
-
- Contrôleur OEM
-
-
- Opacité
-
-
- Modifier l'opacité des trackpads
-
-
- Overlay
-
-
- Modèle du contrôleur
-
-
- Modifier le modèle du contrôleur
-
-
- Aperçu de l'overlay
-
-
- Taille
-
-
- Modifier la taille du contrôleur
-
-
- Modifier la taille des trackpads
-
-
- Menu
-
-
- Options des trackpads
-
-
- ZD O+
-
-
- Overlay
-
-
- Paramètres supplémentaires
-
-
- Options de la caméra
-
-
- Courbe de réponse personnalisée
-
-
- Commande envoyée au jeu
-
-
- Intensité du mouvement
-
-
- Agressif
-
-
- Défaut
-
-
- Options de préréglage
-
-
- Précis
-
-
- Durée du mouvement
-
-
- Modifier la durée du mouvement, calibrée à un virage de 180 degrés, en millisecondes
-
-
- Flick stick (expérimental)
-
-
- Pointer la caméra dans la direction du mouvement du joystick droit, faites pivoter la caméra purement dans le plan horizontal en tournant le joystick
-
-
- Activer flick stick
-
-
- Sensibilité
-
-
- Modifier la sensibilité au mouvement de l'axe horizontal et vertical
-
-
- Sensibilité du joystick
-
-
- Modifier la vitesse de rotation
-
-
- Paramètres supplémentaires
-
-
- Zone morte
-
-
- Modifier la zone morte de la direction, en degré. Améliore la rectitude de la direction
-
-
- Entrée de jeu par joystick
- // not good
-
-
- Direction par joystick
-
-
- Options de direction par joystick
-
-
- Aperçu de la direction par joystick
-
-
- Angle de braquage maximal
-
-
- Modifier la valeur maximale de l'angle de braquage, en degrés
-
-
- Linéarité de la direction
-
-
- Correspondance entre les commandes du joystick et la direction. Les valeurs les plus basses fournissent plus de précision près du braquage complet mais moins de précision près du centre. Des valeurs plus élevées fournissent plus de précision près du centre mais moins de précision près du braquage maximum
-
-
- Multiplicateur de l'accéléromètre
-
-
- Modifier la valeur de l'accéléromètre rapportée par le système
-
-
- Paramètres supplémentaires
-
-
- Anti-zone morte
-
-
- Modifier l'anti-zone morte, en pourcentage
-
-
- Êtes-vous sûr de vouloir supprimer?
-
-
- Cet élément sera supprimé immédiatement. Vous ne pouvez pas annuler cette action.
-
-
- Etes-vous sûr de vouloir écraser?
-
-
- Cet élément sera écrasé. Vous ne pouvez pas annuler cette action.
-
-
- Annuler
-
-
- Créer un nouveau profil
-
-
- Supprimer
-
-
- Supprimer le profil
-
-
- Activer le profil
-
-
- Le profil sera automatiquement appliqué lorsque l'application associée sera détectée
-
-
- Paramètres globaux
-
-
- Modifier les paramètres des profils globaux
-
-
- Multiplicateur du gyromètre
-
-
- Modifier la valeur du gyromètre rapportée par le système
-
-
- Axe de direction du gyroscope
-
-
- Pour contrôler le mouvement horizontal du contrôleur, vous pouvez utiliser l'axe de lacet ou de roulis
-
-
- Inverser l'axe horizontal
-
-
- Inverser l'axe vertical
-
-
- Paramètres de contrôle du mouvement
-
-
- Modifier les paramètres globaux de contrôle du mouvement
-
-
- OK
-
-
- Détails du profil
-
-
- Nom du profil
-
-
- Chemin du profil
-
-
- Profils
-
-
- Sélection du profil
-
-
- Sélectionner le profil que vous souhaitez modifier
-
-
- Paramètres du profil
-
-
- Profil mis à jour
-
-
- a été mis à jour.
-
-
- Roulis
-
-
- Style d'entrée
-
-
- Les entrées physiques du contrôleur peuvent être programmées pour agir comme différents types de dispositifs
-
-
- Dispositif de sortie
-
-
- Sélectionner le dispositif qui recevra les commandes de mouvement
-
-
- Activer le contrôle universel de mouvements
-
-
- Disabled, turn on with button(s)
-
-
- Enabled, turn off with button(s)
-
-
- Motion activation
-
-
- With motion input disabled, use selected button(s) to enable motion,
-with motion input enabled, use selected button(s) to disable motion.
-
-
- Sélectionner le dispositif qui recevra les commandes de mouvement
-
-
- Paramètres du contrôle universel de mouvements
-
-
- Traduire les mouvements du dispositif en entrées du contrôleur
-
-
- Mettre à jour le profil
-
-
- Autoriser l'application à accéder au contrôleur physique du dispositif
-
-
- Compatibilitée améliorée (XInputPlus)
-
-
- Lacet
-
-
- Oui
-
-
- Fournit une prise en charge du gyroscope et de l'accéléromètre aux ordinateurs de jeu portables Windows par le biais d'un contrôleur virtuel. Si le service est activé, le contrôleur intégré sera masqué pour les applications en dehors de la liste blanche. Si le service est désactivé, le contrôleur embarqué ne sera plus caché et le contrôleur virtuel sera désactivé.
-
-
- Controller Service
-
-
- Langue
-
-
- La langue de l'application
-
-
- Redémarrage nécessaire
-
-
- Pour que les modifications soient prises en compte, veuillez redémarrer l'application
-
-
- Thème de l'application
-
-
- Le thème de l'application, mode clair ou foncé
-
-
- Démarrage automatique de l'application
-
-
- L'application démarre automatiquement lorsque je me connecte à Windows
-
-
- Vérifier les mises à jour
-
-
- Fermer l'application la réduira
-
-
- L'application sera réduite au lieu d'être fermée
-
-
- Téléchargement -
-
-
- Options générales
-
-
- Installer maintenant
-
-
- Dernière vérification:
-
-
- Options de notification
-
-
- Ouvrir l'application en arrière-plan
-
-
- L'application démarre initialement réduite et apparaît dans la barre des tâches
-
-
- Sensor options
- Translate
-
-
- External sensor placement direction
- Translate
-
-
- Select on which side of the device the senor has been mounted
- Translate
-
-
- External sensor upside down
- Translate
-
-
- Sensor has been mounted upside down, possible with USB-C convertor
- Translate
-
-
- Sensor selection
- Translate
-
-
- Select the desired sensor used for motion input
- Translate
-
-
- Paramètres
-
-
- Type de démarrage
-
-
- Utilisé par le gestionnaire du service pour définir le type de démarrage du service
-
-
- Foncé
-
-
- Clair
-
-
- Notification toast
-
-
- Obtenir des notifications de l'application dans le centre d'action Windows
-
-
- Mises à jour disponibles
-
-
- Vérification des mises à jour...
-
-
- Vous êtes à jour
-
-
- Le contrôleur est maintenant masqué et les entrées sont transmises au contrôleur virtuel
-
-
- Utilisateur
-
-
- Exécutez cet outil en tant qu'administrateur pour déverrouiller ces paramètres
-
-
- External
-
-
- Internal
-
-
- Decrease thermal power limit (TDP)
-
-
- Decrease system or currently applied profile TDP by one watt
-
-
- Press to define hotkey input
-
-
- Press to define keyboard output
-
-
- Increase thermal power limit (TDP)
-
-
- Increase system or currently applied profile TDP by one watt
-
-
- Display 3D controller
-
-
- Change 3D hotkey by pressing a button or a special key
-
-
- Display virtual trackpads
-
-
- Change hotkey by pressing a button or a special key
-
-
- Summon quick tools window
-
-
- Change hotkey by pressing a button or a special key
-
-
- Custom shortcut
-
-
- Change hotkey by pressing a button or a special key
-
-
- Display and hide the desktop
-
-
- Press this key: Windows + D
-
-
- Exit
-
-
- Press this key: Escape
-
-
- Switches between window and full screen
-
-
- Press this key: Alt + Enter
-
-
- Guide or PS button
-
-
- Simulate a Xbox Guide or Sony PS button input
-
-
- Display touch keyboard
-
-
- Change hotkey by pressing a button or a special key
-
-
- Display and hide main window
-
-
- Change hotkey by pressing a button or a special key
-
-
- Open Task Manager
-
-
- Press this key: Ctrl + Shift + Esc
-
-
- Open Task view
-
-
- Press this key: Windows + Tab
-
-
- Toggle Suspender
-
-
- Suspend or resume the foreground application
-
-
- 8BitDo Lite 2
-
-
- Always on top
-
-
- When toggled, 3D controller overlay will stay on top of other windows
-
-
- Face camera
-
-
- Change 3D controller overlay model behaviour for facing the camera
-
-
- Background Color
-
-
- Change 3D controller overlay background color
-
-
- Listening...
-
-
- MACHENIKE HG510
-
-
- N64
-
-
- Change 3D controller overlay opacity
-
-
- Render settings
-
-
- Anti-Aliasing
-
-
- Change the render anti-aliasing status
-
-
- Change the render settings of your stationary 3D overlay controller model
-
-
- Update rate
-
-
- Change the render update rate, in update per second
-
-
- Fisher-Price controller
-
-
- Xbox One
-
-
- Resume
-
-
- Suspend
-
-
- Aiming down sights motion multiplier
-
-
- Activation button
-
-
- An additional motion sensitivity multiplier when aiming down sights or scope through the use of the configured activation button
-
-
- Multiplier value
-
-
- Boost power limit
-
-
- Change boost thermal power limit
-
-
- Power settings
-
-
- Change the power settings
-
-
- Sustained power limit
-
-
- Change sustained thermal power limit
-
-
- Thermal Power (TDP) Override
-
-
- Override the processor thermal power limit
-
-
- Manual GPU Clock Control
-
-
- Sets the GPU to a fixed clock
-
-
- MHz
-
-
- Power mode
-
-
- Balanced
-
-
- Optimize your device based on power use and performance
-
-
- Efficiency
-
-
- Performance
-
-
- Thermal Power (TDP) Limit
-
-
- Limits processor power for less total power
-
-
- Thermal Power Limit is overwritten by a profile
-
-
- W
-
-
- Create profile
-
-
- Waiting for foreground process...
-
-
- Use Acrylic backdrop
-
-
- Acrylic
-
-
- The application will use acrylic backdrop
-
-
- Mica
-
-
- None
-
-
- Tabbed
-
-
- Download
-
-
- EcoQoS
-
-
- Throttle inactive or background processes and applications to improve energy efficency
-
-
- External
-
-
- Internal
-
-
- Maximum Power
-
-
- The maximum power in watts supplied to the processor
-
-
- Minimum Power
-
-
- The minimum power in watts supplied to the processor
-
-
- Configurable Power (cTDP) override
-
-
- Allows to modify the minimum and maximum power values (TDP) beyond the CPU specifications
-
-
- We couldn't download the update file.
-
-
- We couldn't reach github.
-
-
- We couldn't locate the update file.
-
-
- Oups. There was an issue.
-
-
- %
-
-
- Force application shutdown
-
-
- Change hotkey by pressing a button or a special key
-
-
- PlayStation DualSense
-
-
- Motion
-
-
- Model will move in accordance with user movements based on sensor information
-
-
- Sensitivity X
-
-
- Change the motion sensitivity of the horizontal axis
-
-
- Sensitivity Y
-
-
- Change the motion sensitivity of the vertical axis
-
-
- X
-
-
- Y
-
-
- Boost
-
-
- Sustained
-
-
- Améliorer la détection du contrôleur virtuel
-
-
- Force le contrôleur virtuel à être en première position. Activez cette option si votre application/jeu ne détecte pas votre manette (redémarrage de l'appareil requis).
-
-
- Oui
-
-
- Non
-
-
- Le redémarrage de votre appareil est requis pour que les changements soient pris en compte. Voulez-vous redémarrer maintenant ?
-
-
- Redémarrage requis
-
-
- Oui
-
-
- Non
-
-
- Si vous désactivez ce paramètre, le paramètre "Amélioration de la détection du contrôleur virtuel" sera aussi désactivé. Voulez-vous continuer?
-
-
- Avertissement
-
-
- Oui
-
-
- Non
-
-
- Améliorer la détection du controlleur ne fonctionnera pas si vous fermez Handheld Companion. Êtes-vous sûr?
-
-
- Avertissement
-
-
- Manufacturer
-
-
- Partner
-
-
- Product name
-
-
- A,B,X,Y
-
-
- BACK GRIPS
-
-
- BUMPERS
-
-
- MENU
-
-
- OEM
-
-
- Desktop layout
-
-
- Define desktop layout
-
-
- Define controller layout when in desktop mode
-
-
- Edit
-
-
- Enable desktop layout
-
-
- Controller settings
-
-
- Non-game controller layouts
-
-
- You might want to click on Connect next to your plugged controller.
-
-
- You have no physical controller connected. No inputs will be sent to HC or its service.
-
-
- Please make sure you connected a compatible XInput or DInput device.
-
-
- No physical controller detected
-
-
- No physical controller connected
-
-
- You might want to start companion service or make sure your virtual controller status is set to: Connected
-
-
- Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
-
-
- No virtual controller detected
-
-
- You might want to unmute your virtual controller or unhide your physical controller.
-
-
- Your physical controller is hidden, yet you have muted your virtual controller.
-
-
- Physical controller is hidden
-
-
- You might want to hide your physical controller or mute your virtual controller.
-
-
- Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
-
-
- Physical controller is not hidden
-
-
- HD rumble
-
-
- Use high-definition rumble engine, at the cost of higher CPU usage
-
-
- Mute virtual controller
-
-
- Mute virtual controller on steam related applications
-
-
- Paramètres du contrôleur
-
-
- Vibrate controller on connect
-
-
- Vibrate physical controller when connected
-
-
- DIRECTIONAL PAD
-
-
- Decrease brightness
-
-
- Decrease the current display brightness by 5%
-
-
- Decrease volume
-
-
- Decrease the system volume by 5%
-
-
- Toggle Desktop controller layout
-
-
- Increase brightness
-
-
- Increase the current display brightness by 5%
-
-
- Increase volume
-
-
- Increase the system volume by 5%
-
-
- On-screen display
-
-
- Enable on-screen display support
-
-
- Fan override
-
-
- Set the fan duty cycle to user-defined value
-
-
- Display and hide Windows Action center
-
-
- Desktop layout
-
-
- Display Action center
-
-
- Open Snipping tool
-
-
- Press this key: Windows + Shift + S
-
-
- LEFT JOYSTICK
-
-
- LEFT JOYSTICK BUTTONS
-
-
- RIGHT JOYSTICK
-
-
- RIGHT JOYSTICK BUTTONS
-
-
- Apply template
-
-
- Buttons
-
-
- Cancel
-
-
- COMMUNITY
-
-
- Confirm
-
-
- Dpad
-
-
- Export for current controller
-
-
- Export layout
-
-
- Gyro
-
-
- Joysticks
-
-
- Layout author
-
-
- Layout description
-
-
- Layout title
-
-
- Save game information with the layout
-
-
- Show current controller templates only
-
-
- Layout template picker
-
-
- TEMPLATES
-
-
- Trackpads
-
-
- Triggers
-
-
- Hotkeys
-
-
- ms
-
-
- Overlay display level
-
-
- Disabled
-
-
- Extended
-
-
- Full
-
-
- Minimal
-
-
- Change the on-screen display level of information
-
-
- Update rate
-
-
- Change the on-screen display update rate
-
-
- Automatic TDP
-
-
- Automatic adjustment of TDP based on measured FPS and requested FPS target
-
-
- Framerate target
-
-
- Desired FPS target value for automatic TDP controller
-
-
- Controller layout
-
-
- Change the virtual controller layout
-
-
- Controller settings
-
-
- Change the virtual controller settings
-
-
- CPU
-
-
- Energy performance preference (EPP)
-
-
- CPU/GPU power balance
-
-
- Specifies power distribution policy between CPU and GPU
-
-
- Framerate limit
-
-
- Limits framerate for 3D applications
-
-
- GPU
-
-
- GPU Clock max frequency
-
-
- Maximum clock speed of the GPU in Mhz
-
-
- Joystick deadzone % left
-
-
- Adjust the inner and outer deadzone percentage of the left joystick
-
-
- Joystick deadzone % right
-
-
- Adjust the inner and outer deadzone percentage of the right joystick
-
-
- Power limit target
-
-
- Improve the stick circularity
-
-
- Circularity stick left
-
-
- Circularity stick right
-
-
- Left trigger deadzone %
-
-
- Adjust the inner and outer deadzone percentage of the left trigger
-
-
- Right trigger deadzone %
-
-
- Adjust the inner and outer deadzone percentage of the right trigger
-
-
- Motion anti-deadzone
-
-
- Compensate for in game deadzone, improve registration of small movements
-
-
- Disconnect
-
-
- FPS
-
-
- Enable desktop profile on start
-
-
- The desktop profile will be automatically enabled on application start
-
-
- Native display orientation
-
-
- Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
-
-
- Detect
-
-
- Not set
-
-
- Use system setting
-
-
- LEFT TRACKPAD
-
-
- LEFT TRACKPAD BUTTONS
-
-
- RIGHT TRACKPAD
-
-
- RIGHT TRACKPAD BUTTONS
-
-
- LEFT TRIGGER
-
-
- LEFT TRIGGER BUTTONS
-
-
- RIGHT TRIGGER
-
-
- RIGHT TRIGGER BUTTONS
-
-
- Power limit target
-
-
- Quicktools options
-
-
- %
-
-
- Set current CPU boost mode
-
-
- CPU boost mode
-
-
- Set the fan duty cycle to user-defined value
-
-
- Fan override
-
-
- Adjust main display resolution and refresh rate
-
-
- Display resolution and refresh rate
-
-
- Top right
-
-
- Top left
-
-
- Window location
-
-
- Bottom right
-
-
- Bottom left
-
-
- Power options
-
-
- Define quicktools window location
-
-
- Third-party applications
-
-
- None
-
-
- Quicktools backdrop, none, mica, tabbed, acrylic
-
-
- Automatically turn RTSS off when companion is closed
-
-
- Automatically turn HWiNFO off when companion is closed
-
-
- HWiNFO
-
-
- Default
-
-
- Current profile:
-
-
- RivaTuner Statistics Server
-
-
- Automatically hide quick tools when the user clicks outside of window
-
-
- Hide when loses focus
-
-
- Désactivé
-
-
- Injection (recommandé)
-
-
- Redirection
-
-
- This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
-
-
- Bouton A
-
-
- Toujours activé
-
-
- Bouton B
-
-
- Retour
-
-
- DPAD - Bas
-
-
- DPAD - Gauche
-
-
- DPAD - Droit
-
-
- DPAD - Bas
-
-
- Gâchette haute gauche
-
-
- Clic stick gauche
-
-
- Gâchette gauche
-
-
- Gâchette haute droite
-
-
- Clic stick droit
-
-
- Gâchette droite
-
-
- Menu
-
-
- Bouton X
-
-
- Bouton Y
-
-
- Contrôleur DualShock 4 émulé
-
-
- Aucun contrôleur émulé
-
-
- Contrôleur XBOX 360 émulé
-
-
- Connecté
-
-
- Déconnecté
-
-
- Auto Roll Yaw Swap
-
-
- Caméra joystick
-
-
- Conduite par joystick
-
-
- Player space
- A traduire...
-
-
- Joystick gauche
-
-
- Joystick droit
-
-
- Il s'agit de votre profil de contrôleur par défaut. Ce profil sera appliqué pour toutes vos applications qui n'ont pas de profil spécifique. Certaines options nécessitant un exécutable peuvent être désactivées.
-
-
- Oups. Il semble que ce profil soit en cours d'exécution. Certaines options nécessitant un exécutable pourraient être désactivées.
-
-
- Oups. Il semble que ce profil n'ait pas d'exécutable. Comment cela est-il possible ?
-
-
- Oups. Il semble que ce profil ne dispose pas d'un chemin vers l'application. Certaines options nécessitant un exécutable pourraient être désactivées.
-
-
- Oups. Il semble que vous n'ayez pas le niveau de permission nécessaire pour modifier le contenu de cette application. Assurez-vous que vous avez lancé ce programme en mode administrateur.
-
-
- Rien à voir ici.
-
-
- Automatique
-
-
- Désactivé
-
-
- Manuel
-
-
- Cette entrée fonctionnera comme un simple joystick. Elle est destinée aux applications traditionnelles de joystick
-
-
- Cette entrée fonctionnera comme un joystick optimisé pour le contrôle d'un volant ou d'un jeu de course
-
-
- Cette entrée fonctionnera comme un joystick optimisé pour le contrôle d'une caméra à la première ou à la troisième personne
-
-
- Handheld Companion
-
-
- Overlay
-
-
- Quick tools
-
-
- Windows
-
-
- Default
-
-
- Eco
-
-
- High
-
-
- Handheld Companion
-
-
- ≈
-
-
- ≈
-
-
- ≈
-
-
- ≈
-
-
- AYA
-
-
- AYA
-
-
- AYA
-
-
- AYA
-
-
- KB
-
-
- RC
-
-
- LC
-
-
- RC
-
-
- LC
-
-
- RC
-
-
- LC
-
-
- Win
-
-
- Esc
-
-
- RC
-
-
- LC
-
-
- M1
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Sony
-
-
- Options
-
-
- Custom
-
-
- Device
-
-
- Auto Roll Yaw Swap
-
-
- Joystick Camera
-
-
- Joystick Steering
-
-
- Player Space
-
-
- Left Stick
-
-
- Right Stick
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- STEAM
-
-
- Menu
-
-
- Oops. It seems this profile excutable is running. Some options requiring an executable might be disabled.
-
-
- Command center
-
-
- Armory crate
-
-
- Options
-
-
- L2
-
-
- R2
-
-
- Right Thumb
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- View
-
-
- DPad Down
-
-
- DPad Left
-
-
- PPad Right
-
-
- DPad Up
-
-
- LB
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Left Thumb
-
-
- Left Thumb Down
-
-
- Left Thumb Left
-
-
- Left Thumb Right
-
-
- Left Thumb Up
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- RB
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Right Thumb
-
-
- Right Thumb Down
-
-
- Right Thumb Left
-
-
- Right Thumb Right
-
-
- Right Thumb Up
-
-
- Guide
-
-
- Menu
-
-
- Left Thumb
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- S
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- LeftStick
-
-
- RightStick
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Back
-
-
- Exit
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- External
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ À propos
+
+
+ Handheld Companion fournit une prise en charge du gyroscope et de l'accéléromètre aux modèles AYA NEO 2020 et 2021 par le biais d'un contrôleur DualShock 4 virtuel. Si le service est activé, le contrôleur intégré sera masqué pour les applications en dehors de la liste blanche. Si le service est désactivé, le contrôleur intégré ne sera pas masqué et le contrôleur DualShock 4 virtuel sera désactivé. Handheld Companion s'appuie sur le pilote ViGEmBus et les bibliothèques ViGEmClient ainsi que sur le pilote de filtre en mode noyau HidHide. Les algorithmes de contrôle de mouvement sont basés sur le travail de Jibbsmart et les informations disponibles sur le GyroWiki.
+
+
+ Accéléromètre
+
+
+ Auteur
+
+
+ Contributeurs
+
+
+ Description
+
+
+ Faire un don
+
+
+ Gyromètre
+
+
+ Inclinomètre
+
+
+ N/A
+
+
+ Liens connexes
+
+
+ Nom du capteur
+
+
+ Spécification du capteur
+
+
+ Service
+
+
+ Code source
+
+
+ Version
+
+
+ Wiki
+
+
+ Administrateur
+
+
+ Masquer le contrôleur physique
+
+
+ Modifier la visibilité du contrôleur physique pour les autres applications
+
+
+ Connecter
+
+
+ Controller
+
+
+ Contrôleur
+
+
+ Déconnecter
+
+
+ Dispositifs d'entrée
+
+
+ Dévoiler à la fermeture
+
+
+ Rétablissement de la visibilité des contrôleurs physique pour les autres applications à l'arrêt du service
+
+
+ Force de vibration
+
+
+ Modification de la force de vibration du contrôleur
+
+
+ Handheld Companion
+
+
+ À propos
+
+
+ Contrôleur
+
+
+ Overlay
+
+
+ Profils
+
+
+ OK
+
+
+ Paramètres
+
+
+ Alignement
+
+
+ Modifier l'alignement du contrôleur
+
+
+ Modifier l'alignement des trackpads
+
+
+ Retour
+
+
+ Stationary pitch
+
+
+ Change the angle
+
+
+ Options du contrôleur
+
+
+ Contrôleur émulé
+
+
+ Face camera
+
+
+ 3D Model slowly rotates to face camera as default position
+
+
+ Déclencheur principal
+
+
+ Modifier le déclencheur principal
+
+
+ Contrôleur OEM
+
+
+ Opacité
+
+
+ Modifier l'opacité des trackpads
+
+
+ Overlay
+
+
+ Modèle du contrôleur
+
+
+ Modifier le modèle du contrôleur
+
+
+ Aperçu de l'overlay
+
+
+ Taille
+
+
+ Modifier la taille du contrôleur
+
+
+ Modifier la taille des trackpads
+
+
+ Menu
+
+
+ Options des trackpads
+
+
+ ZD O+
+
+
+ Overlay
+
+
+ Paramètres supplémentaires
+
+
+ Options de la caméra
+
+
+ Courbe de réponse personnalisée
+
+
+ Commande envoyée au jeu
+
+
+ Intensité du mouvement
+
+
+ Agressif
+
+
+ Défaut
+
+
+ Options de préréglage
+
+
+ Précis
+
+
+ Durée du mouvement
+
+
+ Modifier la durée du mouvement, calibrée à un virage de 180 degrés, en millisecondes
+
+
+ Flick stick (expérimental)
+
+
+ Pointer la caméra dans la direction du mouvement du joystick droit, faites pivoter la caméra purement dans le plan horizontal en tournant le joystick
+
+
+ Activer flick stick
+
+
+ Sensibilité
+
+
+ Modifier la sensibilité au mouvement de l'axe horizontal et vertical
+
+
+ Sensibilité du joystick
+
+
+ Modifier la vitesse de rotation
+
+
+ Paramètres supplémentaires
+
+
+ Zone morte
+
+
+ Modifier la zone morte de la direction, en degré. Améliore la rectitude de la direction
+
+
+ Entrée de jeu par joystick
+ // not good
+
+
+ Direction par joystick
+
+
+ Options de direction par joystick
+
+
+ Aperçu de la direction par joystick
+
+
+ Angle de braquage maximal
+
+
+ Modifier la valeur maximale de l'angle de braquage, en degrés
+
+
+ Linéarité de la direction
+
+
+ Correspondance entre les commandes du joystick et la direction. Les valeurs les plus basses fournissent plus de précision près du braquage complet mais moins de précision près du centre. Des valeurs plus élevées fournissent plus de précision près du centre mais moins de précision près du braquage maximum
+
+
+ Multiplicateur de l'accéléromètre
+
+
+ Modifier la valeur de l'accéléromètre rapportée par le système
+
+
+ Paramètres supplémentaires
+
+
+ Anti-zone morte
+
+
+ Modifier l'anti-zone morte, en pourcentage
+
+
+ Êtes-vous sûr de vouloir supprimer?
+
+
+ Cet élément sera supprimé immédiatement. Vous ne pouvez pas annuler cette action.
+
+
+ Etes-vous sûr de vouloir écraser?
+
+
+ Cet élément sera écrasé. Vous ne pouvez pas annuler cette action.
+
+
+ Annuler
+
+
+ Créer un nouveau profil
+
+
+ Supprimer
+
+
+ Supprimer le profil
+
+
+ Activer le profil
+
+
+ Le profil sera automatiquement appliqué lorsque l'application associée sera détectée
+
+
+ Paramètres globaux
+
+
+ Modifier les paramètres des profils globaux
+
+
+ Multiplicateur du gyromètre
+
+
+ Modifier la valeur du gyromètre rapportée par le système
+
+
+ Axe de direction du gyroscope
+
+
+ Pour contrôler le mouvement horizontal du contrôleur, vous pouvez utiliser l'axe de lacet ou de roulis
+
+
+ Inverser l'axe horizontal
+
+
+ Inverser l'axe vertical
+
+
+ Paramètres de contrôle du mouvement
+
+
+ Modifier les paramètres globaux de contrôle du mouvement
+
+
+ OK
+
+
+ Détails du profil
+
+
+ Nom du profil
+
+
+ Chemin du profil
+
+
+ Profils
+
+
+ Sélection du profil
+
+
+ Sélectionner le profil que vous souhaitez modifier
+
+
+ Paramètres du profil
+
+
+ Profil mis à jour
+
+
+ a été mis à jour.
+
+
+ Roulis
+
+
+ Style d'entrée
+
+
+ Les entrées physiques du contrôleur peuvent être programmées pour agir comme différents types de dispositifs
+
+
+ Dispositif de sortie
+
+
+ Sélectionner le dispositif qui recevra les commandes de mouvement
+
+
+ Activer le contrôle universel de mouvements
+
+
+ Disabled, turn on with button(s)
+
+
+ Enabled, turn off with button(s)
+
+
+ Motion activation
+
+
+ With motion input disabled, use selected button(s) to enable motion,
+with motion input enabled, use selected button(s) to disable motion.
+
+
+ Sélectionner le dispositif qui recevra les commandes de mouvement
+
+
+ Paramètres du contrôle universel de mouvements
+
+
+ Traduire les mouvements du dispositif en entrées du contrôleur
+
+
+ Mettre à jour le profil
+
+
+ Autoriser l'application à accéder au contrôleur physique du dispositif
+
+
+ Compatibilitée améliorée (XInputPlus)
+
+
+ Lacet
+
+
+ Oui
+
+
+ Fournit une prise en charge du gyroscope et de l'accéléromètre aux ordinateurs de jeu portables Windows par le biais d'un contrôleur virtuel. Si le service est activé, le contrôleur intégré sera masqué pour les applications en dehors de la liste blanche. Si le service est désactivé, le contrôleur embarqué ne sera plus caché et le contrôleur virtuel sera désactivé.
+
+
+ Controller Service
+
+
+ Langue
+
+
+ La langue de l'application
+
+
+ Redémarrage nécessaire
+
+
+ Pour que les modifications soient prises en compte, veuillez redémarrer l'application
+
+
+ Thème de l'application
+
+
+ Le thème de l'application, mode clair ou foncé
+
+
+ Démarrage automatique de l'application
+
+
+ L'application démarre automatiquement lorsque je me connecte à Windows
+
+
+ Vérifier les mises à jour
+
+
+ Fermer l'application la réduira
+
+
+ L'application sera réduite au lieu d'être fermée
+
+
+ Téléchargement -
+
+
+ Options générales
+
+
+ Installer maintenant
+
+
+ Dernière vérification:
+
+
+ Options de notification
+
+
+ Ouvrir l'application en arrière-plan
+
+
+ L'application démarre initialement réduite et apparaît dans la barre des tâches
+
+
+ Sensor options
+ Translate
+
+
+ External sensor placement direction
+ Translate
+
+
+ Select on which side of the device the senor has been mounted
+ Translate
+
+
+ External sensor upside down
+ Translate
+
+
+ Sensor has been mounted upside down, possible with USB-C convertor
+ Translate
+
+
+ Sensor selection
+ Translate
+
+
+ Select the desired sensor used for motion input
+ Translate
+
+
+ Paramètres
+
+
+ Type de démarrage
+
+
+ Utilisé par le gestionnaire du service pour définir le type de démarrage du service
+
+
+ Foncé
+
+
+ Clair
+
+
+ Notification toast
+
+
+ Obtenir des notifications de l'application dans le centre d'action Windows
+
+
+ Mises à jour disponibles
+
+
+ Vérification des mises à jour...
+
+
+ Vous êtes à jour
+
+
+ Le contrôleur est maintenant masqué et les entrées sont transmises au contrôleur virtuel
+
+
+ Utilisateur
+
+
+ Exécutez cet outil en tant qu'administrateur pour déverrouiller ces paramètres
+
+
+ External
+
+
+ Internal
+
+
+ Decrease thermal power limit (TDP)
+
+
+ Decrease system or currently applied profile TDP by one watt
+
+
+ Press to define hotkey input
+
+
+ Press to define keyboard output
+
+
+ Increase thermal power limit (TDP)
+
+
+ Increase system or currently applied profile TDP by one watt
+
+
+ Display 3D controller
+
+
+ Change 3D hotkey by pressing a button or a special key
+
+
+ Display virtual trackpads
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ Summon quick tools window
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ Custom shortcut
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ Display and hide the desktop
+
+
+ Press this key: Windows + D
+
+
+ Exit
+
+
+ Press this key: Escape
+
+
+ Switches between window and full screen
+
+
+ Press this key: Alt + Enter
+
+
+ Guide or PS button
+
+
+ Simulate a Xbox Guide or Sony PS button input
+
+
+ Display touch keyboard
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ Display and hide main window
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ Open Task Manager
+
+
+ Press this key: Ctrl + Shift + Esc
+
+
+ Open Task view
+
+
+ Press this key: Windows + Tab
+
+
+ Toggle Suspender
+
+
+ Suspend or resume the foreground application
+
+
+ 8BitDo Lite 2
+
+
+ Always on top
+
+
+ When toggled, 3D controller overlay will stay on top of other windows
+
+
+ Face camera
+
+
+ Change 3D controller overlay model behaviour for facing the camera
+
+
+ Background Color
+
+
+ Change 3D controller overlay background color
+
+
+ Listening...
+
+
+ MACHENIKE HG510
+
+
+ N64
+
+
+ Change 3D controller overlay opacity
+
+
+ Render settings
+
+
+ Anti-Aliasing
+
+
+ Change the render anti-aliasing status
+
+
+ Change the render settings of your stationary 3D overlay controller model
+
+
+ Update rate
+
+
+ Change the render update rate, in update per second
+
+
+ Fisher-Price controller
+
+
+ Xbox One
+
+
+ Resume
+
+
+ Suspend
+
+
+ Aiming down sights motion multiplier
+
+
+ Activation button
+
+
+ An additional motion sensitivity multiplier when aiming down sights or scope through the use of the configured activation button
+
+
+ Multiplier value
+
+
+ Boost power limit
+
+
+ Change boost thermal power limit
+
+
+ Power settings
+
+
+ Change the power settings
+
+
+ Sustained power limit
+
+
+ Change sustained thermal power limit
+
+
+ Thermal Power (TDP) Override
+
+
+ Override the processor thermal power limit
+
+
+ Manual GPU Clock Control
+
+
+ Sets the GPU to a fixed clock
+
+
+ MHz
+
+
+ Power mode
+
+
+ Balanced
+
+
+ Optimize your device based on power use and performance
+
+
+ Efficiency
+
+
+ Performance
+
+
+ Thermal Power (TDP) Limit
+
+
+ Limits processor power for less total power
+
+
+ Thermal Power Limit is overwritten by a profile
+
+
+ W
+
+
+ Create profile
+
+
+ Waiting for foreground process...
+
+
+ Use Acrylic backdrop
+
+
+ Acrylic
+
+
+ The application will use acrylic backdrop
+
+
+ Mica
+
+
+ None
+
+
+ Tabbed
+
+
+ Download
+
+
+ EcoQoS
+
+
+ Throttle inactive or background processes and applications to improve energy efficency
+
+
+ External
+
+
+ Internal
+
+
+ Maximum Power
+
+
+ The maximum power in watts supplied to the processor
+
+
+ Minimum Power
+
+
+ The minimum power in watts supplied to the processor
+
+
+ Configurable Power (cTDP) override
+
+
+ Allows to modify the minimum and maximum power values (TDP) beyond the CPU specifications
+
+
+ We couldn't download the update file.
+
+
+ We couldn't reach github.
+
+
+ We couldn't locate the update file.
+
+
+ Oups. There was an issue.
+
+
+ %
+
+
+ Force application shutdown
+
+
+ Change hotkey by pressing a button or a special key
+
+
+ PlayStation DualSense
+
+
+ Motion
+
+
+ Model will move in accordance with user movements based on sensor information
+
+
+ Sensitivity X
+
+
+ Change the motion sensitivity of the horizontal axis
+
+
+ Sensitivity Y
+
+
+ Change the motion sensitivity of the vertical axis
+
+
+ X
+
+
+ Y
+
+
+ Boost
+
+
+ Sustained
+
+
+ Améliorer la détection du contrôleur virtuel
+
+
+ Force le contrôleur virtuel à être en première position. Activez cette option si votre application/jeu ne détecte pas votre manette (redémarrage de l'appareil requis).
+
+
+ Oui
+
+
+ Non
+
+
+ Le redémarrage de votre appareil est requis pour que les changements soient pris en compte. Voulez-vous redémarrer maintenant ?
+
+
+ Redémarrage requis
+
+
+ Oui
+
+
+ Non
+
+
+ Si vous désactivez ce paramètre, le paramètre "Amélioration de la détection du contrôleur virtuel" sera aussi désactivé. Voulez-vous continuer?
+
+
+ Avertissement
+
+
+ Oui
+
+
+ Non
+
+
+ Améliorer la détection du controlleur ne fonctionnera pas si vous fermez Handheld Companion. Êtes-vous sûr?
+
+
+ Avertissement
+
+
+ Manufacturer
+
+
+ Partner
+
+
+ Product name
+
+
+ A,B,X,Y
+
+
+ BACK GRIPS
+
+
+ BUMPERS
+
+
+ MENU
+
+
+ OEM
+
+
+ Desktop layout
+
+
+ Define desktop layout
+
+
+ Define controller layout when in desktop mode
+
+
+ Edit
+
+
+ Enable desktop layout
+
+
+ Controller settings
+
+
+ Non-game controller layouts
+
+
+ You might want to click on Connect next to your plugged controller.
+
+
+ You have no physical controller connected. No inputs will be sent to HC or its service.
+
+
+ Please make sure you connected a compatible XInput or DInput device.
+
+
+ No physical controller detected
+
+
+ No physical controller connected
+
+
+ You might want to start companion service or make sure your virtual controller status is set to: Connected
+
+
+ Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
+
+
+ No virtual controller detected
+
+
+ You might want to unmute your virtual controller or unhide your physical controller.
+
+
+ Your physical controller is hidden, yet you have muted your virtual controller.
+
+
+ Physical controller is hidden
+
+
+ You might want to hide your physical controller or mute your virtual controller.
+
+
+ Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
+
+
+ Physical controller is not hidden
+
+
+ HD rumble
+
+
+ Use high-definition rumble engine, at the cost of higher CPU usage
+
+
+ Mute virtual controller
+
+
+ Mute virtual controller on steam related applications
+
+
+ Paramètres du contrôleur
+
+
+ Vibrate controller on connect
+
+
+ Vibrate physical controller when connected
+
+
+ DIRECTIONAL PAD
+
+
+ Decrease brightness
+
+
+ Decrease the current display brightness by 5%
+
+
+ Decrease volume
+
+
+ Decrease the system volume by 5%
+
+
+ Toggle Desktop controller layout
+
+
+ Increase brightness
+
+
+ Increase the current display brightness by 5%
+
+
+ Increase volume
+
+
+ Increase the system volume by 5%
+
+
+ On-screen display
+
+
+ Enable on-screen display support
+
+
+ Fan override
+
+
+ Set the fan duty cycle to user-defined value
+
+
+ Display and hide Windows Action center
+
+
+ Desktop layout
+
+
+ Display Action center
+
+
+ Open Snipping tool
+
+
+ Press this key: Windows + Shift + S
+
+
+ LEFT JOYSTICK
+
+
+ LEFT JOYSTICK BUTTONS
+
+
+ RIGHT JOYSTICK
+
+
+ RIGHT JOYSTICK BUTTONS
+
+
+ Apply template
+
+
+ Buttons
+
+
+ Cancel
+
+
+ COMMUNITY
+
+
+ Confirm
+
+
+ Dpad
+
+
+ Export for current controller
+
+
+ Export layout
+
+
+ Gyro
+
+
+ Joysticks
+
+
+ Layout author
+
+
+ Layout description
+
+
+ Layout title
+
+
+ Save game information with the layout
+
+
+ Show current controller templates only
+
+
+ Layout template picker
+
+
+ TEMPLATES
+
+
+ Trackpads
+
+
+ Triggers
+
+
+ Hotkeys
+
+
+ ms
+
+
+ Overlay display level
+
+
+ Disabled
+
+
+ Extended
+
+
+ Full
+
+
+ Minimal
+
+
+ Change the on-screen display level of information
+
+
+ Update rate
+
+
+ Change the on-screen display update rate
+
+
+ Automatic TDP
+
+
+ Automatic adjustment of TDP based on measured FPS and requested FPS target
+
+
+ Framerate target
+
+
+ Desired FPS target value for automatic TDP controller
+
+
+ Controller layout
+
+
+ Change the virtual controller layout
+
+
+ Controller settings
+
+
+ Change the virtual controller settings
+
+
+ CPU
+
+
+ Energy performance preference (EPP)
+
+
+ CPU/GPU power balance
+
+
+ Specifies power distribution policy between CPU and GPU
+
+
+ Framerate limit
+
+
+ Limits framerate for 3D applications
+
+
+ GPU
+
+
+ GPU Clock max frequency
+
+
+ Maximum clock speed of the GPU in Mhz
+
+
+ Joystick deadzone % left
+
+
+ Adjust the inner and outer deadzone percentage of the left joystick
+
+
+ Joystick deadzone % right
+
+
+ Adjust the inner and outer deadzone percentage of the right joystick
+
+
+ Power limit target
+
+
+ Improve the stick circularity
+
+
+ Circularity stick left
+
+
+ Circularity stick right
+
+
+ Left trigger deadzone %
+
+
+ Adjust the inner and outer deadzone percentage of the left trigger
+
+
+ Right trigger deadzone %
+
+
+ Adjust the inner and outer deadzone percentage of the right trigger
+
+
+ Motion anti-deadzone
+
+
+ Compensate for in game deadzone, improve registration of small movements
+
+
+ Disconnect
+
+
+ FPS
+
+
+ Enable desktop profile on start
+
+
+ The desktop profile will be automatically enabled on application start
+
+
+ Native display orientation
+
+
+ Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
+
+
+ Detect
+
+
+ Not set
+
+
+ Use system setting
+
+
+ LEFT TRACKPAD
+
+
+ LEFT TRACKPAD BUTTONS
+
+
+ RIGHT TRACKPAD
+
+
+ RIGHT TRACKPAD BUTTONS
+
+
+ LEFT TRIGGER
+
+
+ LEFT TRIGGER BUTTONS
+
+
+ RIGHT TRIGGER
+
+
+ RIGHT TRIGGER BUTTONS
+
+
+ Power limit target
+
+
+ Quicktools options
+
+
+ %
+
+
+ Set current CPU boost mode
+
+
+ CPU boost mode
+
+
+ Set the fan duty cycle to user-defined value
+
+
+ Fan override
+
+
+ Adjust main display resolution and refresh rate
+
+
+ Display resolution and refresh rate
+
+
+ Top right
+
+
+ Top left
+
+
+ Window location
+
+
+ Bottom right
+
+
+ Bottom left
+
+
+ Power options
+
+
+ Define quicktools window location
+
+
+ Third-party applications
+
+
+ None
+
+
+ Quicktools backdrop, none, mica, tabbed, acrylic
+
+
+ Automatically turn RTSS off when companion is closed
+
+
+ Default
+
+
+ Current profile:
+
+
+ RivaTuner Statistics Server
+
+
+ Automatically hide quick tools when the user clicks outside of window
+
+
+ Hide when loses focus
+
+
+ Désactivé
+
+
+ Injection (recommandé)
+
+
+ Redirection
+
+
+ This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
+
+
+ Bouton A
+
+
+ Toujours activé
+
+
+ Bouton B
+
+
+ Retour
+
+
+ DPAD - Bas
+
+
+ DPAD - Gauche
+
+
+ DPAD - Droit
+
+
+ DPAD - Bas
+
+
+ Gâchette haute gauche
+
+
+ Clic stick gauche
+
+
+ Gâchette gauche
+
+
+ Gâchette haute droite
+
+
+ Clic stick droit
+
+
+ Gâchette droite
+
+
+ Menu
+
+
+ Bouton X
+
+
+ Bouton Y
+
+
+ Contrôleur DualShock 4 émulé
+
+
+ Aucun contrôleur émulé
+
+
+ Contrôleur XBOX 360 émulé
+
+
+ Connecté
+
+
+ Déconnecté
+
+
+ Auto Roll Yaw Swap
+
+
+ Caméra joystick
+
+
+ Conduite par joystick
+
+
+ Player space
+ A traduire...
+
+
+ Joystick gauche
+
+
+ Joystick droit
+
+
+ Il s'agit de votre profil de contrôleur par défaut. Ce profil sera appliqué pour toutes vos applications qui n'ont pas de profil spécifique. Certaines options nécessitant un exécutable peuvent être désactivées.
+
+
+ Oups. Il semble que ce profil soit en cours d'exécution. Certaines options nécessitant un exécutable pourraient être désactivées.
+
+
+ Oups. Il semble que ce profil n'ait pas d'exécutable. Comment cela est-il possible ?
+
+
+ Oups. Il semble que ce profil ne dispose pas d'un chemin vers l'application. Certaines options nécessitant un exécutable pourraient être désactivées.
+
+
+ Oups. Il semble que vous n'ayez pas le niveau de permission nécessaire pour modifier le contenu de cette application. Assurez-vous que vous avez lancé ce programme en mode administrateur.
+
+
+ Rien à voir ici.
+
+
+ Automatique
+
+
+ Désactivé
+
+
+ Manuel
+
+
+ Cette entrée fonctionnera comme un simple joystick. Elle est destinée aux applications traditionnelles de joystick
+
+
+ Cette entrée fonctionnera comme un joystick optimisé pour le contrôle d'un volant ou d'un jeu de course
+
+
+ Cette entrée fonctionnera comme un joystick optimisé pour le contrôle d'une caméra à la première ou à la troisième personne
+
+
+ Handheld Companion
+
+
+ Overlay
+
+
+ Quick tools
+
+
+ Windows
+
+
+ Default
+
+
+ Eco
+
+
+ High
+
+
+ Handheld Companion
+
+
+ ≈
+
+
+ ≈
+
+
+ ≈
+
+
+ ≈
+
+
+ AYA
+
+
+ AYA
+
+
+ AYA
+
+
+ AYA
+
+
+ KB
+
+
+ RC
+
+
+ LC
+
+
+ RC
+
+
+ LC
+
+
+ RC
+
+
+ LC
+
+
+ Win
+
+
+ Esc
+
+
+ RC
+
+
+ LC
+
+
+ M1
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Sony
+
+
+ Options
+
+
+ Custom
+
+
+ Device
+
+
+ Auto Roll Yaw Swap
+
+
+ Joystick Camera
+
+
+ Joystick Steering
+
+
+ Player Space
+
+
+ Left Stick
+
+
+ Right Stick
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ STEAM
+
+
+ Menu
+
+
+ Oops. It seems this profile excutable is running. Some options requiring an executable might be disabled.
+
+
+ Command center
+
+
+ Armory crate
+
+
+ Options
+
+
+ L2
+
+
+ R2
+
+
+ Right Thumb
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ View
+
+
+ DPad Down
+
+
+ DPad Left
+
+
+ DPad Right
+
+
+ DPad Up
+
+
+ LB
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Left Thumb
+
+
+ Left Thumb Down
+
+
+ Left Thumb Left
+
+
+ Left Thumb Right
+
+
+ Left Thumb Up
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ RB
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Right Thumb
+
+
+ Right Thumb Down
+
+
+ Right Thumb Left
+
+
+ Right Thumb Right
+
+
+ Right Thumb Up
+
+
+ Guide
+
+
+ Menu
+
+
+ Left Thumb
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ LeftStick
+
+
+ RightStick
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Back
+
+
+ Exit
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ External
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.it-IT.resx b/HandheldCompanion/Properties/Resources.it-IT.resx
index 21301b582..414bb9cd3 100644
--- a/HandheldCompanion/Properties/Resources.it-IT.resx
+++ b/HandheldCompanion/Properties/Resources.it-IT.resx
@@ -1,2359 +1,2353 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Informazioni
-
-
- Una combinazione di un servizio Windows e un'interfaccia touch ottimizzata per migliorare la tua esperienza con il computer portatile da gioco. Le funzionalità includono: controllo del movimento, simulazione del controller virtuale, sovrapposizione di strumenti rapidi, touchpad virtuali, modello di controller 3D, sistema di impostazioni del profilo basato sull'applicazione. Handheld Companion si basa sul driver ViGEmBus e sulle librerie ViGEmClient, nonché sul driver del filtro di livello kernel HidHide. Gli algoritmi di controllo del movimento si basano sul lavoro di Jibbsmart e sulle informazioni disponibili su GyroWiki.
-
-
- Accelerometro
-
-
- Autore
-
-
- Contributori
-
-
- Descrizione
-
-
- Donazioni
-
-
- Giroscopio
-
-
- Inclinometro
-
-
- N/D
-
-
- Link correlati
-
-
- Esterno
-
-
- Interno
-
-
- Nome del sensore
-
-
- Specifiche del sensore
-
-
- Servizio
-
-
- Codice sorgente
-
-
- Versione
-
-
- Wiki
-
-
- Amministratore
-
-
- Nascondi controller al collegamento
-
-
- Nascondi il controller fisico quando è collegato
-
-
- Collega
-
-
- Controller
-
-
- Nascondi controller
-
-
- Impostazioni controller
-
-
- Disconnetti
-
-
- Dispositivi di input
-
-
- Ripristina visibilità controller alla chiusura
-
-
- Ripristina la visibilità di tutti i controller fisici quando l'applicazione viene chiusa
-
-
- Intensità vibrazione
-
-
- Cambia l'intensità della vibrazione del controller
-
-
-
- ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- Riduci limite di potenza termica (TDP)
-
-
- Riduci il TDP del sistema o del profilo correntemente applicato di un watt
-
-
- Premi per definire il trigger
-
-
- Premi per definire l'output della tastiera
-
-
- Aumenta limite di potenza termica (TDP)
-
-
- Aumenta il TDP del sistema o del profilo correntemente applicato di un watt
-
-
- Mostra controller 3D
-
-
- Cambia l'hotkey del controller 3D premendo un pulsante o un tasto speciale
-
-
- Mostra trackpad virtuali
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Richiama finestra strumenti rapidi
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Scorciatoia personalizzata
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Mostra e nascondi il desktop
-
-
- Premi questa combinazione di tasti: Windows + D
-
-
- Tasto Escape
-
-
- Premi questo tasto: Escape
-
-
- Passa da finestra a schermo intero
-
-
- Premi questa combinazione di tasti: Alt + Enter
-
-
- Pulsante Guide o PS
-
-
- Simula l'input di un pulsante Guide di Xbox o PS di Sony
-
-
- Mostra tastiera touch
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Forza la chiusura dell'applicazione
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Mostra e nascondi finestra principale
-
-
- Cambia l'hotkey premendo un pulsante o un tasto speciale
-
-
- Apri Task Manager
-
-
- Premi questa combinazione di tasti: Ctrl + Shift + Esc
-
-
- Apri visualizzazione attività
-
-
- Premi questa combinazione di tasti: Windows + Tab
-
-
- Attiva/disattiva sospensione
-
-
- Sospendi o riprendi l'applicazione in primo piano
-
-
- Handheld Companion
-
-
- Informazioni
-
-
- Controller
-
-
- Overlay
-
-
- Profili
-
-
- OK
-
-
- Impostazioni
-
-
- 8BitDo Lite 2
-
-
- Allineamento
-
-
- Cambia l'allineamento dell'overlay del controller 3D
-
-
- Cambia l'allineamento dell'overlay dei trackpad
-
-
- Sempre in primo piano
-
-
- Quando attivato, l'overlay del controller 3D rimarrà sempre in primo piano rispetto alle altre finestre
-
-
- Indietro
-
-
- Inquadra la fotocamera
-
-
- Cambia il comportamento del modello dell'overlay del controller 3D per inquadrare la fotocamera
-
-
- Pitch fisso
-
-
- Cambia l'angolo, in gradi
-
-
- Colore sfondo
-
-
- Cambia il colore di sfondo dell'overlay del controller 3D
-
-
- Opzioni del controller
-
-
- PlayStation DualSense
-
-
- Controller emulato
-
-
- Inquadra la fotocamera
-
-
- Il modello 3D ruota lentamente per inquadrare la fotocamera come posizione predefinita
-
-
- In ascolto...
-
-
- MACHENIKE HG510
-
-
- Pulsante principale
-
-
- Cambia il pulsante principale dell'overlay del controller 3D
-
-
- Movimento
-
-
- Il modello si muoverà in base ai movimenti dell'utente basati sulle informazioni dei sensori
-
-
- N64
-
-
- Controller OEM
-
-
- Opacità
-
-
- Cambia l'opacità dell'overlay del controller 3D
-
-
- Cambia l'opacità dell'overlay dei trackpad
-
-
- Overlay
-
-
- Modello overlay
-
-
- Cambia il modello dell'overlay del controller 3D
-
-
- Anteprima overlay
-
-
- Impostazioni di rendering
-
-
- Anti-Aliasing
-
-
- Cambia lo stato dell'anti-aliasing del rendering
-
-
- Cambia le impostazioni di rendering del modello del tuo controller 3D overlay stazionario
-
-
- Frequenza di aggiornamento
-
-
- Cambia la frequenza di aggiornamento del rendering, in aggiornamenti al secondo
-
-
- Dimensioni
-
-
- Cambia le dimensioni dell'overlay del controller 3D
-
-
- Cambia le dimensioni dell'overlay dei trackpad
-
-
- Avvia
-
-
- Controller Fisher-Price
-
-
- Opzioni dei trackpad
-
-
- Xbox One
-
-
- ZD O+
-
-
- Overlay
-
-
- Riprendi
-
-
- Sospendi
-
-
- Impostazioni aggiuntive
-
-
- Moltiplicatore movimento mira
-
-
- Pulsante di attivazione
-
-
- Un moltiplicatore di sensibilità del movimento aggiuntivo quando si mira o si utilizza un mirino attraverso l'uso del pulsante di attivazione configurato
-
-
- Valore moltiplicatore
-
-
- Opzioni fotocamera
-
-
- Curva di risposta personalizzata
-
-
- Uscita inviata al gioco
-
-
- Intensità del movimento
-
-
- Aggressivo
-
-
- Predefinito
-
-
- Opzioni predefinite
-
-
- Preciso
-
-
- Durata flick
-
-
- Cambia la durata del flick, calibra per una rotazione di 180 gradi, in millisecondi
-
-
- Flick stick (sperimentale)
-
-
- Punta la fotocamera nella direzione del flick del joystick (destro), ruota la fotocamera esclusivamente nel piano orizzontale ruotando
-
-
- Abilita flick stick
-
-
- Sensibilità
-
-
- Cambia la sensibilità del movimento dell'asse orizzontale e verticale
-
-
- Sensibilità X
-
-
- Cambia la sensibilità del movimento dell'asse orizzontale
-
-
- Sensibilità Y
-
-
- Cambia la sensibilità del movimento dell'asse verticale
-
-
- Sensibilità del joystick
-
-
- Cambia la velocità di rotazione
-
-
- Impostazioni aggiuntive
-
-
- Zona morta
-
-
- Cambia la zona morta dello sterzo, in gradi. Migliora la rettilineità dello sterzo
-
-
- Input joystick gioco
-
-
- Sterzo joystick
-
-
- Opzioni sterzo joystick
-
-
- Anteprima sterzo joystick
-
-
- Angolo massimo di sterzo
-
-
- Cambia il valore massimo dell'angolo di sterzo, in gradi
-
-
- Linearità dello sterzo
-
-
- Mappatura tra input e sterzo. Valori più bassi forniscono maggiore precisione vicino alla massima rotazione ma minore precisione vicino al centro. Valori più alti forniscono maggiore precisione vicino al centro ma minore precisione vicino alla massima rotazione. 1.0 è una mappatura lineare
-
-
- Moltiplicatore accelerometro
-
-
- Cambia il valore dell'accelerometro riportato dal sistema
-
-
- Impostazioni aggiuntive
-
-
- Anti-zona morta
-
-
- Cambia l'anti-zona morta nel gioco, in percentuale
-
-
- %
-
-
- Sei sicuro di voler eliminare?
-
-
- Questo elemento verrà eliminato immediatamente. Non è possibile annullare questa azione.
-
-
- Sei sicuro di voler sovrascrivere questo profilo?
-
-
- {0} sarà sovrascritto. Non è possibile annullare questa azione.
-
-
- Limite potenza boost
-
-
- Cambia il limite di potenza termica del boost
-
-
- Annulla
-
-
- Crea un nuovo profilo
-
-
- Elimina
-
-
- Elimina profilo
-
-
- Profilo utente per gioco
-
-
- Il profilo verrà applicato automaticamente quando verrà rilevata l'applicazione associata
-
-
- Impostazioni globali
-
-
- Cambia le impostazioni globali dei profili
-
-
- Moltiplicatore giroscopio
-
-
- Cambia il valore del giroscopio riportato dal sistema
-
-
- Asse sterzo giroscopio
-
-
- Per il controllo del movimento orizzontale del controller, puoi utilizzare l'asse di imbardata o rollio
-
-
- Inverti asse orizzontale
-
-
- Inverti asse verticale
-
-
- Impostazioni controllo del movimento
-
-
- Cambia le impostazioni globali del controllo del movimento
-
-
- OK
-
-
- Impostazioni alimentazione
-
-
- Cambia le impostazioni di alimentazione
-
-
- Dettagli profilo
-
-
- Nome profilo
-
-
- Percorso profilo
-
-
- Profili
-
-
- Selezione profilo
-
-
- Seleziona il profilo che desideri modificare
-
-
- Impostazioni profilo
-
-
- Profilo aggiornato
-
-
- è stato aggiornato.
-
-
- Rollio
-
-
- X
-
-
- Y
-
-
- Stile di input
-
-
- I comandi fisici del controller possono essere programmati per agire come diversi tipi di dispositivi
-
-
- Dispositivo di output
-
-
- Seleziona il dispositivo che riceverà i comandi di movimento
-
-
- Limite di potenza sostenuta
-
-
- Cambia il limite di potenza termica sostenuta
-
-
- Limite di potenza termica (TDP)
-
-
- Limita la potenza del processore per una potenza totale inferiore
-
-
- Abilita il controller di movimento universale
-
-
- Disattivato, attiva con il pulsante(i)
-
-
- Attivato, disattiva con il pulsante(i)
-
-
- Attivazione movimento
-
-
- Con l'input di movimento disabilitato, utilizza il/i pulsante/i selezionato/i per abilitare il movimento, con l'input di movimento abilitato, utilizza il/i pulsante/i selezionato/i per disabilitare il movimento.
-
-
- Seleziona il dispositivo che riceverà i comandi di movimento
-
-
- Impostazioni del controllo di movimento universale
-
-
- Traduci i movimenti del dispositivo in input del controller
-
-
- Aggiorna profilo
-
-
- Consenti all'applicazione di accedere al controller fisico del dispositivo
-
-
- Compatibilità estesa (XInputPlus)
-
-
- Giro
-
-
- Sì
-
-
- Disconnetti
-
-
- Controllo manuale dell'orologio della GPU
-
-
- Imposta la GPU su un orologio fisso
-
-
- MHz
-
-
- Modalità di alimentazione
-
-
- Bilanciata
-
-
- Ottimizza il dispositivo in base all'utilizzo dell'alimentazione e alle prestazioni
-
-
- Efficienza
-
-
- Prestazioni
-
-
- Boost
-
-
- Limite di potenza termica (TDP)
-
-
- Limita la potenza del processore per una potenza totale inferiore
-
-
- Il limite di potenza termica è sovrascritto da un profilo
-
-
- Sostenuta
-
-
- W
-
-
- Crea profilo
-
-
- In attesa del processo in primo piano...
-
-
- Fornisce supporto per giroscopio e accelerometro ai computer portatili per il gioco con Windows tramite un controller virtuale. Se il servizio è abilitato, il controller integrato sarà nascosto alle applicazioni al di fuori della whitelist. Se il servizio è disabilitato, il controller integrato sarà visibile e il controller virtuale sarà disabilitato.
-
-
- Controller Service
-
-
- Lingua
-
-
- La lingua dell'applicazione
-
-
- Riavvio necessario
-
-
- Per rendere effettive le modifiche, riavviare l'applicazione
-
-
- Tema dell'applicazione
-
-
- Il tema dell'applicazione, modalità chiara o scura
-
-
- Avvia automaticamente l'applicazione
-
-
- L'applicazione si avvierà automaticamente quando accedo a Windows
-
-
- Sfondo dell'applicazione
-
-
- Acrylic
-
-
- Lo sfondo dell'applicazione, nessuno, mica, a schede, acrilico
-
-
- Mica
-
-
- Nessuno
-
-
- A schede
-
-
- Verifica aggiornamenti
-
-
- Chiudi minimizza
-
-
- L'applicazione verrà ridotta a icona invece di essere chiusa
-
-
- Abilita il profilo desktop all'avvio
-
-
- Il profilo desktop verrà abilitato automaticamente all'avvio dell'applicazione
-
-
- Scarica
-
-
- Download in corso -
-
-
- Efficienza intelligente
-
-
- La modalità di efficienza intelligente riduce la priorità dei processi in background e migliora l'efficienza energetica
-
-
- Opzioni generali
-
-
- Installa ora
-
-
- Ultimo controllo:
-
-
- Opzioni di notifica
-
-
- Apri l'applicazione in background
-
-
- L'applicazione si avvierà inizialmente minimizzata e apparirà nella barra delle applicazioni
-
-
- Esterno
-
-
- Interno
-
-
- Opzioni del sensore
-
-
- Direzione di posizionamento del sensore esterno
-
-
- Seleziona su quale lato del dispositivo è stato montato il sensore
-
-
- Sensore esterno capovolto
-
-
- Il sensore è stato montato capovolto, possibile con convertitore USB-C
-
-
- Selezione del sensore
-
-
- Seleziona il sensore desiderato utilizzato per l'input di movimento
-
-
- Impostazioni
-
-
- Tipo di avvio
-
-
- Utilizzato dal gestore dei servizi per definire il tipo di avvio del servizio
-
-
- Potenza massima
-
-
- La potenza massima in watt fornita al processore
-
-
- Potenza minima
-
-
- La potenza minima in watt fornita al processore
-
-
- Sovrascrittura dell'intervallo di potenza configurabile (cTDP)
-
-
- Consente di modificare i valori di potenza minima e massima (TDP) al di là delle specifiche della CPU
-
-
- Scuro
-
-
- Chiaro
-
-
- Notifica a comparsa
-
-
- Ottieni notifiche dall'applicazione nel centro notifiche di Windows
-
-
- Aggiornamenti disponibili
-
-
- Controllo degli aggiornamenti in corso...
-
-
- Impossibile scaricare il file di aggiornamento.
-
-
- Impossibile raggiungere GitHub.
-
-
- Impossibile individuare il file di aggiornamento.
-
-
- Oops. Si è verificato un problema.
-
-
- Sei aggiornato
-
-
- Il controller è ora nascosto e gli input vengono inoltrati al controller virtuale
-
-
- Utente
-
-
- Esegui questo strumento come amministratore per sbloccare queste impostazioni
-
-
- ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
-
-
- Silenzia il controller virtuale
-
-
- Silenzia il controller virtuale nelle applicazioni correlate a Steam
-
-
- Impostazioni del controller
-
-
- Modifica le impostazioni del controller virtuale
-
-
- Antimuorto di movimento
-
-
- Compensa la zona morta in gioco, migliora la registrazione dei piccoli movimenti
-
-
- ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Migliora la circolarità dello stick
-
-
- Circolarità stick sinistro
-
-
- Circolarità stick destro
-
-
- Zona morta joystick % sinistro
-
-
- Regola la percentuale della zona morta interna ed esterna del joystick sinistro
-
-
- Zona morta joystick % destro
-
-
- Regola la percentuale della zona morta interna ed esterna del joystick destro
-
-
- Zona morta del trigger sinistro %
-
-
- Regola la percentuale della zona morta interna ed esterna del trigger sinistro
-
-
- Zona morta del trigger destro %
-
-
- Regola la percentuale della zona morta interna ed esterna del trigger destro
-
-
- Vibra il controller al collegamento
-
-
- Fai vibrare il controller fisico quando è collegato
-
-
- Layout desktop
-
-
- Passa al layout del controller desktop
-
-
- Mostra Centro notifiche
-
-
- Mostra e nasconde il Centro notifiche di Windows
-
-
- Layout del controller
-
-
- Sovrascrittura ventola
-
-
- Imposta il ciclo di dovere della ventola su un valore definito dall'utente
-
-
- Visualizzazione a schermo
-
-
- Abilita il supporto per la visualizzazione a schermo
-
-
- Riduci luminosità
-
-
- Riduci la luminosità corrente del display del 5%
-
-
- Riduci volume
-
-
- Riduci il volume del sistema del 5%
-
-
- Aumenta luminosità
-
-
- Aumenta volume
-
-
- Aumenta il volume del sistema del 5%
-
-
- TDP automatico
-
-
- Regolazione automatica del TDP in base al framerate misurato e al framerate target richiesto
-
-
- Obiettivo framerate
-
-
- Valore obiettivo del framerate desiderato per il controller TDP automatico
-
-
- Frequenza massima clock GPU
-
-
- Frequenza massima del clock della GPU in Mhz
-
-
- FPS
-
-
- Livello di visualizzazione sovrapposizione
-
-
- Cambia il livello di visualizzazione delle informazioni sulla sovrapposizione a schermo
-
-
- Frequenza di aggiornamento
-
-
- Cambia la frequenza di aggiornamento della sovrapposizione a schermo
-
-
- Limite framerate
-
-
- Limita il framerate per le applicazioni 3D
-
-
- Apri strumento di cattura
-
-
- Premi questi tasti: Windows + Shift + S
-
-
- Tasti di scelta rapida
-
-
- Usa impostazione di sistema
-
-
- A,B,X,Y
-
-
- GRIP POSTERIORI
-
-
- BUMPERS
-
-
- MENU
-
-
- OEM
-
-
- PAD DIREZIONALE
-
-
- JOYSTICK SINISTRO
-
-
- PULSANTI JOYSTICK SINISTRO
-
-
- JOYSTICK DESTRO
-
-
- PULSANTI JOYSTICK DESTRO
-
-
- TRACKPAD SINISTRO
-
-
- PULSANTI TRACKPAD SINISTRO
-
-
- TRACKPAD DESTRO
-
-
- PULSANTI TRACKPAD DESTRO
-
-
- TRIGGER SINISTRO
-
-
- PULSANTI TRIGGER SINISTRO
-
-
- TRIGGER DESTRO
-
-
- PULSANTI TRIGGER DESTRO
-
-
- Partner
-
-
- Produttore
-
-
- Nome prodotto
-
-
- Nessun controller fisico connesso
-
-
- Layout desktop
-
-
- Definisci layout desktop
-
-
- Definisci il layout del controller quando sei in modalità desktop
-
-
- Modifica
-
-
- Abilita layout desktop
-
-
- Layout di controller non da gioco
-
-
- Potresti voler fare clic su Connetti accanto al tuo controller collegato.
-
-
- Non hai nessun controller fisico collegato. Nessun input verrà inviato a HC o al suo servizio.
-
-
- Assicurati di aver collegato un dispositivo XInput o DInput compatibile.
-
-
- Nessun controller fisico rilevato
-
-
- Potresti voler avviare il servizio companion o assicurarti che lo stato del tuo controller virtuale sia impostato su: Connesso
-
-
- Il tuo controller fisico è nascosto, ma non hai a disposizione un controller virtuale. Nessun input verrà inviato ai giochi.
-
-
- Nessun controller virtuale rilevato
-
-
- Potresti voler attivare l'audio del tuo controller virtuale o rendere visibile il tuo controller fisico.
-
-
- Il tuo controller fisico è nascosto, ma hai attivato l'audio del tuo controller virtuale.
-
-
- Controller fisico nascosto
-
-
- Potresti voler nascondere il tuo controller fisico o disattivare l'audio del tuo controller virtuale.
-
-
- Il tuo controller fisico non è nascosto, ma hai un controller virtuale non silenziato. Potresti riscontrare input doppi nei giochi.
-
-
- Controller fisico non nascosto
-
-
- HD rumble
-
-
- Utilizza il motore di vibrazione ad alta definizione, a scapito di un utilizzo maggiore della CPU
-
-
- Impostazioni del controller
-
-
- Applica modello
-
-
- Pulsanti
-
-
- Annulla
-
-
- COMUNITÀ
-
-
- Conferma
-
-
- Pad direzionale
-
-
- Esporta per il controller attuale
-
-
- Esporta layout
-
-
- Giroscopio
-
-
- Joystick
-
-
- Autore layout
-
-
- Descrizione layout
-
-
- Titolo layout
-
-
- Salva informazioni di gioco con il layout
-
-
- Mostra solo i modelli del controller attuale
-
-
- Selezionatore di modelli di layout
-
-
- MODELLI
-
-
- Trackpad
-
-
- Trigger
-
-
- ms
-
-
- Disabilitato
-
-
- Esteso
-
-
- Completo
-
-
- Minimale
-
-
- Cambia il layout del controller virtuale
-
-
- CPU
-
-
- Preferenza di prestazioni energetiche (EPP)
-
-
- Bilanciamento della potenza CPU/GPU
-
-
- Specifica la politica di distribuzione della potenza tra CPU e GPU
-
-
- GPU
-
-
- Target del limite di potenza
-
-
- Orientamento display nativo
-
-
- Alcune funzionalità dipendono dalla corretta rilevazione dell'orientamento del display per funzionare correttamente. Se ciò non è stato rilevato correttamente, impostare l'orientamento del display sulla stessa orientamento del tuo controller, quindi fare clic su Rileva
-
-
- Rileva
-
-
- Non impostato
-
-
- Increase the current display brightness by 5%
-
-
- Power limit target
-
-
- Quicktools options
-
-
- %
-
-
- Set current CPU boost mode
-
-
- CPU boost mode
-
-
- Set the fan duty cycle to user-defined value
-
-
- Fan override
-
-
- Adjust main display resolution and refresh rate
-
-
- Display resolution and refresh rate
-
-
- Top right
-
-
- Top left
-
-
- Window location
-
-
- Bottom right
-
-
- Bottom left
-
-
- Power options
-
-
- Define quicktools window location
-
-
- Third-party applications
-
-
- None
-
-
- Quicktools backdrop, none, mica, tabbed, acrylic
-
-
- Automatically turn RTSS off when companion is closed
-
-
- Automatically turn HWiNFO off when companion is closed
-
-
- HWiNFO
-
-
- Default
-
-
- Current profile:
-
-
- RivaTuner Statistics Server
-
-
- Automatically hide quick tools when the user clicks outside of window
-
-
- Hide when loses focus
-
-
- Questo input funzionerà come un semplice joystick. Ideale per laptop e dispositivi portatili di tipo clamshell, lo scambio automatico di rollio di beccheggio in base al modo in cui il dispositivo viene tenuto (aperto a 90 o 180 gradi).
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Croce
-
-
- Cerchio
-
-
- Quadrato
-
-
- Triangolo
-
-
- Condividi
-
-
- Sony
-
-
- Opzioni
-
-
- Controller DualShock 4 emulato
-
-
- Nessun controller emulato
-
-
- Controller XBOX 360 emulato
-
-
- Connesso
-
-
- Disconnesso
-
-
- Scambio automatico beccheggio-rollio
-
-
- Joystick telecamera
-
-
- Joystick sterzo
-
-
- Spazio del giocatore
-
-
- Handheld Companion
-
-
- Overlay
-
-
- Strumenti rapidi
-
-
- Windows
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- Vista
-
-
- Menu
-
-
- Joystick sinistro
-
-
- Joystick destro
-
-
- Questo è il tuo profilo controller predefinito. Questo profilo verrà applicato a tutte le tue applicazioni che non hanno un profilo specifico. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
-
-
- Oops. Sembra che questo profilo non abbia un'eseguibile. Come è possibile?
-
-
- Oops. Sembra che questo profilo non abbia un percorso per l'applicazione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
-
-
- Oops. Sembra che tu non abbia il livello di autorizzazione necessario per modificare il contenuto di questa applicazione. Assicurati di aver avviato questo programma in modalità amministratore.
-
-
- Niente da vedere qui.
-
-
- Oops. Sembra che l'eseguibile di questo profilo sia in esecuzione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
-
-
- Predefinito
-
-
- Eco
-
-
- Alta
-
-
- Automatico
-
-
- Disabilitato
-
-
- Manuale
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- Vista
-
-
- LB
-
-
- RB
-
-
- Guida
-
-
- Menu
-
-
- Questo input funzionerà come un semplice joystick. È destinato alle applicazioni joystick tradizionali
-
-
- Questo input funzionerà come un joystick ottimizzato per il controllo di un volante o un gioco di guida
-
-
- Questo input funzionerà come un joystick ottimizzato per il controllo di una telecamera in prima o terza persona
-
-
- Handheld Companion
-
-
- Opzioni
-
-
- STEAM
-
-
- Centro comandi
-
-
- Cassetta dell'armatura
-
-
- M1
-
-
- Win
-
-
- Esc
-
-
- Tastiera
-
-
- Personalizzato
-
-
- Dispositivo
-
-
- Scambio automatico beccheggio-rollio
-
-
- Joystick telecamera
-
-
- Joystick sterzo
-
-
- Spazio del giocatore
-
-
- Joystick sinistro
-
-
- Joystick destro
-
-
- L2
-
-
- Levetta sinistra
-
-
- R2
-
-
- Levetta destra
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- Pulsante D-Pad giù
-
-
- Pulsante D-Pad sinistra
-
-
- Pulsante D-Pad destra
-
-
- Pulsante D-Pad su
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Levetta sinistra
-
-
- Levetta sinistra giù
-
-
- Levetta sinistra sinistra
-
-
- Levetta sinistra destra
-
-
- Levetta sinistra su
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Levetta destra
-
-
- Levetta destra giù
-
-
- Levetta destra sinistra
-
-
- Levetta destra destra
-
-
- Levetta destra su
-
-
- A
-
-
- Always On
-
-
- B
-
-
- Indietro
-
-
- Pulsante D-Pad giù
-
-
- Pulsante D-Pad sinistra
-
-
- Pulsante D-Pad destra
-
-
- Pulsante D-Pad su
-
-
- Spalla sinistra
-
-
- Levetta sinistra
-
-
- Grilletto sinistro
-
-
- Spalla destra
-
-
- Levetta destra
-
-
- Grilletto destro
-
-
- Avvio
-
-
- X
-
-
- Y
-
-
- Oops. Sembra che questo profilo sia già in esecuzione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- S
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- LeftStick
-
-
- RightStick
-
-
- Yes
-
-
- No
-
-
- Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
-
-
- Warning
-
-
- Disabled
-
-
- Injection (recommended)
-
-
- Redirection
-
-
- Improve virtual controller detection
-
-
- Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
-
-
- Yes
-
-
- No
-
-
- Your device must be restarted in order for the changes to take effect. Would you like to restart now?
-
-
- Restart required
-
-
- Yes
-
-
- No
-
-
- Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
-
-
- Warning
-
-
- M
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Back
-
-
- Exit
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- External
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Informazioni
+
+
+ Una combinazione di un servizio Windows e un'interfaccia touch ottimizzata per migliorare la tua esperienza con il computer portatile da gioco. Le funzionalità includono: controllo del movimento, simulazione del controller virtuale, sovrapposizione di strumenti rapidi, touchpad virtuali, modello di controller 3D, sistema di impostazioni del profilo basato sull'applicazione. Handheld Companion si basa sul driver ViGEmBus e sulle librerie ViGEmClient, nonché sul driver del filtro di livello kernel HidHide. Gli algoritmi di controllo del movimento si basano sul lavoro di Jibbsmart e sulle informazioni disponibili su GyroWiki.
+
+
+ Accelerometro
+
+
+ Autore
+
+
+ Contributori
+
+
+ Descrizione
+
+
+ Donazioni
+
+
+ Giroscopio
+
+
+ Inclinometro
+
+
+ N/D
+
+
+ Link correlati
+
+
+ Esterno
+
+
+ Interno
+
+
+ Nome del sensore
+
+
+ Specifiche del sensore
+
+
+ Servizio
+
+
+ Codice sorgente
+
+
+ Versione
+
+
+ Wiki
+
+
+ Amministratore
+
+
+ Nascondi controller al collegamento
+
+
+ Nascondi il controller fisico quando è collegato
+
+
+ Collega
+
+
+ Controller
+
+
+ Nascondi controller
+
+
+ Impostazioni controller
+
+
+ Disconnetti
+
+
+ Dispositivi di input
+
+
+ Ripristina visibilità controller alla chiusura
+
+
+ Ripristina la visibilità di tutti i controller fisici quando l'applicazione viene chiusa
+
+
+ Intensità vibrazione
+
+
+ Cambia l'intensità della vibrazione del controller
+
+
+
+ ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Riduci limite di potenza termica (TDP)
+
+
+ Riduci il TDP del sistema o del profilo correntemente applicato di un watt
+
+
+ Premi per definire il trigger
+
+
+ Premi per definire l'output della tastiera
+
+
+ Aumenta limite di potenza termica (TDP)
+
+
+ Aumenta il TDP del sistema o del profilo correntemente applicato di un watt
+
+
+ Mostra controller 3D
+
+
+ Cambia l'hotkey del controller 3D premendo un pulsante o un tasto speciale
+
+
+ Mostra trackpad virtuali
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Richiama finestra strumenti rapidi
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Scorciatoia personalizzata
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Mostra e nascondi il desktop
+
+
+ Premi questa combinazione di tasti: Windows + D
+
+
+ Tasto Escape
+
+
+ Premi questo tasto: Escape
+
+
+ Passa da finestra a schermo intero
+
+
+ Premi questa combinazione di tasti: Alt + Enter
+
+
+ Pulsante Guide o PS
+
+
+ Simula l'input di un pulsante Guide di Xbox o PS di Sony
+
+
+ Mostra tastiera touch
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Forza la chiusura dell'applicazione
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Mostra e nascondi finestra principale
+
+
+ Cambia l'hotkey premendo un pulsante o un tasto speciale
+
+
+ Apri Task Manager
+
+
+ Premi questa combinazione di tasti: Ctrl + Shift + Esc
+
+
+ Apri visualizzazione attività
+
+
+ Premi questa combinazione di tasti: Windows + Tab
+
+
+ Attiva/disattiva sospensione
+
+
+ Sospendi o riprendi l'applicazione in primo piano
+
+
+ Handheld Companion
+
+
+ Informazioni
+
+
+ Controller
+
+
+ Overlay
+
+
+ Profili
+
+
+ OK
+
+
+ Impostazioni
+
+
+ 8BitDo Lite 2
+
+
+ Allineamento
+
+
+ Cambia l'allineamento dell'overlay del controller 3D
+
+
+ Cambia l'allineamento dell'overlay dei trackpad
+
+
+ Sempre in primo piano
+
+
+ Quando attivato, l'overlay del controller 3D rimarrà sempre in primo piano rispetto alle altre finestre
+
+
+ Indietro
+
+
+ Inquadra la fotocamera
+
+
+ Cambia il comportamento del modello dell'overlay del controller 3D per inquadrare la fotocamera
+
+
+ Pitch fisso
+
+
+ Cambia l'angolo, in gradi
+
+
+ Colore sfondo
+
+
+ Cambia il colore di sfondo dell'overlay del controller 3D
+
+
+ Opzioni del controller
+
+
+ PlayStation DualSense
+
+
+ Controller emulato
+
+
+ Inquadra la fotocamera
+
+
+ Il modello 3D ruota lentamente per inquadrare la fotocamera come posizione predefinita
+
+
+ In ascolto...
+
+
+ MACHENIKE HG510
+
+
+ Pulsante principale
+
+
+ Cambia il pulsante principale dell'overlay del controller 3D
+
+
+ Movimento
+
+
+ Il modello si muoverà in base ai movimenti dell'utente basati sulle informazioni dei sensori
+
+
+ N64
+
+
+ Controller OEM
+
+
+ Opacità
+
+
+ Cambia l'opacità dell'overlay del controller 3D
+
+
+ Cambia l'opacità dell'overlay dei trackpad
+
+
+ Overlay
+
+
+ Modello overlay
+
+
+ Cambia il modello dell'overlay del controller 3D
+
+
+ Anteprima overlay
+
+
+ Impostazioni di rendering
+
+
+ Anti-Aliasing
+
+
+ Cambia lo stato dell'anti-aliasing del rendering
+
+
+ Cambia le impostazioni di rendering del modello del tuo controller 3D overlay stazionario
+
+
+ Frequenza di aggiornamento
+
+
+ Cambia la frequenza di aggiornamento del rendering, in aggiornamenti al secondo
+
+
+ Dimensioni
+
+
+ Cambia le dimensioni dell'overlay del controller 3D
+
+
+ Cambia le dimensioni dell'overlay dei trackpad
+
+
+ Avvia
+
+
+ Controller Fisher-Price
+
+
+ Opzioni dei trackpad
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ Overlay
+
+
+ Riprendi
+
+
+ Sospendi
+
+
+ Impostazioni aggiuntive
+
+
+ Moltiplicatore movimento mira
+
+
+ Pulsante di attivazione
+
+
+ Un moltiplicatore di sensibilità del movimento aggiuntivo quando si mira o si utilizza un mirino attraverso l'uso del pulsante di attivazione configurato
+
+
+ Valore moltiplicatore
+
+
+ Opzioni fotocamera
+
+
+ Curva di risposta personalizzata
+
+
+ Uscita inviata al gioco
+
+
+ Intensità del movimento
+
+
+ Aggressivo
+
+
+ Predefinito
+
+
+ Opzioni predefinite
+
+
+ Preciso
+
+
+ Durata flick
+
+
+ Cambia la durata del flick, calibra per una rotazione di 180 gradi, in millisecondi
+
+
+ Flick stick (sperimentale)
+
+
+ Punta la fotocamera nella direzione del flick del joystick (destro), ruota la fotocamera esclusivamente nel piano orizzontale ruotando
+
+
+ Abilita flick stick
+
+
+ Sensibilità
+
+
+ Cambia la sensibilità del movimento dell'asse orizzontale e verticale
+
+
+ Sensibilità X
+
+
+ Cambia la sensibilità del movimento dell'asse orizzontale
+
+
+ Sensibilità Y
+
+
+ Cambia la sensibilità del movimento dell'asse verticale
+
+
+ Sensibilità del joystick
+
+
+ Cambia la velocità di rotazione
+
+
+ Impostazioni aggiuntive
+
+
+ Zona morta
+
+
+ Cambia la zona morta dello sterzo, in gradi. Migliora la rettilineità dello sterzo
+
+
+ Input joystick gioco
+
+
+ Sterzo joystick
+
+
+ Opzioni sterzo joystick
+
+
+ Anteprima sterzo joystick
+
+
+ Angolo massimo di sterzo
+
+
+ Cambia il valore massimo dell'angolo di sterzo, in gradi
+
+
+ Linearità dello sterzo
+
+
+ Mappatura tra input e sterzo. Valori più bassi forniscono maggiore precisione vicino alla massima rotazione ma minore precisione vicino al centro. Valori più alti forniscono maggiore precisione vicino al centro ma minore precisione vicino alla massima rotazione. 1.0 è una mappatura lineare
+
+
+ Moltiplicatore accelerometro
+
+
+ Cambia il valore dell'accelerometro riportato dal sistema
+
+
+ Impostazioni aggiuntive
+
+
+ Anti-zona morta
+
+
+ Cambia l'anti-zona morta nel gioco, in percentuale
+
+
+ %
+
+
+ Sei sicuro di voler eliminare?
+
+
+ Questo elemento verrà eliminato immediatamente. Non è possibile annullare questa azione.
+
+
+ Sei sicuro di voler sovrascrivere questo profilo?
+
+
+ {0} sarà sovrascritto. Non è possibile annullare questa azione.
+
+
+ Limite potenza boost
+
+
+ Cambia il limite di potenza termica del boost
+
+
+ Annulla
+
+
+ Crea un nuovo profilo
+
+
+ Elimina
+
+
+ Elimina profilo
+
+
+ Profilo utente per gioco
+
+
+ Il profilo verrà applicato automaticamente quando verrà rilevata l'applicazione associata
+
+
+ Impostazioni globali
+
+
+ Cambia le impostazioni globali dei profili
+
+
+ Moltiplicatore giroscopio
+
+
+ Cambia il valore del giroscopio riportato dal sistema
+
+
+ Asse sterzo giroscopio
+
+
+ Per il controllo del movimento orizzontale del controller, puoi utilizzare l'asse di imbardata o rollio
+
+
+ Inverti asse orizzontale
+
+
+ Inverti asse verticale
+
+
+ Impostazioni controllo del movimento
+
+
+ Cambia le impostazioni globali del controllo del movimento
+
+
+ OK
+
+
+ Impostazioni alimentazione
+
+
+ Cambia le impostazioni di alimentazione
+
+
+ Dettagli profilo
+
+
+ Nome profilo
+
+
+ Percorso profilo
+
+
+ Profili
+
+
+ Selezione profilo
+
+
+ Seleziona il profilo che desideri modificare
+
+
+ Impostazioni profilo
+
+
+ Profilo aggiornato
+
+
+ è stato aggiornato.
+
+
+ Rollio
+
+
+ X
+
+
+ Y
+
+
+ Stile di input
+
+
+ I comandi fisici del controller possono essere programmati per agire come diversi tipi di dispositivi
+
+
+ Dispositivo di output
+
+
+ Seleziona il dispositivo che riceverà i comandi di movimento
+
+
+ Limite di potenza sostenuta
+
+
+ Cambia il limite di potenza termica sostenuta
+
+
+ Limite di potenza termica (TDP)
+
+
+ Limita la potenza del processore per una potenza totale inferiore
+
+
+ Abilita il controller di movimento universale
+
+
+ Disattivato, attiva con il pulsante(i)
+
+
+ Attivato, disattiva con il pulsante(i)
+
+
+ Attivazione movimento
+
+
+ Con l'input di movimento disabilitato, utilizza il/i pulsante/i selezionato/i per abilitare il movimento, con l'input di movimento abilitato, utilizza il/i pulsante/i selezionato/i per disabilitare il movimento.
+
+
+ Seleziona il dispositivo che riceverà i comandi di movimento
+
+
+ Impostazioni del controllo di movimento universale
+
+
+ Traduci i movimenti del dispositivo in input del controller
+
+
+ Aggiorna profilo
+
+
+ Consenti all'applicazione di accedere al controller fisico del dispositivo
+
+
+ Compatibilità estesa (XInputPlus)
+
+
+ Giro
+
+
+ Sì
+
+
+ Disconnetti
+
+
+ Controllo manuale dell'orologio della GPU
+
+
+ Imposta la GPU su un orologio fisso
+
+
+ MHz
+
+
+ Modalità di alimentazione
+
+
+ Bilanciata
+
+
+ Ottimizza il dispositivo in base all'utilizzo dell'alimentazione e alle prestazioni
+
+
+ Efficienza
+
+
+ Prestazioni
+
+
+ Boost
+
+
+ Limite di potenza termica (TDP)
+
+
+ Limita la potenza del processore per una potenza totale inferiore
+
+
+ Il limite di potenza termica è sovrascritto da un profilo
+
+
+ Sostenuta
+
+
+ W
+
+
+ Crea profilo
+
+
+ In attesa del processo in primo piano...
+
+
+ Fornisce supporto per giroscopio e accelerometro ai computer portatili per il gioco con Windows tramite un controller virtuale. Se il servizio è abilitato, il controller integrato sarà nascosto alle applicazioni al di fuori della whitelist. Se il servizio è disabilitato, il controller integrato sarà visibile e il controller virtuale sarà disabilitato.
+
+
+ Controller Service
+
+
+ Lingua
+
+
+ La lingua dell'applicazione
+
+
+ Riavvio necessario
+
+
+ Per rendere effettive le modifiche, riavviare l'applicazione
+
+
+ Tema dell'applicazione
+
+
+ Il tema dell'applicazione, modalità chiara o scura
+
+
+ Avvia automaticamente l'applicazione
+
+
+ L'applicazione si avvierà automaticamente quando accedo a Windows
+
+
+ Sfondo dell'applicazione
+
+
+ Acrylic
+
+
+ Lo sfondo dell'applicazione, nessuno, mica, a schede, acrilico
+
+
+ Mica
+
+
+ Nessuno
+
+
+ A schede
+
+
+ Verifica aggiornamenti
+
+
+ Chiudi minimizza
+
+
+ L'applicazione verrà ridotta a icona invece di essere chiusa
+
+
+ Abilita il profilo desktop all'avvio
+
+
+ Il profilo desktop verrà abilitato automaticamente all'avvio dell'applicazione
+
+
+ Scarica
+
+
+ Download in corso -
+
+
+ Efficienza intelligente
+
+
+ La modalità di efficienza intelligente riduce la priorità dei processi in background e migliora l'efficienza energetica
+
+
+ Opzioni generali
+
+
+ Installa ora
+
+
+ Ultimo controllo:
+
+
+ Opzioni di notifica
+
+
+ Apri l'applicazione in background
+
+
+ L'applicazione si avvierà inizialmente minimizzata e apparirà nella barra delle applicazioni
+
+
+ Esterno
+
+
+ Interno
+
+
+ Opzioni del sensore
+
+
+ Direzione di posizionamento del sensore esterno
+
+
+ Seleziona su quale lato del dispositivo è stato montato il sensore
+
+
+ Sensore esterno capovolto
+
+
+ Il sensore è stato montato capovolto, possibile con convertitore USB-C
+
+
+ Selezione del sensore
+
+
+ Seleziona il sensore desiderato utilizzato per l'input di movimento
+
+
+ Impostazioni
+
+
+ Tipo di avvio
+
+
+ Utilizzato dal gestore dei servizi per definire il tipo di avvio del servizio
+
+
+ Potenza massima
+
+
+ La potenza massima in watt fornita al processore
+
+
+ Potenza minima
+
+
+ La potenza minima in watt fornita al processore
+
+
+ Sovrascrittura dell'intervallo di potenza configurabile (cTDP)
+
+
+ Consente di modificare i valori di potenza minima e massima (TDP) al di là delle specifiche della CPU
+
+
+ Scuro
+
+
+ Chiaro
+
+
+ Notifica a comparsa
+
+
+ Ottieni notifiche dall'applicazione nel centro notifiche di Windows
+
+
+ Aggiornamenti disponibili
+
+
+ Controllo degli aggiornamenti in corso...
+
+
+ Impossibile scaricare il file di aggiornamento.
+
+
+ Impossibile raggiungere GitHub.
+
+
+ Impossibile individuare il file di aggiornamento.
+
+
+ Oops. Si è verificato un problema.
+
+
+ Sei aggiornato
+
+
+ Il controller è ora nascosto e gli input vengono inoltrati al controller virtuale
+
+
+ Utente
+
+
+ Esegui questo strumento come amministratore per sbloccare queste impostazioni
+
+
+ ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+
+ Silenzia il controller virtuale
+
+
+ Silenzia il controller virtuale nelle applicazioni correlate a Steam
+
+
+ Impostazioni del controller
+
+
+ Modifica le impostazioni del controller virtuale
+
+
+ Antimuorto di movimento
+
+
+ Compensa la zona morta in gioco, migliora la registrazione dei piccoli movimenti
+
+
+ ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Migliora la circolarità dello stick
+
+
+ Circolarità stick sinistro
+
+
+ Circolarità stick destro
+
+
+ Zona morta joystick % sinistro
+
+
+ Regola la percentuale della zona morta interna ed esterna del joystick sinistro
+
+
+ Zona morta joystick % destro
+
+
+ Regola la percentuale della zona morta interna ed esterna del joystick destro
+
+
+ Zona morta del trigger sinistro %
+
+
+ Regola la percentuale della zona morta interna ed esterna del trigger sinistro
+
+
+ Zona morta del trigger destro %
+
+
+ Regola la percentuale della zona morta interna ed esterna del trigger destro
+
+
+ Vibra il controller al collegamento
+
+
+ Fai vibrare il controller fisico quando è collegato
+
+
+ Layout desktop
+
+
+ Passa al layout del controller desktop
+
+
+ Mostra Centro notifiche
+
+
+ Mostra e nasconde il Centro notifiche di Windows
+
+
+ Layout del controller
+
+
+ Sovrascrittura ventola
+
+
+ Imposta il ciclo di dovere della ventola su un valore definito dall'utente
+
+
+ Visualizzazione a schermo
+
+
+ Abilita il supporto per la visualizzazione a schermo
+
+
+ Riduci luminosità
+
+
+ Riduci la luminosità corrente del display del 5%
+
+
+ Riduci volume
+
+
+ Riduci il volume del sistema del 5%
+
+
+ Aumenta luminosità
+
+
+ Aumenta volume
+
+
+ Aumenta il volume del sistema del 5%
+
+
+ TDP automatico
+
+
+ Regolazione automatica del TDP in base al framerate misurato e al framerate target richiesto
+
+
+ Obiettivo framerate
+
+
+ Valore obiettivo del framerate desiderato per il controller TDP automatico
+
+
+ Frequenza massima clock GPU
+
+
+ Frequenza massima del clock della GPU in Mhz
+
+
+ FPS
+
+
+ Livello di visualizzazione sovrapposizione
+
+
+ Cambia il livello di visualizzazione delle informazioni sulla sovrapposizione a schermo
+
+
+ Frequenza di aggiornamento
+
+
+ Cambia la frequenza di aggiornamento della sovrapposizione a schermo
+
+
+ Limite framerate
+
+
+ Limita il framerate per le applicazioni 3D
+
+
+ Apri strumento di cattura
+
+
+ Premi questi tasti: Windows + Shift + S
+
+
+ Tasti di scelta rapida
+
+
+ Usa impostazione di sistema
+
+
+ A,B,X,Y
+
+
+ GRIP POSTERIORI
+
+
+ BUMPERS
+
+
+ MENU
+
+
+ OEM
+
+
+ PAD DIREZIONALE
+
+
+ JOYSTICK SINISTRO
+
+
+ PULSANTI JOYSTICK SINISTRO
+
+
+ JOYSTICK DESTRO
+
+
+ PULSANTI JOYSTICK DESTRO
+
+
+ TRACKPAD SINISTRO
+
+
+ PULSANTI TRACKPAD SINISTRO
+
+
+ TRACKPAD DESTRO
+
+
+ PULSANTI TRACKPAD DESTRO
+
+
+ TRIGGER SINISTRO
+
+
+ PULSANTI TRIGGER SINISTRO
+
+
+ TRIGGER DESTRO
+
+
+ PULSANTI TRIGGER DESTRO
+
+
+ Partner
+
+
+ Produttore
+
+
+ Nome prodotto
+
+
+ Nessun controller fisico connesso
+
+
+ Layout desktop
+
+
+ Definisci layout desktop
+
+
+ Definisci il layout del controller quando sei in modalità desktop
+
+
+ Modifica
+
+
+ Abilita layout desktop
+
+
+ Layout di controller non da gioco
+
+
+ Potresti voler fare clic su Connetti accanto al tuo controller collegato.
+
+
+ Non hai nessun controller fisico collegato. Nessun input verrà inviato a HC o al suo servizio.
+
+
+ Assicurati di aver collegato un dispositivo XInput o DInput compatibile.
+
+
+ Nessun controller fisico rilevato
+
+
+ Potresti voler avviare il servizio companion o assicurarti che lo stato del tuo controller virtuale sia impostato su: Connesso
+
+
+ Il tuo controller fisico è nascosto, ma non hai a disposizione un controller virtuale. Nessun input verrà inviato ai giochi.
+
+
+ Nessun controller virtuale rilevato
+
+
+ Potresti voler attivare l'audio del tuo controller virtuale o rendere visibile il tuo controller fisico.
+
+
+ Il tuo controller fisico è nascosto, ma hai attivato l'audio del tuo controller virtuale.
+
+
+ Controller fisico nascosto
+
+
+ Potresti voler nascondere il tuo controller fisico o disattivare l'audio del tuo controller virtuale.
+
+
+ Il tuo controller fisico non è nascosto, ma hai un controller virtuale non silenziato. Potresti riscontrare input doppi nei giochi.
+
+
+ Controller fisico non nascosto
+
+
+ HD rumble
+
+
+ Utilizza il motore di vibrazione ad alta definizione, a scapito di un utilizzo maggiore della CPU
+
+
+ Impostazioni del controller
+
+
+ Applica modello
+
+
+ Pulsanti
+
+
+ Annulla
+
+
+ COMUNITÀ
+
+
+ Conferma
+
+
+ Pad direzionale
+
+
+ Esporta per il controller attuale
+
+
+ Esporta layout
+
+
+ Giroscopio
+
+
+ Joystick
+
+
+ Autore layout
+
+
+ Descrizione layout
+
+
+ Titolo layout
+
+
+ Salva informazioni di gioco con il layout
+
+
+ Mostra solo i modelli del controller attuale
+
+
+ Selezionatore di modelli di layout
+
+
+ MODELLI
+
+
+ Trackpad
+
+
+ Trigger
+
+
+ ms
+
+
+ Disabilitato
+
+
+ Esteso
+
+
+ Completo
+
+
+ Minimale
+
+
+ Cambia il layout del controller virtuale
+
+
+ CPU
+
+
+ Preferenza di prestazioni energetiche (EPP)
+
+
+ Bilanciamento della potenza CPU/GPU
+
+
+ Specifica la politica di distribuzione della potenza tra CPU e GPU
+
+
+ GPU
+
+
+ Target del limite di potenza
+
+
+ Orientamento display nativo
+
+
+ Alcune funzionalità dipendono dalla corretta rilevazione dell'orientamento del display per funzionare correttamente. Se ciò non è stato rilevato correttamente, impostare l'orientamento del display sulla stessa orientamento del tuo controller, quindi fare clic su Rileva
+
+
+ Rileva
+
+
+ Non impostato
+
+
+ Increase the current display brightness by 5%
+
+
+ Power limit target
+
+
+ Quicktools options
+
+
+ %
+
+
+ Set current CPU boost mode
+
+
+ CPU boost mode
+
+
+ Set the fan duty cycle to user-defined value
+
+
+ Fan override
+
+
+ Adjust main display resolution and refresh rate
+
+
+ Display resolution and refresh rate
+
+
+ Top right
+
+
+ Top left
+
+
+ Window location
+
+
+ Bottom right
+
+
+ Bottom left
+
+
+ Power options
+
+
+ Define quicktools window location
+
+
+ Third-party applications
+
+
+ None
+
+
+ Quicktools backdrop, none, mica, tabbed, acrylic
+
+
+ Automatically turn RTSS off when companion is closed
+
+
+ Default
+
+
+ Current profile:
+
+
+ RivaTuner Statistics Server
+
+
+ Automatically hide quick tools when the user clicks outside of window
+
+
+ Hide when loses focus
+
+
+ Questo input funzionerà come un semplice joystick. Ideale per laptop e dispositivi portatili di tipo clamshell, lo scambio automatico di rollio di beccheggio in base al modo in cui il dispositivo viene tenuto (aperto a 90 o 180 gradi).
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Croce
+
+
+ Cerchio
+
+
+ Quadrato
+
+
+ Triangolo
+
+
+ Condividi
+
+
+ Sony
+
+
+ Opzioni
+
+
+ Controller DualShock 4 emulato
+
+
+ Nessun controller emulato
+
+
+ Controller XBOX 360 emulato
+
+
+ Connesso
+
+
+ Disconnesso
+
+
+ Scambio automatico beccheggio-rollio
+
+
+ Joystick telecamera
+
+
+ Joystick sterzo
+
+
+ Spazio del giocatore
+
+
+ Handheld Companion
+
+
+ Overlay
+
+
+ Strumenti rapidi
+
+
+ Windows
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ Vista
+
+
+ Menu
+
+
+ Joystick sinistro
+
+
+ Joystick destro
+
+
+ Questo è il tuo profilo controller predefinito. Questo profilo verrà applicato a tutte le tue applicazioni che non hanno un profilo specifico. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
+
+
+ Oops. Sembra che questo profilo non abbia un'eseguibile. Come è possibile?
+
+
+ Oops. Sembra che questo profilo non abbia un percorso per l'applicazione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
+
+
+ Oops. Sembra che tu non abbia il livello di autorizzazione necessario per modificare il contenuto di questa applicazione. Assicurati di aver avviato questo programma in modalità amministratore.
+
+
+ Niente da vedere qui.
+
+
+ Oops. Sembra che l'eseguibile di questo profilo sia in esecuzione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
+
+
+ Predefinito
+
+
+ Eco
+
+
+ Alta
+
+
+ Automatico
+
+
+ Disabilitato
+
+
+ Manuale
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ Vista
+
+
+ LB
+
+
+ RB
+
+
+ Guida
+
+
+ Menu
+
+
+ Questo input funzionerà come un semplice joystick. È destinato alle applicazioni joystick tradizionali
+
+
+ Questo input funzionerà come un joystick ottimizzato per il controllo di un volante o un gioco di guida
+
+
+ Questo input funzionerà come un joystick ottimizzato per il controllo di una telecamera in prima o terza persona
+
+
+ Handheld Companion
+
+
+ Opzioni
+
+
+ STEAM
+
+
+ Centro comandi
+
+
+ Cassetta dell'armatura
+
+
+ M1
+
+
+ Win
+
+
+ Esc
+
+
+ Tastiera
+
+
+ Personalizzato
+
+
+ Dispositivo
+
+
+ Scambio automatico beccheggio-rollio
+
+
+ Joystick telecamera
+
+
+ Joystick sterzo
+
+
+ Spazio del giocatore
+
+
+ Joystick sinistro
+
+
+ Joystick destro
+
+
+ L2
+
+
+ Levetta sinistra
+
+
+ R2
+
+
+ Levetta destra
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ Pulsante D-Pad giù
+
+
+ Pulsante D-Pad sinistra
+
+
+ Pulsante D-Pad destra
+
+
+ Pulsante D-Pad su
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Levetta sinistra
+
+
+ Levetta sinistra giù
+
+
+ Levetta sinistra sinistra
+
+
+ Levetta sinistra destra
+
+
+ Levetta sinistra su
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Levetta destra
+
+
+ Levetta destra giù
+
+
+ Levetta destra sinistra
+
+
+ Levetta destra destra
+
+
+ Levetta destra su
+
+
+ A
+
+
+ Always On
+
+
+ B
+
+
+ Indietro
+
+
+ Pulsante D-Pad giù
+
+
+ Pulsante D-Pad sinistra
+
+
+ Pulsante D-Pad destra
+
+
+ Pulsante D-Pad su
+
+
+ Spalla sinistra
+
+
+ Levetta sinistra
+
+
+ Grilletto sinistro
+
+
+ Spalla destra
+
+
+ Levetta destra
+
+
+ Grilletto destro
+
+
+ Avvio
+
+
+ X
+
+
+ Y
+
+
+ Oops. Sembra che questo profilo sia già in esecuzione. Alcune opzioni che richiedono un'eseguibile potrebbero essere disabilitate.
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ LeftStick
+
+
+ RightStick
+
+
+ Yes
+
+
+ No
+
+
+ Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
+
+
+ Warning
+
+
+ Disabled
+
+
+ Injection (recommended)
+
+
+ Redirection
+
+
+ Improve virtual controller detection
+
+
+ Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
+
+
+ Yes
+
+
+ No
+
+
+ Your device must be restarted in order for the changes to take effect. Would you like to restart now?
+
+
+ Restart required
+
+
+ Yes
+
+
+ No
+
+
+ Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
+
+
+ Warning
+
+
+ M
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Back
+
+
+ Exit
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ External
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.ja-JP.resx b/HandheldCompanion/Properties/Resources.ja-JP.resx
index 49a98c992..1882c5cf6 100644
--- a/HandheldCompanion/Properties/Resources.ja-JP.resx
+++ b/HandheldCompanion/Properties/Resources.ja-JP.resx
@@ -1,2359 +1,2353 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- 概要
-
-
- >Windows サービスとタッチ インターフェイスに最適化された GUI の組み合わせにより、ハンドヘルド ゲーム コンピューターのエクスペリエンスが向上します。機能には、ジャイロ コントロール、仮想コントローラ シミュレーション、クイック ツール オーバーレイ、仮想タッチパッド、3D コントローラ モデル、アプリケーションごとのベースのプロファイル設定システムが含まれます。Handheld Companion は、ViGEmBus ドライバーと ViGEmClient ライブラリ、および HidHide カーネル モード フィルター ドライバーに依存しています。モーション コントロール アルゴリズムは、Jibbsmart による研究と GyroWiki で入手可能な情報に基づいています。
-
-
- 加速度計
-
-
- 作成者
-
-
- 貢献者
-
-
- 説明
-
-
- 寄付する
-
-
- ジャイロ
-
-
- 傾き
-
-
- 該当なし
-
-
- 関連リンク
-
-
- External
-
-
- Internal
-
-
- センサー名
-
-
- センサー仕様
-
-
- サービス
-
-
- ソースコード
-
-
- バージョン
-
-
- Wiki
-
-
- 管理者
-
-
- 接続時にコントローラーを非表示にする
-
-
- 接続時に物理コントローラーを非表示にする
-
-
- 接続
-
-
- コントローラ
-
-
- コントローラを隠す
-
-
- コントローラー設定
-
-
- 切断
-
-
- 入力デバイス
-
-
- >閉じるときにコントローラを再表示する
-
-
- アプリケーションの終了時にすべての物理コントローラーを復元
-
-
- 振動の強さ
-
-
- コントローラーの振動の強さを変更
-
-
-
- ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- TDPを下げる
-
-
- システムまたは現在適用されているプロファイルの TDP を 1 ワット減少
-
-
- 押してホットキー入力を設定
-
-
- 押してキーボード出力を設定
-
-
- TDPを上げる
-
-
- システムまたは現在適用されているプロファイルの TDP を 1 ワット増加
-
-
- 3D コントローラーを表示
-
-
- ボタンまたは特殊キーを押して 3D ホットキーを変更
-
-
- 仮想トラックパッドを表示する
-
-
- ボタンまたは特殊キーを押してホットキーを変更
-
-
- クイック ツール ウィンドウの呼び出し
-
-
- カスタムショートカット
-
-
- カスタムショートカット
-
-
- ボタンまたは特殊キーを押してホットキーを変更
-
-
- デスクトップの表示と非表示を切り替える
-
-
- 次のキーを押します: Windows + D
-
-
- Escape
-
-
- このキーを押します: Escape
-
-
- ウィンドウと全画面を切り替える
-
-
- 次のキーを押します: Alt + Enter
-
-
- ガイドまたは PS ボタン
-
-
- Xbox ガイドまたは Sony PS ボタン入力をシミュレートする
-
-
- タッチ キーボードを表示する
-
-
- ボタンまたは特殊キーを押してホットキーを変更
-
-
- アプリケーションを強制的にシャットダウン
-
-
- ボタンまたは特殊キーを押してホットキーを変更
-
-
- メインウィンドウの表示と非表示を切り替える
-
-
- ボタンまたは特殊キーを押してホットキーを変更
-
-
- タスク マネージャーを開く
-
-
- 次のキーを押します: Ctrl + Shift + Esc
-
-
- タスクビューを開く
-
-
- 次のキーを押します: Windows + Tab
-
-
- 再開と停止の切り替え
-
-
- フォアグラウンド アプリケーションを一時停止または再開
-
-
- Handheld Companion
-
-
- 概要
-
-
- コントローラー
-
-
- オーバーレイ
-
-
- プロファイル
-
-
- OK
-
-
- 設定
-
-
- 8BitDo Lite 2
-
-
- 配置
-
-
- 3D コントローラー オーバーレイの配置を変更
-
-
- トラックパッド オーバーレイの配置を変更する
-
-
- 常に先頭に表示
-
-
- 切り替えると、3D コントローラーのオーバーレイが他のウィンドウの上に表示
-
-
- 戻る
-
-
- フェイスカメラ
-
-
- カメラを向いた場合の 3D コントローラー オーバーレイ モデルの動作を変更
-
-
- ピッチ
-
-
- 角度を度単位で変更
-
-
- 背景色
-
-
- 3D コントローラーのオーバーレイの背景色を変更
-
-
- コントローラ オプション
-
-
- プレイステーション DualSense
-
-
- エミュレートされたコントローラー
-
-
- フェイスカメラ
-
-
- 3D モデルはデフォルトの位置としてカメラに向かうようにゆっくり回転します
-
-
- Listening...
-
-
- MACHENIKE HG510
-
-
- メイントリガー
-
-
- 3D コントローラー オーバーレイのメイン トリガーを変更
-
-
- モーション
-
-
- センサー情報をもとにユーザーの動きに合わせてモデルが動きます
-
-
- N64
-
-
- OEM コントローラー
-
-
- 不透明度
-
-
- 3D コントローラーのオーバーレイの不透明度を変更
-
-
- トラックパッドのオーバーレイの不透明度を変更
-
-
- オーバーレイ
-
-
- オーバーレイ モデル
-
-
- 3D コントローラーのオーバーレイ モデルを変更
-
-
- オーバーレイ プレビュー
-
-
- レンダリング設定
-
-
- アンチエイリアシング
-
-
- レンダリングのアンチエイリアスステータスを変更
-
-
- 固定 3D オーバーレイ コントローラー モデルのレンダリング設定を変更
-
-
- 更新レート
-
-
- レンダリングの更新レートを 1秒あたりで変更
-
-
- サイズ
-
-
- 3D コントローラーのオーバーレイ サイズを変更
-
-
- トラックパッドのオーバーレイ サイズを変更する
-
-
- Start
-
-
- Fisher-Price controller
-
-
- トラックパッドのオプション
-
-
- Xbox One
-
-
- ZD O+
-
-
- オーバーレイ
-
-
- 再開
-
-
- 一時停止
-
-
- 追加設定
-
-
- 照準を合わせるモーション数
-
-
- アクティブ化ボタン
-
-
- 設定された起動ボタンを使用して照準器またはスコープを狙うときの追加のモーション感度数
-
-
- 乗数値
-
-
- カメラオプション
-
-
- カスタム応答曲線
-
-
- ゲームに送信
-
-
- 動きの強さ
-
-
- アグレッシブ
-
-
- デフォルト
-
-
- プリセットオプション
-
-
- 正確
-
-
- フリック時間
-
-
- フリック時間を変更し、180 度回転するように調整
-
-
- フリックスティック (実験的)
-
-
- ジョイスティックの(右)フリックの方向にカメラを向け、回転させることでカメラを純粋に水平面内で回転
-
-
- フリックスティック有効
-
-
- 感度
-
-
- 水平軸と垂直軸のモーション感度を変更
-
-
- 感度 X
-
-
- 横軸のモーション感度を変更
-
-
- 感度 Y
-
-
- 垂直軸のモーション感度を変更
-
-
- スティック感度
-
-
- 回転速度を変更
-
-
- 追加設定
-
-
- デッドゾーン
-
-
- ステアリングのデッドゾーンを度単位で変更します。ステアリングの直進性が向上
-
-
- ジョイスティック ゲーム入力
-
-
- ジョイスティックステアリング
-
-
- ジョイスティックステアリングオプション
-
-
- ジョイスティックステアリングのプレビュー
-
-
- 最大ステアリング角度
-
-
- ステアリング角度の最大値を度単位で変更
-
-
- ステアリングリニアリティ
-
-
- 入力とステアリングの間のマッピング。値を低くすると、フルロック付近の精度が高くなりますが、中心付近の精度は低くなります。値を大きくすると、中心付近の精度が高くなりますが、フルロック付近の精度は低くなります。1.0 は線形マッピングです
-
-
- 加速度計乗数
-
-
- システムが報告する加速度計の値を変更
-
-
- 追加設定
-
-
- アンチデッドゾーン
-
-
- ゲーム内のアンチデッドゾーンをパーセント単位で変更
-
-
- %
-
-
- 削除してもよろしいですか?
-
-
- このアイテムはすぐに削除されます。この操作を元に戻すことはできません
-
-
- このプロファイルを上書きしてもよろしいですか?
-
-
- {0} は上書きされます。この操作を元に戻すことはできません
-
-
- ブーストTDP
-
-
- ブーストTDPを変更
-
-
- キャンセル
-
-
- 新しいプロファイルを作成
-
-
- 削除
-
-
- プロファイルを削除
-
-
- ゲームごとのユーザー プロファイル
-
-
- 関連付けられたアプリケーションが検出されると、プロファイルは自動的に適用
-
-
- グローバル設定
-
-
- グローバル プロファイル設定を変更
-
-
- ジャイロメーター乗数
-
-
- システムが報告するジャイロメーター値を変更
-
-
- ジャイロステアリング
-
-
- コントローラーの水平方向の動きを制御するには、回転軸または横軸を使用できます
-
-
- 横軸を反転
-
-
- 縦軸を反転
-
-
- モーションコントロール設定
-
-
- グローバル モーション コントロール設定を変更
-
-
- OK
-
-
- 電源設定
-
-
- 電源設定を変更
-
-
- プロファイルの詳細
-
-
- プロファイル名
-
-
- プロファイル パス
-
-
- プロファイル
-
-
- プロファイルの選択
-
-
- 編集したいプロファイルを選択
-
-
- プロファイル設定
-
-
- プロファイルが更新されました
-
-
- 更新されました
-
-
- ロール
-
-
- X
-
-
- Y
-
-
- 入力のスタイル
-
-
- コントローラーの物理入力は、さまざまなタイプのデバイスのように動作するようにプログラムできます
-
-
- 出力デバイス
-
-
- モーション コマンドを受信するデバイスを選択
-
-
- TDP制限
-
-
- TDPを変更
-
-
- TDPを変更
-
-
- プロセッサの電力を制限して総電力を削減
-
-
- ユニバーサル モーション コントローラーを有効
-
-
- 無効、ボタンでオンにします
-
-
- 有効、ボタンでオフにします
-
-
- モーションのアクティブ化
-
-
- モーション入力が無効な状態で、選択したボタンを使用してモーションを有効に
-モーション入力が有効になっている場合、選択したボタンを使用してモーションを無効にします
-
-
- モーション コマンドを受信するデバイスを選択
-
-
- ユニバーサル モーション コントロール設定
-
-
- デバイスの動きをコントローラー入力に変換
-
-
- プロファイルを更新
-
-
- アプリケーションがデバイスの物理コントローラーにアクセスできるようにする
-
-
- 拡張互換性 (XInputPlus)
-
-
- 回転
-
-
- Yes
-
-
- 手動 GPU クロック制御
-
-
- GPU を固定クロックに設定
-
-
- MHz
-
-
- 電力モード
-
-
- バランス型
-
-
- 電力使用量とパフォーマンスに基づいてデバイスを最適化
-
-
- 効率
-
-
- パフォーマンス
-
-
- ブースト
-
-
- TDP制限
-
-
- プロセッサの電力を制限して総電力を削減
-
-
- TDP制限はプロファイルによって上書きされます
-
-
- 基本
-
-
- W
-
-
- プロファイルを作成する
-
-
- プロセスを待機しています...
-
-
- 仮想コントローラーを介して Windows ハンドヘルド ゲーム コンピューターにジャイロスコープと加速度計のサポートを提供します。サービスが有効になっている場合、組み込みコントローラーはホワイトリスト外のアプリケーションに隠されます。サービスが無効になっている場合、組み込みコントローラーのクロークが解除され、仮想コントローラーが無効になります
-
-
- コントローラー サービス
-
-
- 言語
-
-
- アプリケーション言語
-
-
- 再起動が必要です
-
-
- 変更を有効にするには、アプリケーションを再起動してください
-
-
- テーマ
-
-
- ライト モードまたはダーク モード
-
-
- アプリケーションの自動起動
-
-
- Windows にサインインすると、アプリケーションが自動的に起動します
-
-
- アプリケーションの背景
-
-
- アクリル
-
-
- アプリケーションの背景、なし、マイカ、タブ付き、アクリル
-
-
- マイカ
-
-
- なし
-
-
- タブ
-
-
- 更新を確認する
-
-
- 閉じると最小化
-
-
- アプリケーションを閉じずに最小化
-
-
- 起動時にデスクトップ プロファイルを有効にする
-
-
- デスクトップ プロファイルはアプリケーションの起動時に自動的に有効になります
-
-
- ダウンロード
-
-
- ダウンロード中 -
-
-
- スマートな効率
-
-
- スマート効率モードはバックグラウンドプロセスの優先順位を下げ、エネルギー効率を向上させます
-
-
- 一般オプション
-
-
- 今すぐインストール
-
-
- 最終チェック日:
-
-
- 通知オプション
-
-
- アプリケーションをバックグラウンドで開きます
-
-
- アプリケーションは最初は最小化されて起動し、タスクバーに表示されます
-
-
- 外部
-
-
- 内部
-
-
- センサー オプション
-
-
- 外部センサーの設置方向
-
-
- センサーがデバイスのどちら側に取り付けられているかを選択します
-
-
- 外部センサーの上下が逆
-
-
- センサーは逆さまに取り付けられており、USB-C コンバーターで可能
-
-
- センサーの選択
-
-
- モーション入力に使用する目的のセンサーを選択します
-
-
- 設定
-
-
- スタートアップの種類
-
-
- サービスの起動タイプを定義するためにサービス マネージャーによって使用されます
-
-
- 最大電力
-
-
- プロセッサに供給される最大電力 (ワット単位)
-
-
- 最小電力
-
-
- プロセッサに供給される最小電力 (ワット単位)
-
-
- 設定可能な電力 (cTDP) オーバーライド
-
-
- CPU 仕様を超えて最小および最大電力値 (TDP) を変更できます
-
-
- Dark
-
-
- Light
-
-
- 通知
-
-
- Windows アクション センターでアプリケーションから通知を取得
-
-
- 利用可能なアップデート
-
-
- 更新をチェックしています...
-
-
- アップデート ファイルをダウンロードできませんでした
-
-
- github にアクセスできませんでした
-
-
- アップデート ファイルが見つかりませんでした
-
-
- 問題がありました
-
-
- 最新情報
-
-
- コントローラが隠され、入力が仮想コントローラに転送されるようになりました
-
-
- User
-
-
- これらの設定のロックを解除するには、管理者としてこのツールを実行してください
-
-
- ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
-
-
- 仮想コントローラーをミュートします
-
-
- Steam 関連アプリケーションの仮想コントローラーをミュートします
-
-
- コントローラー設定
-
-
- 仮想コントローラーの設定を変更
-
-
- モーションアンチデッドゾーン
-
-
- ゲーム内のデッドゾーンを補正し、小さな動きの認識を改善
-
-
- ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- スティックの真円度を改善
-
-
- 円形度を左に
-
-
- 円形度を右に
-
-
- 左ジョイスティックのデッドゾーン %
-
-
- 左ジョイスティックの内側と外側のデッドゾーンのパーセンテージを調整
-
-
- 右ジョイスティックのデッドゾーン %
-
-
- 右ジョイスティックの内側と外側のデッドゾーンの割合を調整
-
-
- 左トリガーデッドゾーン %
-
-
- 左トリガーの内側と外側のデッドゾーンの割合を調整
-
-
- 右トリガーデッドゾーン %
-
-
- 右トリガーの内側と外側のデッドゾーンの割合を調整
-
-
- 接続時にコントローラーを振動させる
-
-
- 接続時に物理コントローラーを振動させる
-
-
- デスクトップレイアウト
-
-
- デスクトップ コントローラーのレイアウトを切り替え
-
-
- アクションセンターを表示
-
-
- Windows アクション センターの表示と非表示を切り替え
-
-
- コントローラのレイアウト
-
-
- ファンオーバーライド
-
-
- ファンのデューティ サイクルをユーザーの値に設定
-
-
- スクリーンに表示
-
-
- スクリーン表示サポートを有効
-
-
- 明るさを下げる
-
-
- 現在のディスプレイの明るさを 5% 下げます
-
-
- 音量を下げる
-
-
- システムの音量を 5% 下げます
-
-
- 明るさを上げる
-
-
- 現在のディスプレイの明るさを 5% 上げます
-
-
- 音量を上げる
-
-
- システムの音量を 5% 上げます
-
-
- AutoTDP
-
-
- 測定された FPS と要求された FPS ターゲットに基づいて TDP を自動調整
-
-
- Framerateターゲット
-
-
- AutoTDP コントローラーの必要な FPS ターゲット値
-
-
- GPU クロックの最大周波数
-
-
- GPU の最大クロック速度 (Mhz)
-
-
- FPS
-
-
- オーバーレイ表示レベル
-
-
- 画面上の情報表示レベルを変更
-
-
- 更新レート
-
-
- オンスクリーン表示の更新レートを変更
-
-
- フレームレート制限
-
-
- 3D アプリケーションのフレームレートを制限
-
-
- Open Snipping tool
-
-
- Press this key: Windows + Shift + S
-
-
- Manufacturer
-
-
- Partner
-
-
- Product name
-
-
- A,B,X,Y
-
-
- BACK GRIPS
-
-
- BUMPERS
-
-
- MENU
-
-
- OEM
-
-
- Desktop layout
-
-
- Define desktop layout
-
-
- Define controller layout when in desktop mode
-
-
- Edit
-
-
- Enable desktop layout
-
-
- Non-game controller layouts
-
-
- You might want to click on Connect next to your plugged controller.
-
-
- You have no physical controller connected. No inputs will be sent to HC or its service.
-
-
- Please make sure you connected a compatible XInput or DInput device.
-
-
- No physical controller detected
-
-
- No physical controller connected
-
-
- You might want to start companion service or make sure your virtual controller status is set to: Connected
-
-
- Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
-
-
- No virtual controller detected
-
-
- You might want to unmute your virtual controller or unhide your physical controller.
-
-
- Your physical controller is hidden, yet you have muted your virtual controller.
-
-
- Physical controller is hidden
-
-
- You might want to hide your physical controller or mute your virtual controller.
-
-
- Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
-
-
- Physical controller is not hidden
-
-
- HD rumble
-
-
- Use high-definition rumble engine, at the cost of higher CPU usage
-
-
- コントローラー設定
-
-
- DIRECTIONAL PAD
-
-
- LEFT JOYSTICK
-
-
- LEFT JOYSTICK BUTTONS
-
-
- RIGHT JOYSTICK
-
-
- RIGHT JOYSTICK BUTTONS
-
-
- Apply template
-
-
- Buttons
-
-
- Cancel
-
-
- COMMUNITY
-
-
- Confirm
-
-
- Dpad
-
-
- Export for current controller
-
-
- Export layout
-
-
- Gyro
-
-
- Joysticks
-
-
- Layout author
-
-
- Layout description
-
-
- Layout title
-
-
- Save game information with the layout
-
-
- Show current controller templates only
-
-
- Layout template picker
-
-
- TEMPLATES
-
-
- Trackpads
-
-
- Triggers
-
-
- Hotkeys
-
-
- ms
-
-
- Disabled
-
-
- Extended
-
-
- Full
-
-
- Minimal
-
-
- CPU
-
-
- Energy performance preference (EPP)
-
-
- CPU/GPU power balance
-
-
- Specifies power distribution policy between CPU and GPU
-
-
- GPU
-
-
- Power limit target
-
-
- Disconnect
-
-
- Native display orientation
-
-
- Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
-
-
- Detect
-
-
- Not set
-
-
- Use system setting
-
-
- LEFT TRACKPAD
-
-
- LEFT TRACKPAD BUTTONS
-
-
- RIGHT TRACKPAD
-
-
- RIGHT TRACKPAD BUTTONS
-
-
- LEFT TRIGGER
-
-
- LEFT TRIGGER BUTTONS
-
-
- RIGHT TRIGGER
-
-
- RIGHT TRIGGER BUTTONS
-
-
- Power limit target
-
-
- Quicktools options
-
-
- %
-
-
- Set current CPU boost mode
-
-
- CPU boost mode
-
-
- Set the fan duty cycle to user-defined value
-
-
- Fan override
-
-
- Adjust main display resolution and refresh rate
-
-
- Display resolution and refresh rate
-
-
- Top right
-
-
- Top left
-
-
- Window location
-
-
- Bottom right
-
-
- Bottom left
-
-
- Power options
-
-
- Define quicktools window location
-
-
- Third-party applications
-
-
- None
-
-
- Quicktools backdrop, none, mica, tabbed, acrylic
-
-
- Automatically turn RTSS off when companion is closed
-
-
- Automatically turn HWiNFO off when companion is closed
-
-
- HWiNFO
-
-
- Default
-
-
- Current profile:
-
-
- RivaTuner Statistics Server
-
-
- Automatically hide quick tools when the user clicks outside of window
-
-
- Hide when loses focus
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Sony
-
-
- Options
-
-
- DualShock 4 コントローラー
-
-
- コントローラー無効
-
-
- XBOX 360 コントローラー
-
-
- 接続済み
-
-
- 切断
-
-
- Auto Roll Yaw Swap
-
-
- ジョイスティックカメラ
-
-
- ジョイスティックステアリング
-
-
- プレーヤースペース
-
-
- Handheld Companion
-
-
- オーバーレイ
-
-
- クイック ツール
-
-
- Windows
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- Menu
-
-
- 左ジョイスティック
-
-
- 右ジョイスティック
-
-
- デフォルトのコントローラー プロファイル
-
-
- 実行可能ファイルがありません
-
-
- アプリケーションへのパスがありません
-
-
- コンテンツを変更の権限がありません
-
-
- ここには何も表示されません
-
-
- このプロファイルは実行されています
-
-
- Default
-
-
- Eco
-
-
- High
-
-
- 自動
-
-
- 無効
-
-
- マニュアル
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- LB
-
-
- RB
-
-
- Guide
-
-
- Menu
-
-
- 単純なジョイスティックとして動作します。これは従来のジョイスティック アプリケーションを対象としています
-
-
- ステアリング ホイールやレーシング ゲームの制御に最適化されたジョイスティックとして動作します
-
-
- 一人称または三人称カメラの制御に最適化されたジョイスティックとして動作します
-
-
- Handheld Companion
-
-
- オプション
-
-
- STEAM
-
-
- KB
-
-
- Win
-
-
- Esc
-
-
- M1
-
-
- A
-
-
- Always On
-
-
- B
-
-
- Back
-
-
- DPad Down
-
-
- DPad Left
-
-
- DPad Right
-
-
- DPad Up
-
-
- Left Shoulder
-
-
- Left Thumb
-
-
- Left Trigger
-
-
- Right Shoulder
-
-
- Right Thumb
-
-
- Right Trigger
-
-
- Start
-
-
- X
-
-
- Y
-
-
- Custom
-
-
- Device
-
-
- Auto Roll Yaw Swap
-
-
- Joystick Camera
-
-
- Joystick Steering
-
-
- Player Space
-
-
- Left Stick
-
-
- Right Stick
-
-
- Oops. This profile seems to be running. Some options requiring an executable may be disabled.
-
-
- Command center
-
-
- Armory crate
-
-
- L2
-
-
- Left Thumb
-
-
- R2
-
-
- Right Thumb
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- DPad Down
-
-
- DPad Left
-
-
- PPad Right
-
-
- DPad Up
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Left Thumb
-
-
- Left Thumb Down
-
-
- Left Thumb Left
-
-
- Left Thumb Right
-
-
- Left Thumb Up
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Right Thumb
-
-
- Right Thumb Down
-
-
- Right Thumb Left
-
-
- Right Thumb Right
-
-
- Right Thumb Up
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- S
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- LeftStick
-
-
- RightStick
-
-
- Yes
-
-
- No
-
-
- Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
-
-
- Warning
-
-
- Disabled
-
-
- Injection (recommended)
-
-
- Redirection
-
-
- Improve virtual controller detection
-
-
- Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
-
-
- Yes
-
-
- No
-
-
- Your device must be restarted in order for the changes to take effect. Would you like to restart now?
-
-
- Restart required
-
-
- Yes
-
-
- No
-
-
- Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
-
-
- Warning
-
-
- Change the virtual controller layout
-
-
- This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Back
-
-
- Exit
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- External
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 概要
+
+
+ >Windows サービスとタッチ インターフェイスに最適化された GUI の組み合わせにより、ハンドヘルド ゲーム コンピューターのエクスペリエンスが向上します。機能には、ジャイロ コントロール、仮想コントローラ シミュレーション、クイック ツール オーバーレイ、仮想タッチパッド、3D コントローラ モデル、アプリケーションごとのベースのプロファイル設定システムが含まれます。Handheld Companion は、ViGEmBus ドライバーと ViGEmClient ライブラリ、および HidHide カーネル モード フィルター ドライバーに依存しています。モーション コントロール アルゴリズムは、Jibbsmart による研究と GyroWiki で入手可能な情報に基づいています。
+
+
+ 加速度計
+
+
+ 作成者
+
+
+ 貢献者
+
+
+ 説明
+
+
+ 寄付する
+
+
+ ジャイロ
+
+
+ 傾き
+
+
+ 該当なし
+
+
+ 関連リンク
+
+
+ External
+
+
+ Internal
+
+
+ センサー名
+
+
+ センサー仕様
+
+
+ サービス
+
+
+ ソースコード
+
+
+ バージョン
+
+
+ Wiki
+
+
+ 管理者
+
+
+ 接続時にコントローラーを非表示にする
+
+
+ 接続時に物理コントローラーを非表示にする
+
+
+ 接続
+
+
+ コントローラ
+
+
+ コントローラを隠す
+
+
+ コントローラー設定
+
+
+ 切断
+
+
+ 入力デバイス
+
+
+ >閉じるときにコントローラを再表示する
+
+
+ アプリケーションの終了時にすべての物理コントローラーを復元
+
+
+ 振動の強さ
+
+
+ コントローラーの振動の強さを変更
+
+
+
+ ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ TDPを下げる
+
+
+ システムまたは現在適用されているプロファイルの TDP を 1 ワット減少
+
+
+ 押してホットキー入力を設定
+
+
+ 押してキーボード出力を設定
+
+
+ TDPを上げる
+
+
+ システムまたは現在適用されているプロファイルの TDP を 1 ワット増加
+
+
+ 3D コントローラーを表示
+
+
+ ボタンまたは特殊キーを押して 3D ホットキーを変更
+
+
+ 仮想トラックパッドを表示する
+
+
+ ボタンまたは特殊キーを押してホットキーを変更
+
+
+ クイック ツール ウィンドウの呼び出し
+
+
+ カスタムショートカット
+
+
+ カスタムショートカット
+
+
+ ボタンまたは特殊キーを押してホットキーを変更
+
+
+ デスクトップの表示と非表示を切り替える
+
+
+ 次のキーを押します: Windows + D
+
+
+ Escape
+
+
+ このキーを押します: Escape
+
+
+ ウィンドウと全画面を切り替える
+
+
+ 次のキーを押します: Alt + Enter
+
+
+ ガイドまたは PS ボタン
+
+
+ Xbox ガイドまたは Sony PS ボタン入力をシミュレートする
+
+
+ タッチ キーボードを表示する
+
+
+ ボタンまたは特殊キーを押してホットキーを変更
+
+
+ アプリケーションを強制的にシャットダウン
+
+
+ ボタンまたは特殊キーを押してホットキーを変更
+
+
+ メインウィンドウの表示と非表示を切り替える
+
+
+ ボタンまたは特殊キーを押してホットキーを変更
+
+
+ タスク マネージャーを開く
+
+
+ 次のキーを押します: Ctrl + Shift + Esc
+
+
+ タスクビューを開く
+
+
+ 次のキーを押します: Windows + Tab
+
+
+ 再開と停止の切り替え
+
+
+ フォアグラウンド アプリケーションを一時停止または再開
+
+
+ Handheld Companion
+
+
+ 概要
+
+
+ コントローラー
+
+
+ オーバーレイ
+
+
+ プロファイル
+
+
+ OK
+
+
+ 設定
+
+
+ 8BitDo Lite 2
+
+
+ 配置
+
+
+ 3D コントローラー オーバーレイの配置を変更
+
+
+ トラックパッド オーバーレイの配置を変更する
+
+
+ 常に先頭に表示
+
+
+ 切り替えると、3D コントローラーのオーバーレイが他のウィンドウの上に表示
+
+
+ 戻る
+
+
+ フェイスカメラ
+
+
+ カメラを向いた場合の 3D コントローラー オーバーレイ モデルの動作を変更
+
+
+ ピッチ
+
+
+ 角度を度単位で変更
+
+
+ 背景色
+
+
+ 3D コントローラーのオーバーレイの背景色を変更
+
+
+ コントローラ オプション
+
+
+ プレイステーション DualSense
+
+
+ エミュレートされたコントローラー
+
+
+ フェイスカメラ
+
+
+ 3D モデルはデフォルトの位置としてカメラに向かうようにゆっくり回転します
+
+
+ Listening...
+
+
+ MACHENIKE HG510
+
+
+ メイントリガー
+
+
+ 3D コントローラー オーバーレイのメイン トリガーを変更
+
+
+ モーション
+
+
+ センサー情報をもとにユーザーの動きに合わせてモデルが動きます
+
+
+ N64
+
+
+ OEM コントローラー
+
+
+ 不透明度
+
+
+ 3D コントローラーのオーバーレイの不透明度を変更
+
+
+ トラックパッドのオーバーレイの不透明度を変更
+
+
+ オーバーレイ
+
+
+ オーバーレイ モデル
+
+
+ 3D コントローラーのオーバーレイ モデルを変更
+
+
+ オーバーレイ プレビュー
+
+
+ レンダリング設定
+
+
+ アンチエイリアシング
+
+
+ レンダリングのアンチエイリアスステータスを変更
+
+
+ 固定 3D オーバーレイ コントローラー モデルのレンダリング設定を変更
+
+
+ 更新レート
+
+
+ レンダリングの更新レートを 1秒あたりで変更
+
+
+ サイズ
+
+
+ 3D コントローラーのオーバーレイ サイズを変更
+
+
+ トラックパッドのオーバーレイ サイズを変更する
+
+
+ Start
+
+
+ Fisher-Price controller
+
+
+ トラックパッドのオプション
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ オーバーレイ
+
+
+ 再開
+
+
+ 一時停止
+
+
+ 追加設定
+
+
+ 照準を合わせるモーション数
+
+
+ アクティブ化ボタン
+
+
+ 設定された起動ボタンを使用して照準器またはスコープを狙うときの追加のモーション感度数
+
+
+ 乗数値
+
+
+ カメラオプション
+
+
+ カスタム応答曲線
+
+
+ ゲームに送信
+
+
+ 動きの強さ
+
+
+ アグレッシブ
+
+
+ デフォルト
+
+
+ プリセットオプション
+
+
+ 正確
+
+
+ フリック時間
+
+
+ フリック時間を変更し、180 度回転するように調整
+
+
+ フリックスティック (実験的)
+
+
+ ジョイスティックの(右)フリックの方向にカメラを向け、回転させることでカメラを純粋に水平面内で回転
+
+
+ フリックスティック有効
+
+
+ 感度
+
+
+ 水平軸と垂直軸のモーション感度を変更
+
+
+ 感度 X
+
+
+ 横軸のモーション感度を変更
+
+
+ 感度 Y
+
+
+ 垂直軸のモーション感度を変更
+
+
+ スティック感度
+
+
+ 回転速度を変更
+
+
+ 追加設定
+
+
+ デッドゾーン
+
+
+ ステアリングのデッドゾーンを度単位で変更します。ステアリングの直進性が向上
+
+
+ ジョイスティック ゲーム入力
+
+
+ ジョイスティックステアリング
+
+
+ ジョイスティックステアリングオプション
+
+
+ ジョイスティックステアリングのプレビュー
+
+
+ 最大ステアリング角度
+
+
+ ステアリング角度の最大値を度単位で変更
+
+
+ ステアリングリニアリティ
+
+
+ 入力とステアリングの間のマッピング。値を低くすると、フルロック付近の精度が高くなりますが、中心付近の精度は低くなります。値を大きくすると、中心付近の精度が高くなりますが、フルロック付近の精度は低くなります。1.0 は線形マッピングです
+
+
+ 加速度計乗数
+
+
+ システムが報告する加速度計の値を変更
+
+
+ 追加設定
+
+
+ アンチデッドゾーン
+
+
+ ゲーム内のアンチデッドゾーンをパーセント単位で変更
+
+
+ %
+
+
+ 削除してもよろしいですか?
+
+
+ このアイテムはすぐに削除されます。この操作を元に戻すことはできません
+
+
+ このプロファイルを上書きしてもよろしいですか?
+
+
+ {0} は上書きされます。この操作を元に戻すことはできません
+
+
+ ブーストTDP
+
+
+ ブーストTDPを変更
+
+
+ キャンセル
+
+
+ 新しいプロファイルを作成
+
+
+ 削除
+
+
+ プロファイルを削除
+
+
+ ゲームごとのユーザー プロファイル
+
+
+ 関連付けられたアプリケーションが検出されると、プロファイルは自動的に適用
+
+
+ グローバル設定
+
+
+ グローバル プロファイル設定を変更
+
+
+ ジャイロメーター乗数
+
+
+ システムが報告するジャイロメーター値を変更
+
+
+ ジャイロステアリング
+
+
+ コントローラーの水平方向の動きを制御するには、回転軸または横軸を使用できます
+
+
+ 横軸を反転
+
+
+ 縦軸を反転
+
+
+ モーションコントロール設定
+
+
+ グローバル モーション コントロール設定を変更
+
+
+ OK
+
+
+ 電源設定
+
+
+ 電源設定を変更
+
+
+ プロファイルの詳細
+
+
+ プロファイル名
+
+
+ プロファイル パス
+
+
+ プロファイル
+
+
+ プロファイルの選択
+
+
+ 編集したいプロファイルを選択
+
+
+ プロファイル設定
+
+
+ プロファイルが更新されました
+
+
+ 更新されました
+
+
+ ロール
+
+
+ X
+
+
+ Y
+
+
+ 入力のスタイル
+
+
+ コントローラーの物理入力は、さまざまなタイプのデバイスのように動作するようにプログラムできます
+
+
+ 出力デバイス
+
+
+ モーション コマンドを受信するデバイスを選択
+
+
+ TDP制限
+
+
+ TDPを変更
+
+
+ TDPを変更
+
+
+ プロセッサの電力を制限して総電力を削減
+
+
+ ユニバーサル モーション コントローラーを有効
+
+
+ 無効、ボタンでオンにします
+
+
+ 有効、ボタンでオフにします
+
+
+ モーションのアクティブ化
+
+
+ モーション入力が無効な状態で、選択したボタンを使用してモーションを有効に
+モーション入力が有効になっている場合、選択したボタンを使用してモーションを無効にします
+
+
+ モーション コマンドを受信するデバイスを選択
+
+
+ ユニバーサル モーション コントロール設定
+
+
+ デバイスの動きをコントローラー入力に変換
+
+
+ プロファイルを更新
+
+
+ アプリケーションがデバイスの物理コントローラーにアクセスできるようにする
+
+
+ 拡張互換性 (XInputPlus)
+
+
+ 回転
+
+
+ Yes
+
+
+ 手動 GPU クロック制御
+
+
+ GPU を固定クロックに設定
+
+
+ MHz
+
+
+ 電力モード
+
+
+ バランス型
+
+
+ 電力使用量とパフォーマンスに基づいてデバイスを最適化
+
+
+ 効率
+
+
+ パフォーマンス
+
+
+ ブースト
+
+
+ TDP制限
+
+
+ プロセッサの電力を制限して総電力を削減
+
+
+ TDP制限はプロファイルによって上書きされます
+
+
+ 基本
+
+
+ W
+
+
+ プロファイルを作成する
+
+
+ プロセスを待機しています...
+
+
+ 仮想コントローラーを介して Windows ハンドヘルド ゲーム コンピューターにジャイロスコープと加速度計のサポートを提供します。サービスが有効になっている場合、組み込みコントローラーはホワイトリスト外のアプリケーションに隠されます。サービスが無効になっている場合、組み込みコントローラーのクロークが解除され、仮想コントローラーが無効になります
+
+
+ コントローラー サービス
+
+
+ 言語
+
+
+ アプリケーション言語
+
+
+ 再起動が必要です
+
+
+ 変更を有効にするには、アプリケーションを再起動してください
+
+
+ テーマ
+
+
+ ライト モードまたはダーク モード
+
+
+ アプリケーションの自動起動
+
+
+ Windows にサインインすると、アプリケーションが自動的に起動します
+
+
+ アプリケーションの背景
+
+
+ アクリル
+
+
+ アプリケーションの背景、なし、マイカ、タブ付き、アクリル
+
+
+ マイカ
+
+
+ なし
+
+
+ タブ
+
+
+ 更新を確認する
+
+
+ 閉じると最小化
+
+
+ アプリケーションを閉じずに最小化
+
+
+ 起動時にデスクトップ プロファイルを有効にする
+
+
+ デスクトップ プロファイルはアプリケーションの起動時に自動的に有効になります
+
+
+ ダウンロード
+
+
+ ダウンロード中 -
+
+
+ スマートな効率
+
+
+ スマート効率モードはバックグラウンドプロセスの優先順位を下げ、エネルギー効率を向上させます
+
+
+ 一般オプション
+
+
+ 今すぐインストール
+
+
+ 最終チェック日:
+
+
+ 通知オプション
+
+
+ アプリケーションをバックグラウンドで開きます
+
+
+ アプリケーションは最初は最小化されて起動し、タスクバーに表示されます
+
+
+ 外部
+
+
+ 内部
+
+
+ センサー オプション
+
+
+ 外部センサーの設置方向
+
+
+ センサーがデバイスのどちら側に取り付けられているかを選択します
+
+
+ 外部センサーの上下が逆
+
+
+ センサーは逆さまに取り付けられており、USB-C コンバーターで可能
+
+
+ センサーの選択
+
+
+ モーション入力に使用する目的のセンサーを選択します
+
+
+ 設定
+
+
+ スタートアップの種類
+
+
+ サービスの起動タイプを定義するためにサービス マネージャーによって使用されます
+
+
+ 最大電力
+
+
+ プロセッサに供給される最大電力 (ワット単位)
+
+
+ 最小電力
+
+
+ プロセッサに供給される最小電力 (ワット単位)
+
+
+ 設定可能な電力 (cTDP) オーバーライド
+
+
+ CPU 仕様を超えて最小および最大電力値 (TDP) を変更できます
+
+
+ Dark
+
+
+ Light
+
+
+ 通知
+
+
+ Windows アクション センターでアプリケーションから通知を取得
+
+
+ 利用可能なアップデート
+
+
+ 更新をチェックしています...
+
+
+ アップデート ファイルをダウンロードできませんでした
+
+
+ github にアクセスできませんでした
+
+
+ アップデート ファイルが見つかりませんでした
+
+
+ 問題がありました
+
+
+ 最新情報
+
+
+ コントローラが隠され、入力が仮想コントローラに転送されるようになりました
+
+
+ User
+
+
+ これらの設定のロックを解除するには、管理者としてこのツールを実行してください
+
+
+ ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+
+ 仮想コントローラーをミュートします
+
+
+ Steam 関連アプリケーションの仮想コントローラーをミュートします
+
+
+ コントローラー設定
+
+
+ 仮想コントローラーの設定を変更
+
+
+ モーションアンチデッドゾーン
+
+
+ ゲーム内のデッドゾーンを補正し、小さな動きの認識を改善
+
+
+ ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ スティックの真円度を改善
+
+
+ 円形度を左に
+
+
+ 円形度を右に
+
+
+ 左ジョイスティックのデッドゾーン %
+
+
+ 左ジョイスティックの内側と外側のデッドゾーンのパーセンテージを調整
+
+
+ 右ジョイスティックのデッドゾーン %
+
+
+ 右ジョイスティックの内側と外側のデッドゾーンの割合を調整
+
+
+ 左トリガーデッドゾーン %
+
+
+ 左トリガーの内側と外側のデッドゾーンの割合を調整
+
+
+ 右トリガーデッドゾーン %
+
+
+ 右トリガーの内側と外側のデッドゾーンの割合を調整
+
+
+ 接続時にコントローラーを振動させる
+
+
+ 接続時に物理コントローラーを振動させる
+
+
+ デスクトップレイアウト
+
+
+ デスクトップ コントローラーのレイアウトを切り替え
+
+
+ アクションセンターを表示
+
+
+ Windows アクション センターの表示と非表示を切り替え
+
+
+ コントローラのレイアウト
+
+
+ ファンオーバーライド
+
+
+ ファンのデューティ サイクルをユーザーの値に設定
+
+
+ スクリーンに表示
+
+
+ スクリーン表示サポートを有効
+
+
+ 明るさを下げる
+
+
+ 現在のディスプレイの明るさを 5% 下げます
+
+
+ 音量を下げる
+
+
+ システムの音量を 5% 下げます
+
+
+ 明るさを上げる
+
+
+ 現在のディスプレイの明るさを 5% 上げます
+
+
+ 音量を上げる
+
+
+ システムの音量を 5% 上げます
+
+
+ AutoTDP
+
+
+ 測定された FPS と要求された FPS ターゲットに基づいて TDP を自動調整
+
+
+ Framerateターゲット
+
+
+ AutoTDP コントローラーの必要な FPS ターゲット値
+
+
+ GPU クロックの最大周波数
+
+
+ GPU の最大クロック速度 (Mhz)
+
+
+ FPS
+
+
+ オーバーレイ表示レベル
+
+
+ 画面上の情報表示レベルを変更
+
+
+ 更新レート
+
+
+ オンスクリーン表示の更新レートを変更
+
+
+ フレームレート制限
+
+
+ 3D アプリケーションのフレームレートを制限
+
+
+ Open Snipping tool
+
+
+ Press this key: Windows + Shift + S
+
+
+ Manufacturer
+
+
+ Partner
+
+
+ Product name
+
+
+ A,B,X,Y
+
+
+ BACK GRIPS
+
+
+ BUMPERS
+
+
+ MENU
+
+
+ OEM
+
+
+ Desktop layout
+
+
+ Define desktop layout
+
+
+ Define controller layout when in desktop mode
+
+
+ Edit
+
+
+ Enable desktop layout
+
+
+ Non-game controller layouts
+
+
+ You might want to click on Connect next to your plugged controller.
+
+
+ You have no physical controller connected. No inputs will be sent to HC or its service.
+
+
+ Please make sure you connected a compatible XInput or DInput device.
+
+
+ No physical controller detected
+
+
+ No physical controller connected
+
+
+ You might want to start companion service or make sure your virtual controller status is set to: Connected
+
+
+ Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
+
+
+ No virtual controller detected
+
+
+ You might want to unmute your virtual controller or unhide your physical controller.
+
+
+ Your physical controller is hidden, yet you have muted your virtual controller.
+
+
+ Physical controller is hidden
+
+
+ You might want to hide your physical controller or mute your virtual controller.
+
+
+ Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
+
+
+ Physical controller is not hidden
+
+
+ HD rumble
+
+
+ Use high-definition rumble engine, at the cost of higher CPU usage
+
+
+ コントローラー設定
+
+
+ DIRECTIONAL PAD
+
+
+ LEFT JOYSTICK
+
+
+ LEFT JOYSTICK BUTTONS
+
+
+ RIGHT JOYSTICK
+
+
+ RIGHT JOYSTICK BUTTONS
+
+
+ Apply template
+
+
+ Buttons
+
+
+ Cancel
+
+
+ COMMUNITY
+
+
+ Confirm
+
+
+ Dpad
+
+
+ Export for current controller
+
+
+ Export layout
+
+
+ Gyro
+
+
+ Joysticks
+
+
+ Layout author
+
+
+ Layout description
+
+
+ Layout title
+
+
+ Save game information with the layout
+
+
+ Show current controller templates only
+
+
+ Layout template picker
+
+
+ TEMPLATES
+
+
+ Trackpads
+
+
+ Triggers
+
+
+ Hotkeys
+
+
+ ms
+
+
+ Disabled
+
+
+ Extended
+
+
+ Full
+
+
+ Minimal
+
+
+ CPU
+
+
+ Energy performance preference (EPP)
+
+
+ CPU/GPU power balance
+
+
+ Specifies power distribution policy between CPU and GPU
+
+
+ GPU
+
+
+ Power limit target
+
+
+ Disconnect
+
+
+ Native display orientation
+
+
+ Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
+
+
+ Detect
+
+
+ Not set
+
+
+ Use system setting
+
+
+ LEFT TRACKPAD
+
+
+ LEFT TRACKPAD BUTTONS
+
+
+ RIGHT TRACKPAD
+
+
+ RIGHT TRACKPAD BUTTONS
+
+
+ LEFT TRIGGER
+
+
+ LEFT TRIGGER BUTTONS
+
+
+ RIGHT TRIGGER
+
+
+ RIGHT TRIGGER BUTTONS
+
+
+ Power limit target
+
+
+ Quicktools options
+
+
+ %
+
+
+ Set current CPU boost mode
+
+
+ CPU boost mode
+
+
+ Set the fan duty cycle to user-defined value
+
+
+ Fan override
+
+
+ Adjust main display resolution and refresh rate
+
+
+ Display resolution and refresh rate
+
+
+ Top right
+
+
+ Top left
+
+
+ Window location
+
+
+ Bottom right
+
+
+ Bottom left
+
+
+ Power options
+
+
+ Define quicktools window location
+
+
+ Third-party applications
+
+
+ None
+
+
+ Quicktools backdrop, none, mica, tabbed, acrylic
+
+
+ Automatically turn RTSS off when companion is closed
+
+
+ Default
+
+
+ Current profile:
+
+
+ RivaTuner Statistics Server
+
+
+ Automatically hide quick tools when the user clicks outside of window
+
+
+ Hide when loses focus
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Sony
+
+
+ Options
+
+
+ DualShock 4 コントローラー
+
+
+ コントローラー無効
+
+
+ XBOX 360 コントローラー
+
+
+ 接続済み
+
+
+ 切断
+
+
+ Auto Roll Yaw Swap
+
+
+ ジョイスティックカメラ
+
+
+ ジョイスティックステアリング
+
+
+ プレーヤースペース
+
+
+ Handheld Companion
+
+
+ オーバーレイ
+
+
+ クイック ツール
+
+
+ Windows
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ Menu
+
+
+ 左ジョイスティック
+
+
+ 右ジョイスティック
+
+
+ デフォルトのコントローラー プロファイル
+
+
+ 実行可能ファイルがありません
+
+
+ アプリケーションへのパスがありません
+
+
+ コンテンツを変更の権限がありません
+
+
+ ここには何も表示されません
+
+
+ このプロファイルは実行されています
+
+
+ Default
+
+
+ Eco
+
+
+ High
+
+
+ 自動
+
+
+ 無効
+
+
+ マニュアル
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ LB
+
+
+ RB
+
+
+ Guide
+
+
+ Menu
+
+
+ 単純なジョイスティックとして動作します。これは従来のジョイスティック アプリケーションを対象としています
+
+
+ ステアリング ホイールやレーシング ゲームの制御に最適化されたジョイスティックとして動作します
+
+
+ 一人称または三人称カメラの制御に最適化されたジョイスティックとして動作します
+
+
+ Handheld Companion
+
+
+ オプション
+
+
+ STEAM
+
+
+ KB
+
+
+ Win
+
+
+ Esc
+
+
+ M1
+
+
+ A
+
+
+ Always On
+
+
+ B
+
+
+ Back
+
+
+ DPad Down
+
+
+ DPad Left
+
+
+ DPad Right
+
+
+ DPad Up
+
+
+ Left Shoulder
+
+
+ Left Thumb
+
+
+ Left Trigger
+
+
+ Right Shoulder
+
+
+ Right Thumb
+
+
+ Right Trigger
+
+
+ Start
+
+
+ X
+
+
+ Y
+
+
+ Custom
+
+
+ Device
+
+
+ Auto Roll Yaw Swap
+
+
+ Joystick Camera
+
+
+ Joystick Steering
+
+
+ Player Space
+
+
+ Left Stick
+
+
+ Right Stick
+
+
+ Oops. This profile seems to be running. Some options requiring an executable may be disabled.
+
+
+ Command center
+
+
+ Armory crate
+
+
+ L2
+
+
+ Left Thumb
+
+
+ R2
+
+
+ Right Thumb
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ DPad Down
+
+
+ DPad Left
+
+
+ DPad Right
+
+
+ DPad Up
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Left Thumb
+
+
+ Left Thumb Down
+
+
+ Left Thumb Left
+
+
+ Left Thumb Right
+
+
+ Left Thumb Up
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Right Thumb
+
+
+ Right Thumb Down
+
+
+ Right Thumb Left
+
+
+ Right Thumb Right
+
+
+ Right Thumb Up
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ LeftStick
+
+
+ RightStick
+
+
+ Yes
+
+
+ No
+
+
+ Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
+
+
+ Warning
+
+
+ Disabled
+
+
+ Injection (recommended)
+
+
+ Redirection
+
+
+ Improve virtual controller detection
+
+
+ Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
+
+
+ Yes
+
+
+ No
+
+
+ Your device must be restarted in order for the changes to take effect. Would you like to restart now?
+
+
+ Restart required
+
+
+ Yes
+
+
+ No
+
+
+ Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
+
+
+ Warning
+
+
+ Change the virtual controller layout
+
+
+ This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Back
+
+
+ Exit
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ External
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.pt-BR.resx b/HandheldCompanion/Properties/Resources.pt-BR.resx
index f40cf222a..731856e96 100644
--- a/HandheldCompanion/Properties/Resources.pt-BR.resx
+++ b/HandheldCompanion/Properties/Resources.pt-BR.resx
@@ -1,2360 +1,2354 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Sobre
-
-
- Uma combinação de serviço Windows e aplicação otimizada com interface de toque para melhorar a experiência de seu computador de jogo portátil de mão. Os recursos incluem: controle de movimento conhecido também como controle giroscópico, simulação de controlador virtual, sobreposição de acesso rápido para ferramentas, touchpads virtuais, modelo 3D de controlador, sistema de perfis de configurações baseado na aplicação ativa. Handheld Companion depende do driver do ViGEmBus e bibliotecas ViGEmClient como também o filtro de driver do HidHide em modo kernel. Algoritmos de controle de movimentos são baseados no trabalho de Jibbsmart e informação disponível em GyroWiki.
-
-
- Acelerômetro
-
-
- Autor
-
-
- Colaboradores
-
-
- Descrição
-
-
- Doar
-
-
- Girometro
-
-
- Inclinometro
-
-
- N/A
-
-
- Links Relacionados
-
-
- Externo
-
-
- Interno
-
-
- Nome do sensor
-
-
- Especificação do Sensor
-
-
- Serviço
-
-
- Código Fonte
-
-
- Versão
-
-
- Wiki
-
-
- Administrador
-
-
- Ocultar controle ao conectar
-
-
- Ocultar controle físico quando conectado
-
-
- Conectar
-
-
- Controle
-
-
- Ocultamento de controle
-
-
- configurações de controle
-
-
- Desconectar
-
-
- Dispositivos de entrada
-
-
- Reexibir controle ao encerrar
-
-
- Restaurar visibilidade de todos os controles físicos quando a aplicação é encerrada
-
-
- Força da vibração
-
-
- Alterar a força da vibração do controle
-
-
-
- ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
-
-
- Diminuir o valor de TDP
-
-
- Diminuir o TDP (do inglês, thermal design power ou potência térmica de projeto) do perfil aplicado ou do sistema em 1 (um) watt
-
-
- Pressione para definir gatilho
-
-
- Pressione para definir saída de teclado
-
-
- Aumentar o valor de TDP
-
-
- Aumentar o TDP (do inglês, thermal design power ou potência térmica de projeto) do perfil aplicado ou do sistema em 1 (um) watt
-
-
- Exibir controle 3D
-
-
- Alterar a tecla de atalho 3D pressionando um botão ou uma tecla especial
-
-
- Exibir trackpads virtuais
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Invocar a janela de ferramentas rápidas
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Atalho personalizado
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Exibir e ocultar a área de trabalho
-
-
- Pressione esta combinação de teclas: Windows + D
-
-
- ESC
-
-
- Pressione esta tecla: ESC
-
-
- Alterna entre modo janela e tela cheia
-
-
- Pressione esta combinação de teclas: Alt + Enter
-
-
- Guia ou Botão PS
-
-
- Simular a entrada de um botão Xbox Guia ou botão Sony PS
-
-
- Exibir o teclado em tela de toque
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Forçar encerramento da aplicação
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Exibir e ocultar a janela principal
-
-
- Alterar a tecla de atalho pressionando um botão ou uma tecla especial
-
-
- Abrir o Gerenciador de Tarefas
-
-
- Pressione esta combinação de teclas: Ctrl + Shift + Esc
-
-
- Abrir Visão de Tarefas
-
-
- Pressionar esta combinação de teclas: Windows + Tab
-
-
- Alternar Suspensão de tarefa
-
-
- Suspender or resumir a aplicação em primeiro plano
-
-
- Handheld Companion
-
-
- Sobre
-
-
- Controle
-
-
- Sobreposição
-
-
- Perfis
-
-
- OK
-
-
- Configurações
-
-
- 8BitDo Lite 2
-
-
- Alinhamento
-
-
- Alterar o alinhamento da sobreposição de controle 3D
-
-
- Alterar o alinhamento da sobreposição de trackpads
-
-
- Sempre no topo
-
-
- Quando ativado, a sobreposição do controle 3D estará sempre no topo de outras janelas
-
-
- Back
-
-
- Frente para câmera
-
-
- Alterar o comportamento do modelo de controle 3D em sobreposição para ficar de frente para a câmera
-
-
- Eixo lateral (arfagem) estacionário
-
-
- Alterar o ângulo, por grau
-
-
- Cor de fundo
-
-
- Alterar a cor de fundo da sobreposição do controle 3D
-
-
- Opções de controle
-
-
- PlayStation DualSense
-
-
- Controle emulado
-
-
- Frente para câmera
-
-
- O modelo 3D vagarosamente rotaciona para encarar a câmera como posição padrão
-
-
- Escutando...
-
-
- MACHENIKE HG510
-
-
- Gatilho principal
-
-
- Alterar o gatilho principal da sobreposição de controle 3D
-
-
- Movimento
-
-
- O modelo se movimentará de acordo com os movimentos do usuário baseado em informações do sensor
-
-
- N64
-
-
- Controle OEM (Original do fabricante)
-
-
- Opacidade
-
-
- Alterar a opacidade da sobreposição de controle 3D
-
-
- Alterar a opacidade da sobreposição de trackpads
-
-
- Sobreposição
-
-
- Modelo de sobreposição
-
-
- Alterar o modelo usado na sobreposição de controle 3D
-
-
- Prévia de sobreposição
-
-
- Configurações de renderização
-
-
- Antisserrilhamento
-
-
- Alterar a situação de antisserrilhamento (suavização de bordas) da sobreposição
-
-
- Alterar as configurações de renderização do seu modelo de controle 3D estacionário
-
-
- Frequência de atualização
-
-
- Alterar a frequência de atualizações da renderização, em atualizações por segundo
-
-
- Tamanho
-
-
- Alterar o tamanho da sobreposição de controle 3D
-
-
- Alterar o tamanho da sobreposição dos trackpads
-
-
- Start
-
-
- Controle Fisher-Price
-
-
- Opções dos trackpads
-
-
- Xbox One
-
-
- ZD O+
-
-
- Sobreposição
-
-
- Resumir
-
-
- Suspender
-
-
- Configurações adicionais
-
-
- Multiplicador de movimento de mirar
-
-
- Botão de ativação
-
-
- Um multiplicador de sensibilidade adicional de movimento quando utilizando miras através do uso de um botão de ativação
-
-
- Valor de multiplicador
-
-
- Opções de câmera
-
-
- Curva de resposta personalizada
-
-
- Saída enviada para o jogo
-
-
- Intensidade de movimentação
-
-
- Agressiva
-
-
- Padrão
-
-
- Opções predefinidas
-
-
- Precisa
-
-
- Duração da virada
-
-
- Alterar a duração da virada, calibrar a virada em 180 graus, em milissegundos
-
-
- Analógio de virada (experimental)
-
-
- Apontar a câmera na direção do analógico de virada (direito), rotacionar a câmera puramente no plano horizontal por rotação
-
-
- Habilitar analógico de virada
-
-
- Sensibilidade
-
-
- Alterar a sensibilidade de movimento do eixo horizontal e vertical
-
-
- Sensibilidade X
-
-
- Alterar a sensibilidade de movimento para o eixo horizontal
-
-
- Sensibilidade Y
-
-
- Alterar a sensibilidade de movimento para o eixo vertical
-
-
- Sensibilidade do analógico
-
-
- Alterar a taxa de rotação
-
-
- Configurações adicionais
-
-
- Zona morta
-
-
- Altera a zona morta da direção, em graus. Melhora a direção reta
-
-
- Entrada de jogo Joystick
-
-
- Joystick de direção
-
-
- Opções de joystick de direção
-
-
- Prévia de joystick de direção
-
-
- Ângulo máximo de direção
-
-
- Alterar o valor de ângulo máximo de direção, em graus
-
-
- Linearidade de direção
-
-
- Mapeamento entre entrada e direção. Valores mais baixos fornecem mais precisão próximos do travamento total do volante, mas menos precisão perto do centro. Valores altos fornecem mais precisão perto do centro, mas menos precisão perto do travamento total do volante. Valor 1.0 é um mapeamento linear
-
-
- Multiplicador de acelerômetro
-
-
- Alterar o valor de acelerômetro relatado pelo sistema
-
-
- Configurações adicionais
-
-
- Anti-zona morta
-
-
- Alterar a anti-zona morta de jogo, em percentual
-
-
- %
-
-
- Você tem certeza que deseja excluir?
-
-
- Este item será excluído imediatamente. Você não pode desfazer esta ação.
-
-
- Você tem certeza que deseja sobreescrever este perfil?
-
-
- {0} será sobreescrito. Você não pode desfazer esta ação.
-
-
- Impulsionar a potência limite
-
-
- Alterar o impulso de limite de potência térmica
-
-
- Cancelar
-
-
- Criar um novo perfil
-
-
- Excluir
-
-
- Excluir perfil
-
-
- Perfil de usuário por jogo
-
-
- O perfil será aplicado automaticamente quando a aplicação indicada é detectada
-
-
- Configurações globais
-
-
- Alterar as configurações do perfil global
-
-
- Multiplicador do girometro
-
-
- Alterar o valor do girometro relatado pelo sistema
-
-
- Eixo de direção pelo giroscópico
-
-
- Para controlar o movimento horizontal do controle, você pode usar tanto o eixo vertical (rolamento) ou o longitudinal (leme)
-
-
- Inverter o eixo horizontal
-
-
- Inverter o eixo vertical
-
-
- Configurações de controle de movimento
-
-
- Alterar as configurações globais de controle de movimento
-
-
- OK
-
-
- Configurações de energia
-
-
- Alterar as configurações de energia
-
-
- Detalhes do perfil
-
-
- Nome do perfil
-
-
- Caminho do perfil
-
-
- Perfis
-
-
- Seleção de perfil
-
-
- Selecionar o perfil que deseja editar
-
-
- Configurações de perfil
-
-
- Perfil atualizado
-
-
- foi atualizado.
-
-
- Rolamento
-
-
- X
-
-
- Y
-
-
- Estilo de entrada
-
-
- As entradas fisicas do controle podem ser programadas para agir como diferentes tipos de dispositivos
-
-
- Dispositivo de saída
-
-
- Selecionar o dispositivo que receberá os comandos de movimento
-
-
- Limite de energia sustentado
-
-
- Alterar o limite de energia térmico sustentado
-
-
- Limite de TDP
-
-
- Limita a energia do processador via ajuste de TDP (do inglês, Thermal Design Power ou potência térmica de projeto) para menos energia total
-
-
- Ligar o controle de movimento universal
-
-
- Desligado, ligar com botão(ões)
-
-
- Ligado, desligar com botão(ões)
-
-
- Ativação de movimento
-
-
- Com a entrada de movimento desligada, use o(s) botão(ões) selecionado(s) para ligar o movimento,
-com a entrada de movimento ligada, use o(s) botão(ões) selecionado(s) para desligar o movimento.
-
-
- Selecionar o dispositivo que receberá os comandos de movimento
-
-
- Configurações de controle de movimento universal
-
-
- Traduz os movimentos dos dispositivos em entradas de controle
-
-
- Atualizar perfil
-
-
- Permitir acesso direto ao dispositivo de controle físico pela aplicação (ignorar controle virtual emulado)
-
-
- Compatiblidade expandida (XInputPlus)
-
-
- Leme
-
-
- Sim
-
-
- Desconectar
-
-
- Controle Manual da Frequência da GPU
-
-
- Define a GPU para utilizar uma frequência fixa
-
-
- MHz
-
-
- Modo de energia
-
-
- Equilibrado
-
-
- Otimizar o seu dispositivo baseado com base no uso de energia e desempenho
-
-
- Melhor eficiência energética
-
-
- Melhor desempenho
-
-
- Impulso
-
-
- Limite de TDP
-
-
- Limita a energia do processador via ajuste de TDP (do inglês, Thermal Design Power ou potência térmica de projeto) para menos energia total
-
-
- Limite de TDP é sobreescrito por um perfil
-
-
- Sustentado
-
-
- W
-
-
- Criar perfil
-
-
- Aguardando por processo em primeiro plano...
-
-
- Fornece suporte de giroscópico e acelerômetro para computadores de jogo portáteis através de um controle virtual. Se o serviço está em execução, o controle embutido será ocultado das aplicações ausentes da lista de exceções. Se o serviço estiver desligado ou ausente, o controle embutido será revelado e o controle virtual desligado.
-
-
- Serviço de Controle
-
-
- Idioma
-
-
- O idioma da aplicação
-
-
- Reinício necessário
-
-
- Para que as alterações entrem em vigor, por favor reinicie a aplicação
-
-
- Tema da aplicação
-
-
- O tema da aplicação, modo claro ou escuro
-
-
- Iniciar a aplicação automaticamente
-
-
- A aplicação será iniciada automaticamente quando eu entrar no Windows
-
-
- Tipo de fundo da aplicação
-
-
- Acrílico
-
-
- O fundo da aplicação, nenhum, mica, abas, acrílico
-
-
- Mica
-
-
- Nenhum
-
-
- Abas
-
-
- Verificar por atualizações
-
-
- Fechar minimiza
-
-
- A aplicação será minimizada ao invés de encerrada ao clicar no botão fechar janela
-
-
- Ligar o perfil de área de trabalho ao iniciar
-
-
- O perfil de área de trabalho será ligado automaticamente no início da aplicação
-
-
- Download
-
-
- Baixando -
-
-
- Modo de eficiência
-
-
- O modo de eficiência reduz a prioridade de processos de plano de fundo e melhora a eficiência energética
-
-
- Opções gerais
-
-
- Instalar agora
-
-
- Última verificação:
-
-
- Opções de notificação
-
-
- Abrir aplicação em plano de fundo
-
-
- A aplicaç"ao será inicializada minimizada e exibida na barra de tarefas
-
-
- Externo
-
-
- Interno
-
-
- Opções de sensor
-
-
- Direção de colocação do sensor externo
-
-
- Escolhere em qual lado do dispositivo o sensor externo foi montado
-
-
- Sensor externo de cabeça para baixo
-
-
- O sensor foi montado de cabeça para baixo, possivelmente com um conversor USB-C
-
-
- Seleção de sensor
-
-
- Selecionar o sensor desejado para entrada de movimento
-
-
- Configurações
-
-
- Tipo de inicialização
-
-
- Utilizado pelo gerenciador de serviço para definir o tipo de inicialização do serviço
-
-
- Potência Máxima
-
-
- O máximo de potência em watts fornecidos ao processador
-
-
- Potência Mínima
-
-
- O mínimo de potência em watts fornecidos ao processador
-
-
- Sobreposição dos limites de potência (cTDP)
-
-
- Permite modificar o mínimo e máximo de valores de potência (TDP) além das especificações do CPU
-
-
- Escuro
-
-
- Claro
-
-
- Notificação toast
-
-
- Receber notificações da aplicação na Central de Ações do Windows
-
-
- Atualização disponível
-
-
- Procurando atualizações...
-
-
- Não conseguimos baixar o arquivo de atualização.
-
-
- Não conseguimos alcançar a página do github.
-
-
- Não conseguimos localizar o arquivo de atualização.
-
-
- Opa. Houve um problema com a atualização.
-
-
- Você está com a versão mais recente
-
-
- O controle físico está agora oculto e seus comandos estão sendo direcionados para o controle virtual
-
-
- Usuário
-
-
- Execute esta ferramenta como um Administrador para destravar estas configurações
-
-
- ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
-
-
- Silenciar controle virtual
-
-
- Silenciar controle virutal em aplicações relacionadas ao Steam
-
-
- Configurações de controle
-
-
- Alterar as configurações de controle virtual
-
-
- Anti-zona morta de movimento
-
-
- Compensar por zona morta dentro do jogo, melhor o registro de movimentos pequenos
-
-
- ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- Melhorar a circularidade do analógico
-
-
- Circularidade do analógico esquerdo
-
-
- Circularidade do analógico direito
-
-
- S
-
-
- Ajustar o percentual de zona morta interior e exterior do joystick esquerdo
-
-
- % de zona morta do joystick direito
-
-
- Ajustar o percentual de zona morta interior e exterior do joystick direito
-
-
- % de zona morta do gatilho esquerdo
-
-
- Ajustar o percentual de zona morta interior e exterior do gatilho esquerdo
-
-
- % de zona morta do gatilho direito
-
-
- Ajustar o percentual de zona morta interior e exterior do gatilho direito
-
-
- Vibrar controle ao conectar
-
-
- Vibrar o controle físico quando conectado
-
-
- Layout de área de trabalho
-
-
- Ligar e desligar o layout de controle para área de trabalho
-
-
- Exibir a Central de Ações
-
-
- Exibe e oculta a Central de Ações do Windows
-
-
- Layout de controle
-
-
- Cooler Fan/Ventoinha manual
-
-
- Defina o ciclo de funcionamento da ventoinha/cooler fan para o valor definido pelo usuário
-
-
- Exibição em tela
-
-
- Ligar a exibição de suporte em tela
-
-
- Diminuir brilho
-
-
- Diminuir o brilho da tela ativa em 5%
-
-
- Diminuir volume
-
-
- Diminuir o volume de som do sistema em 5%
-
-
- Aumentar brilho
-
-
- Aumentar o brilho da tela ativa em 5%
-
-
- Aumentar volume
-
-
- Aumentar o volume de som do sistema em 5%
-
-
- TDP Automático
-
-
- Ajuste automático do TDP baseado no FPS (Frames per second, quadros por segundo) medidos e o FPS alvo definido
-
-
- Taxa de quadros (FPS) alvo
-
-
- O valor alvo de FPS (Frames per second, quadros por segundo) desejado para o controlador de TDP automático
-
-
- Frequência máxima do clock da GPU
-
-
- Velocidade máxima do clock da GPU em Mhz
-
-
- FPS
-
-
- Nível de exibição da sobreposição
-
-
- Alterar o nível de informação exibida na tela
-
-
- Frequência de atualização
-
-
- Alterar a frequência de atualização das informações exibidas em tela
-
-
- Limite de quadros por segundo (FPS)
-
-
- Limita a quantidade de quadros por segundo (FPS) para aplicações 3D
-
-
- Abrir a Ferramenta de Captura
-
-
- Pressione esta combinação: Windows + Shift + S
-
-
- Teclas de atalho
-
-
- Usar padrão do sistema
-
-
- A,B,X,Y
-
-
- BOTÕES TRASEIROS
-
-
- BUMPERS
-
-
- MENU
-
-
- OEM
-
-
- PAD DIGITAL
-
-
- JOYSTICK ESQUERDO
-
-
- BOTÕES JOYSTICK ESQUERDO
-
-
- JOYSTICK DIREITO
-
-
- BOTÕES JOYSTICK DIREITO
-
-
- TRACKPAD ESQUERDO
-
-
- BOTÕES TRACKPAD ESQUERDO
-
-
- TRACKPAD DIREITO
-
-
- BOTÕES TRACKPAD DIREITO
-
-
- GATILHO ESQUERDO
-
-
- BOTÕES GATILHO ESQUERDO
-
-
- GATILHO DIREITO
-
-
- BOTÕES GATILHO DIREITO
-
-
- Fabricante
-
-
- Parceiro
-
-
- Nome do produto
-
-
- Layout de Área de Trabalho
-
-
- Definir layout de área de trabalho
-
-
- Definir layout do controle quando no modo de área de trabalho
-
-
- Editar
-
-
- Ligar layout de área de trabalho
-
-
- Layouts de controle fora de jogos
-
-
- Talvez você queira clicar em Conectar ao lado do seu controle conectado.
-
-
- Você não possui controle físico conectado. Nenhuma entrada será enviada para o HC ou seu serviço.
-
-
- Por favor, certifique-se de conectar um dispositivo compatível com XInput ou DInput.
-
-
- Nenhum controle físico detectado
-
-
- Nenhum controle físico conectado
-
-
- Talvez você queira iniciar o serviço do Companion ou certificar-se que o a situação do seu controle virtual é: Conectado
-
-
- Seu controle físico está oculto, no entanto você não possui controle virtual disponível. Nenhuma entrada será enviada para os jogos.
-
-
- Nenhum controle virtual detectado
-
-
- Talvez você queira reativar seu controle virtual ou ocultar seu controle físico.
-
-
- Seu controle físico está oculto e ainda você também está com o controle virtual inativo.
-
-
- O controle físico está oculto
-
-
- Talvez você queira ocultar seu controle físico ou inativar seu controle virtual.
-
-
- Seu controle físico não está oculto, no entanto você tem um controle virtual ativo. Você pode encontrar entrada duplicada nos jogos.
-
-
- O controle físico não está oculto
-
-
- HD rumble (tremida)
-
-
- Usar o motor de tremida de alta definição, ao custo de maior uso de CPU
-
-
- Configurações do controlador
-
-
- Aplicar modelo
-
-
- Botões
-
-
- Cancelar
-
-
- COMUNIDADE
-
-
- Confirmar
-
-
- Dpad
-
-
- Exportar para controle atual
-
-
- Exportar layout
-
-
- Gyro
-
-
- Joysticks
-
-
- Autor do layout
-
-
- Descrição do layout
-
-
- Título do layout
-
-
- Salvar informações do jogo com o layout
-
-
- Exibir apenas os modelos do controle atual
-
-
- Seletor de modelo de layout
-
-
- MODELOS
-
-
- Trackpads
-
-
- Gatilhos
-
-
- ms
-
-
- Desligado
-
-
- Estendido
-
-
- Completo
-
-
- Mínimo
-
-
- CPU
-
-
- Preferência de desempenho energético (Energy performance preference - EPP)
-
-
- Distribuição de energia CPU/GPU
-
-
- Especifica a política de distribuição de energia entre CPU e GPU
-
-
- Definição de limite de energia
-
-
- Orientação da tela
-
-
- Alguns recursos dependem do conhecimento da orientação da tela para funcionar corretamente. Se isto não foi detectado apropriadamente, defina a orientação da sua tela correspondente ao seu controle, então clique Detectar
-
-
- Detectar
-
-
- Não definida
-
-
- Definição de limite de energia
-
-
- Opções de ferramentas rápidas
-
-
- %
-
-
- Definir o modo de impulso de CPU
-
-
- Modo de impulso de CPU
-
-
- Definir o ciclo de funcionamento da ventoinha/cooler fan para o valor definido pelo usuário
-
-
- Cooler Fan/Ventoinha manual
-
-
- Ajustar a resolução da tela principal e taxa de atualização
-
-
- Resolução de tela e taxa de atualização
-
-
- Superior direito
-
-
- Superior esquerdo
-
-
- Localização da janela
-
-
- Inferior direito
-
-
- Inferior esquerdo
-
-
- Opções de energia
-
-
- Definir localização da janela de ferramentas rápidas
-
-
- Aplicativos de terceiros
-
-
- Nenhum
-
-
- Fundo das ferramentas rápidas: Nenhum, Mica, Abas ou Acrílico
-
-
- Automaticamente desligar RTSS quando o Companion é encerrado
-
-
- Automaticamente desligar HWiNFO quando o Companion é encerrado
-
-
- HWiNFO
-
-
- Padrão
-
-
- Perfil atual:
-
-
- RivaTuner Statistics Server
-
-
- Automaticamente esconder as ferramentas rápidas quando o usuário clica fora da janela
-
-
- Ocultar quando perder foco
-
-
- Esta entrada irá operar como um joystick simples. Ideal para notebook ou portáteis no estilo concha, alternada automática de rolagem de guinada baseado em como o dispositivo está sendo segurado (aberto em 90 ou 180 graus).
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Cruz
-
-
- Círculo
-
-
- Quadrado
-
-
- Triângulo
-
-
- Share
-
-
- Sony
-
-
- Options
-
-
- Controle DualShock 4 emulado
-
-
- Sem controle emulado
-
-
- Controle XBOX 360 emulado
-
-
- Conectado
-
-
- Desconectado
-
-
- Alternar Rolagem de Guinada Auto
-
-
- Câmera de Joystick
-
-
- Joystick de direção (tipo volante)
-
-
- Espaço do jogador
-
-
- Handheld Companion
-
-
- Sobreposição
-
-
- Ferramentas rápidas
-
-
- Windows
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- Menu
-
-
- Analógico esquerdo
-
-
- Analógico direito
-
-
- Este é seu perfil padrão de controle. Este perfil será aplicado a todas as suas aplicações que não possuem um perfil específico. Algumas opções que requerem a definição de um arquivo executável estarão desabilitadas.
-
-
- Opa. Parece que esse perfil não possui um arquivo executável definido. Como isto será possível?
-
-
- Opa. Parece que esse perfil não possui um caminho de diretório até a aplicação. Algumas opções que requerem a definição de um arquivo executável estarão desabilitadas.
-
-
- Opa. Parece que você não possui o nível de permissão necessário para modificar o conteúdo desta aplicação. Certifique-se de iniciar este programa com privilégios administrativos.
-
-
- Nada para ver aqui.
-
-
- Opa. Parece que o arquivo executável deste perfil está em execução. Algumas opções estarão indisponíveis até que a execução seja encerrada.
-
-
- Padrão
-
-
- Eco
-
-
- Alta
-
-
- Automático
-
-
- Desabilitado
-
-
- Manual
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- LB
-
-
- RB
-
-
- Guia
-
-
- Menu
-
-
- Esta entrada irá operar como um joystick simples. Isto é voltado para aplicações que utilizam joystick tradicional
-
-
- Esta entrada irá operar como um joystick otimizado para controlar um volante ou um jogo de corrida
-
-
- Esta entrada irá operar como um joystick otimizado para controlar uma câmera em primeira ou terceira pessoa
-
-
- Handheld Companion
-
-
- Opções
-
-
- STEAM
-
-
- Centro de comando
-
-
- Armory crate
-
-
- M1
-
-
- Win
-
-
- Esc
-
-
- KB
-
-
- Personalizado
-
-
- Dispositivo
-
-
- Troca automática Rolamento e Leme
-
-
- Câmera de Joystick
-
-
- Direção de Joystick
-
-
- Espaço do Jogador
-
-
- Analógico Esquerdo
-
-
- Analógico Direito
-
-
- L2
-
-
- Analógico Esquerdo
-
-
- R2
-
-
- Analógico Direito
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- DPad Baixo
-
-
- DPad Esquerda
-
-
- PPad Direita
-
-
- DPad Cima
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- L5
-
-
- Analógico Esquerdo
-
-
- Analógico Esquerdo Baixo
-
-
- Analógico Esquerdo Esquerda
-
-
- Analógico Esquerdo Direita
-
-
- Analógico Esquerdo Cima
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Analógico Direito
-
-
- Analógico Direito Baixo
-
-
- Analógico Direito Esquerda
-
-
- Analógico Direito Direita
-
-
- Analógico Direito Cima
-
-
- A
-
-
- Sempre Ligado
-
-
- B
-
-
- Back
-
-
- DPad Baixo
-
-
- DPad Esquerda
-
-
- DPad Direita
-
-
- DPad Cima
-
-
- Ombro Esquerda
-
-
- Polegar Esquerda
-
-
- Gatilho Esquerda
-
-
- Ombro Direita
-
-
- Polegar Direita
-
-
- Gatilho Direita
-
-
- Start
-
-
- X
-
-
- Y
-
-
- Opa. Este perfil parece estar em execução algumas opções necessitam que o executável esteja encerrado.
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- S
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- LeftStick
-
-
- RightStick
-
-
- Yes
-
-
- No
-
-
- Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
-
-
- Warning
-
-
- Disabled
-
-
- Injection (recommended)
-
-
- Redirection
-
-
- Improve virtual controller detection
-
-
- Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
-
-
- Yes
-
-
- No
-
-
- Your device must be restarted in order for the changes to take effect. Would you like to restart now?
-
-
- Restart required
-
-
- Yes
-
-
- No
-
-
- Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
-
-
- Warning
-
-
- Change the virtual controller layout
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Back
-
-
- Exit
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- External
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- GPU
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Sobre
+
+
+ Uma combinação de serviço Windows e aplicação otimizada com interface de toque para melhorar a experiência de seu computador de jogo portátil de mão. Os recursos incluem: controle de movimento conhecido também como controle giroscópico, simulação de controlador virtual, sobreposição de acesso rápido para ferramentas, touchpads virtuais, modelo 3D de controlador, sistema de perfis de configurações baseado na aplicação ativa. Handheld Companion depende do driver do ViGEmBus e bibliotecas ViGEmClient como também o filtro de driver do HidHide em modo kernel. Algoritmos de controle de movimentos são baseados no trabalho de Jibbsmart e informação disponível em GyroWiki.
+
+
+ Acelerômetro
+
+
+ Autor
+
+
+ Colaboradores
+
+
+ Descrição
+
+
+ Doar
+
+
+ Girometro
+
+
+ Inclinometro
+
+
+ N/A
+
+
+ Links Relacionados
+
+
+ Externo
+
+
+ Interno
+
+
+ Nome do sensor
+
+
+ Especificação do Sensor
+
+
+ Serviço
+
+
+ Código Fonte
+
+
+ Versão
+
+
+ Wiki
+
+
+ Administrador
+
+
+ Ocultar controle ao conectar
+
+
+ Ocultar controle físico quando conectado
+
+
+ Conectar
+
+
+ Controle
+
+
+ Ocultamento de controle
+
+
+ configurações de controle
+
+
+ Desconectar
+
+
+ Dispositivos de entrada
+
+
+ Reexibir controle ao encerrar
+
+
+ Restaurar visibilidade de todos os controles físicos quando a aplicação é encerrada
+
+
+ Força da vibração
+
+
+ Alterar a força da vibração do controle
+
+
+
+ ..\Resources\icon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ Diminuir o valor de TDP
+
+
+ Diminuir o TDP (do inglês, thermal design power ou potência térmica de projeto) do perfil aplicado ou do sistema em 1 (um) watt
+
+
+ Pressione para definir gatilho
+
+
+ Pressione para definir saída de teclado
+
+
+ Aumentar o valor de TDP
+
+
+ Aumentar o TDP (do inglês, thermal design power ou potência térmica de projeto) do perfil aplicado ou do sistema em 1 (um) watt
+
+
+ Exibir controle 3D
+
+
+ Alterar a tecla de atalho 3D pressionando um botão ou uma tecla especial
+
+
+ Exibir trackpads virtuais
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Invocar a janela de ferramentas rápidas
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Atalho personalizado
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Exibir e ocultar a área de trabalho
+
+
+ Pressione esta combinação de teclas: Windows + D
+
+
+ ESC
+
+
+ Pressione esta tecla: ESC
+
+
+ Alterna entre modo janela e tela cheia
+
+
+ Pressione esta combinação de teclas: Alt + Enter
+
+
+ Guia ou Botão PS
+
+
+ Simular a entrada de um botão Xbox Guia ou botão Sony PS
+
+
+ Exibir o teclado em tela de toque
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Forçar encerramento da aplicação
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Exibir e ocultar a janela principal
+
+
+ Alterar a tecla de atalho pressionando um botão ou uma tecla especial
+
+
+ Abrir o Gerenciador de Tarefas
+
+
+ Pressione esta combinação de teclas: Ctrl + Shift + Esc
+
+
+ Abrir Visão de Tarefas
+
+
+ Pressionar esta combinação de teclas: Windows + Tab
+
+
+ Alternar Suspensão de tarefa
+
+
+ Suspender or resumir a aplicação em primeiro plano
+
+
+ Handheld Companion
+
+
+ Sobre
+
+
+ Controle
+
+
+ Sobreposição
+
+
+ Perfis
+
+
+ OK
+
+
+ Configurações
+
+
+ 8BitDo Lite 2
+
+
+ Alinhamento
+
+
+ Alterar o alinhamento da sobreposição de controle 3D
+
+
+ Alterar o alinhamento da sobreposição de trackpads
+
+
+ Sempre no topo
+
+
+ Quando ativado, a sobreposição do controle 3D estará sempre no topo de outras janelas
+
+
+ Back
+
+
+ Frente para câmera
+
+
+ Alterar o comportamento do modelo de controle 3D em sobreposição para ficar de frente para a câmera
+
+
+ Eixo lateral (arfagem) estacionário
+
+
+ Alterar o ângulo, por grau
+
+
+ Cor de fundo
+
+
+ Alterar a cor de fundo da sobreposição do controle 3D
+
+
+ Opções de controle
+
+
+ PlayStation DualSense
+
+
+ Controle emulado
+
+
+ Frente para câmera
+
+
+ O modelo 3D vagarosamente rotaciona para encarar a câmera como posição padrão
+
+
+ Escutando...
+
+
+ MACHENIKE HG510
+
+
+ Gatilho principal
+
+
+ Alterar o gatilho principal da sobreposição de controle 3D
+
+
+ Movimento
+
+
+ O modelo se movimentará de acordo com os movimentos do usuário baseado em informações do sensor
+
+
+ N64
+
+
+ Controle OEM (Original do fabricante)
+
+
+ Opacidade
+
+
+ Alterar a opacidade da sobreposição de controle 3D
+
+
+ Alterar a opacidade da sobreposição de trackpads
+
+
+ Sobreposição
+
+
+ Modelo de sobreposição
+
+
+ Alterar o modelo usado na sobreposição de controle 3D
+
+
+ Prévia de sobreposição
+
+
+ Configurações de renderização
+
+
+ Antisserrilhamento
+
+
+ Alterar a situação de antisserrilhamento (suavização de bordas) da sobreposição
+
+
+ Alterar as configurações de renderização do seu modelo de controle 3D estacionário
+
+
+ Frequência de atualização
+
+
+ Alterar a frequência de atualizações da renderização, em atualizações por segundo
+
+
+ Tamanho
+
+
+ Alterar o tamanho da sobreposição de controle 3D
+
+
+ Alterar o tamanho da sobreposição dos trackpads
+
+
+ Start
+
+
+ Controle Fisher-Price
+
+
+ Opções dos trackpads
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ Sobreposição
+
+
+ Resumir
+
+
+ Suspender
+
+
+ Configurações adicionais
+
+
+ Multiplicador de movimento de mirar
+
+
+ Botão de ativação
+
+
+ Um multiplicador de sensibilidade adicional de movimento quando utilizando miras através do uso de um botão de ativação
+
+
+ Valor de multiplicador
+
+
+ Opções de câmera
+
+
+ Curva de resposta personalizada
+
+
+ Saída enviada para o jogo
+
+
+ Intensidade de movimentação
+
+
+ Agressiva
+
+
+ Padrão
+
+
+ Opções predefinidas
+
+
+ Precisa
+
+
+ Duração da virada
+
+
+ Alterar a duração da virada, calibrar a virada em 180 graus, em milissegundos
+
+
+ Analógio de virada (experimental)
+
+
+ Apontar a câmera na direção do analógico de virada (direito), rotacionar a câmera puramente no plano horizontal por rotação
+
+
+ Habilitar analógico de virada
+
+
+ Sensibilidade
+
+
+ Alterar a sensibilidade de movimento do eixo horizontal e vertical
+
+
+ Sensibilidade X
+
+
+ Alterar a sensibilidade de movimento para o eixo horizontal
+
+
+ Sensibilidade Y
+
+
+ Alterar a sensibilidade de movimento para o eixo vertical
+
+
+ Sensibilidade do analógico
+
+
+ Alterar a taxa de rotação
+
+
+ Configurações adicionais
+
+
+ Zona morta
+
+
+ Altera a zona morta da direção, em graus. Melhora a direção reta
+
+
+ Entrada de jogo Joystick
+
+
+ Joystick de direção
+
+
+ Opções de joystick de direção
+
+
+ Prévia de joystick de direção
+
+
+ Ângulo máximo de direção
+
+
+ Alterar o valor de ângulo máximo de direção, em graus
+
+
+ Linearidade de direção
+
+
+ Mapeamento entre entrada e direção. Valores mais baixos fornecem mais precisão próximos do travamento total do volante, mas menos precisão perto do centro. Valores altos fornecem mais precisão perto do centro, mas menos precisão perto do travamento total do volante. Valor 1.0 é um mapeamento linear
+
+
+ Multiplicador de acelerômetro
+
+
+ Alterar o valor de acelerômetro relatado pelo sistema
+
+
+ Configurações adicionais
+
+
+ Anti-zona morta
+
+
+ Alterar a anti-zona morta de jogo, em percentual
+
+
+ %
+
+
+ Você tem certeza que deseja excluir?
+
+
+ Este item será excluído imediatamente. Você não pode desfazer esta ação.
+
+
+ Você tem certeza que deseja sobreescrever este perfil?
+
+
+ {0} será sobreescrito. Você não pode desfazer esta ação.
+
+
+ Impulsionar a potência limite
+
+
+ Alterar o impulso de limite de potência térmica
+
+
+ Cancelar
+
+
+ Criar um novo perfil
+
+
+ Excluir
+
+
+ Excluir perfil
+
+
+ Perfil de usuário por jogo
+
+
+ O perfil será aplicado automaticamente quando a aplicação indicada é detectada
+
+
+ Configurações globais
+
+
+ Alterar as configurações do perfil global
+
+
+ Multiplicador do girometro
+
+
+ Alterar o valor do girometro relatado pelo sistema
+
+
+ Eixo de direção pelo giroscópico
+
+
+ Para controlar o movimento horizontal do controle, você pode usar tanto o eixo vertical (rolamento) ou o longitudinal (leme)
+
+
+ Inverter o eixo horizontal
+
+
+ Inverter o eixo vertical
+
+
+ Configurações de controle de movimento
+
+
+ Alterar as configurações globais de controle de movimento
+
+
+ OK
+
+
+ Configurações de energia
+
+
+ Alterar as configurações de energia
+
+
+ Detalhes do perfil
+
+
+ Nome do perfil
+
+
+ Caminho do perfil
+
+
+ Perfis
+
+
+ Seleção de perfil
+
+
+ Selecionar o perfil que deseja editar
+
+
+ Configurações de perfil
+
+
+ Perfil atualizado
+
+
+ foi atualizado.
+
+
+ Rolamento
+
+
+ X
+
+
+ Y
+
+
+ Estilo de entrada
+
+
+ As entradas fisicas do controle podem ser programadas para agir como diferentes tipos de dispositivos
+
+
+ Dispositivo de saída
+
+
+ Selecionar o dispositivo que receberá os comandos de movimento
+
+
+ Limite de energia sustentado
+
+
+ Alterar o limite de energia térmico sustentado
+
+
+ Limite de TDP
+
+
+ Limita a energia do processador via ajuste de TDP (do inglês, Thermal Design Power ou potência térmica de projeto) para menos energia total
+
+
+ Ligar o controle de movimento universal
+
+
+ Desligado, ligar com botão(ões)
+
+
+ Ligado, desligar com botão(ões)
+
+
+ Ativação de movimento
+
+
+ Com a entrada de movimento desligada, use o(s) botão(ões) selecionado(s) para ligar o movimento,
+com a entrada de movimento ligada, use o(s) botão(ões) selecionado(s) para desligar o movimento.
+
+
+ Selecionar o dispositivo que receberá os comandos de movimento
+
+
+ Configurações de controle de movimento universal
+
+
+ Traduz os movimentos dos dispositivos em entradas de controle
+
+
+ Atualizar perfil
+
+
+ Permitir acesso direto ao dispositivo de controle físico pela aplicação (ignorar controle virtual emulado)
+
+
+ Compatiblidade expandida (XInputPlus)
+
+
+ Leme
+
+
+ Sim
+
+
+ Desconectar
+
+
+ Controle Manual da Frequência da GPU
+
+
+ Define a GPU para utilizar uma frequência fixa
+
+
+ MHz
+
+
+ Modo de energia
+
+
+ Equilibrado
+
+
+ Otimizar o seu dispositivo baseado com base no uso de energia e desempenho
+
+
+ Melhor eficiência energética
+
+
+ Melhor desempenho
+
+
+ Impulso
+
+
+ Limite de TDP
+
+
+ Limita a energia do processador via ajuste de TDP (do inglês, Thermal Design Power ou potência térmica de projeto) para menos energia total
+
+
+ Limite de TDP é sobreescrito por um perfil
+
+
+ Sustentado
+
+
+ W
+
+
+ Criar perfil
+
+
+ Aguardando por processo em primeiro plano...
+
+
+ Fornece suporte de giroscópico e acelerômetro para computadores de jogo portáteis através de um controle virtual. Se o serviço está em execução, o controle embutido será ocultado das aplicações ausentes da lista de exceções. Se o serviço estiver desligado ou ausente, o controle embutido será revelado e o controle virtual desligado.
+
+
+ Serviço de Controle
+
+
+ Idioma
+
+
+ O idioma da aplicação
+
+
+ Reinício necessário
+
+
+ Para que as alterações entrem em vigor, por favor reinicie a aplicação
+
+
+ Tema da aplicação
+
+
+ O tema da aplicação, modo claro ou escuro
+
+
+ Iniciar a aplicação automaticamente
+
+
+ A aplicação será iniciada automaticamente quando eu entrar no Windows
+
+
+ Tipo de fundo da aplicação
+
+
+ Acrílico
+
+
+ O fundo da aplicação, nenhum, mica, abas, acrílico
+
+
+ Mica
+
+
+ Nenhum
+
+
+ Abas
+
+
+ Verificar por atualizações
+
+
+ Fechar minimiza
+
+
+ A aplicação será minimizada ao invés de encerrada ao clicar no botão fechar janela
+
+
+ Ligar o perfil de área de trabalho ao iniciar
+
+
+ O perfil de área de trabalho será ligado automaticamente no início da aplicação
+
+
+ Download
+
+
+ Baixando -
+
+
+ Modo de eficiência
+
+
+ O modo de eficiência reduz a prioridade de processos de plano de fundo e melhora a eficiência energética
+
+
+ Opções gerais
+
+
+ Instalar agora
+
+
+ Última verificação:
+
+
+ Opções de notificação
+
+
+ Abrir aplicação em plano de fundo
+
+
+ A aplicaç"ao será inicializada minimizada e exibida na barra de tarefas
+
+
+ Externo
+
+
+ Interno
+
+
+ Opções de sensor
+
+
+ Direção de colocação do sensor externo
+
+
+ Escolhere em qual lado do dispositivo o sensor externo foi montado
+
+
+ Sensor externo de cabeça para baixo
+
+
+ O sensor foi montado de cabeça para baixo, possivelmente com um conversor USB-C
+
+
+ Seleção de sensor
+
+
+ Selecionar o sensor desejado para entrada de movimento
+
+
+ Configurações
+
+
+ Tipo de inicialização
+
+
+ Utilizado pelo gerenciador de serviço para definir o tipo de inicialização do serviço
+
+
+ Potência Máxima
+
+
+ O máximo de potência em watts fornecidos ao processador
+
+
+ Potência Mínima
+
+
+ O mínimo de potência em watts fornecidos ao processador
+
+
+ Sobreposição dos limites de potência (cTDP)
+
+
+ Permite modificar o mínimo e máximo de valores de potência (TDP) além das especificações do CPU
+
+
+ Escuro
+
+
+ Claro
+
+
+ Notificação toast
+
+
+ Receber notificações da aplicação na Central de Ações do Windows
+
+
+ Atualização disponível
+
+
+ Procurando atualizações...
+
+
+ Não conseguimos baixar o arquivo de atualização.
+
+
+ Não conseguimos alcançar a página do github.
+
+
+ Não conseguimos localizar o arquivo de atualização.
+
+
+ Opa. Houve um problema com a atualização.
+
+
+ Você está com a versão mais recente
+
+
+ O controle físico está agora oculto e seus comandos estão sendo direcionados para o controle virtual
+
+
+ Usuário
+
+
+ Execute esta ferramenta como um Administrador para destravar estas configurações
+
+
+ ..\Resources\xinput1_x64.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\xinput1_x86.dll;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\XInputPlus.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16
+
+
+ Silenciar controle virtual
+
+
+ Silenciar controle virutal em aplicações relacionadas ao Steam
+
+
+ Configurações de controle
+
+
+ Alterar as configurações de controle virtual
+
+
+ Anti-zona morta de movimento
+
+
+ Compensar por zona morta dentro do jogo, melhor o registro de movimentos pequenos
+
+
+ ..\Resources\controller_base\chord_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ ..\Resources\controller_base\empty_neptune.vdf;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Melhorar a circularidade do analógico
+
+
+ Circularidade do analógico esquerdo
+
+
+ Circularidade do analógico direito
+
+
+ S
+
+
+ Ajustar o percentual de zona morta interior e exterior do joystick esquerdo
+
+
+ % de zona morta do joystick direito
+
+
+ Ajustar o percentual de zona morta interior e exterior do joystick direito
+
+
+ % de zona morta do gatilho esquerdo
+
+
+ Ajustar o percentual de zona morta interior e exterior do gatilho esquerdo
+
+
+ % de zona morta do gatilho direito
+
+
+ Ajustar o percentual de zona morta interior e exterior do gatilho direito
+
+
+ Vibrar controle ao conectar
+
+
+ Vibrar o controle físico quando conectado
+
+
+ Layout de área de trabalho
+
+
+ Ligar e desligar o layout de controle para área de trabalho
+
+
+ Exibir a Central de Ações
+
+
+ Exibe e oculta a Central de Ações do Windows
+
+
+ Layout de controle
+
+
+ Cooler Fan/Ventoinha manual
+
+
+ Defina o ciclo de funcionamento da ventoinha/cooler fan para o valor definido pelo usuário
+
+
+ Exibição em tela
+
+
+ Ligar a exibição de suporte em tela
+
+
+ Diminuir brilho
+
+
+ Diminuir o brilho da tela ativa em 5%
+
+
+ Diminuir volume
+
+
+ Diminuir o volume de som do sistema em 5%
+
+
+ Aumentar brilho
+
+
+ Aumentar o brilho da tela ativa em 5%
+
+
+ Aumentar volume
+
+
+ Aumentar o volume de som do sistema em 5%
+
+
+ TDP Automático
+
+
+ Ajuste automático do TDP baseado no FPS (Frames per second, quadros por segundo) medidos e o FPS alvo definido
+
+
+ Taxa de quadros (FPS) alvo
+
+
+ O valor alvo de FPS (Frames per second, quadros por segundo) desejado para o controlador de TDP automático
+
+
+ Frequência máxima do clock da GPU
+
+
+ Velocidade máxima do clock da GPU em Mhz
+
+
+ FPS
+
+
+ Nível de exibição da sobreposição
+
+
+ Alterar o nível de informação exibida na tela
+
+
+ Frequência de atualização
+
+
+ Alterar a frequência de atualização das informações exibidas em tela
+
+
+ Limite de quadros por segundo (FPS)
+
+
+ Limita a quantidade de quadros por segundo (FPS) para aplicações 3D
+
+
+ Abrir a Ferramenta de Captura
+
+
+ Pressione esta combinação: Windows + Shift + S
+
+
+ Teclas de atalho
+
+
+ Usar padrão do sistema
+
+
+ A,B,X,Y
+
+
+ BOTÕES TRASEIROS
+
+
+ BUMPERS
+
+
+ MENU
+
+
+ OEM
+
+
+ PAD DIGITAL
+
+
+ JOYSTICK ESQUERDO
+
+
+ BOTÕES JOYSTICK ESQUERDO
+
+
+ JOYSTICK DIREITO
+
+
+ BOTÕES JOYSTICK DIREITO
+
+
+ TRACKPAD ESQUERDO
+
+
+ BOTÕES TRACKPAD ESQUERDO
+
+
+ TRACKPAD DIREITO
+
+
+ BOTÕES TRACKPAD DIREITO
+
+
+ GATILHO ESQUERDO
+
+
+ BOTÕES GATILHO ESQUERDO
+
+
+ GATILHO DIREITO
+
+
+ BOTÕES GATILHO DIREITO
+
+
+ Fabricante
+
+
+ Parceiro
+
+
+ Nome do produto
+
+
+ Layout de Área de Trabalho
+
+
+ Definir layout de área de trabalho
+
+
+ Definir layout do controle quando no modo de área de trabalho
+
+
+ Editar
+
+
+ Ligar layout de área de trabalho
+
+
+ Layouts de controle fora de jogos
+
+
+ Talvez você queira clicar em Conectar ao lado do seu controle conectado.
+
+
+ Você não possui controle físico conectado. Nenhuma entrada será enviada para o HC ou seu serviço.
+
+
+ Por favor, certifique-se de conectar um dispositivo compatível com XInput ou DInput.
+
+
+ Nenhum controle físico detectado
+
+
+ Nenhum controle físico conectado
+
+
+ Talvez você queira iniciar o serviço do Companion ou certificar-se que o a situação do seu controle virtual é: Conectado
+
+
+ Seu controle físico está oculto, no entanto você não possui controle virtual disponível. Nenhuma entrada será enviada para os jogos.
+
+
+ Nenhum controle virtual detectado
+
+
+ Talvez você queira reativar seu controle virtual ou ocultar seu controle físico.
+
+
+ Seu controle físico está oculto e ainda você também está com o controle virtual inativo.
+
+
+ O controle físico está oculto
+
+
+ Talvez você queira ocultar seu controle físico ou inativar seu controle virtual.
+
+
+ Seu controle físico não está oculto, no entanto você tem um controle virtual ativo. Você pode encontrar entrada duplicada nos jogos.
+
+
+ O controle físico não está oculto
+
+
+ HD rumble (tremida)
+
+
+ Usar o motor de tremida de alta definição, ao custo de maior uso de CPU
+
+
+ Configurações do controlador
+
+
+ Aplicar modelo
+
+
+ Botões
+
+
+ Cancelar
+
+
+ COMUNIDADE
+
+
+ Confirmar
+
+
+ Dpad
+
+
+ Exportar para controle atual
+
+
+ Exportar layout
+
+
+ Gyro
+
+
+ Joysticks
+
+
+ Autor do layout
+
+
+ Descrição do layout
+
+
+ Título do layout
+
+
+ Salvar informações do jogo com o layout
+
+
+ Exibir apenas os modelos do controle atual
+
+
+ Seletor de modelo de layout
+
+
+ MODELOS
+
+
+ Trackpads
+
+
+ Gatilhos
+
+
+ ms
+
+
+ Desligado
+
+
+ Estendido
+
+
+ Completo
+
+
+ Mínimo
+
+
+ CPU
+
+
+ Preferência de desempenho energético (Energy performance preference - EPP)
+
+
+ Distribuição de energia CPU/GPU
+
+
+ Especifica a política de distribuição de energia entre CPU e GPU
+
+
+ Definição de limite de energia
+
+
+ Orientação da tela
+
+
+ Alguns recursos dependem do conhecimento da orientação da tela para funcionar corretamente. Se isto não foi detectado apropriadamente, defina a orientação da sua tela correspondente ao seu controle, então clique Detectar
+
+
+ Detectar
+
+
+ Não definida
+
+
+ Definição de limite de energia
+
+
+ Opções de ferramentas rápidas
+
+
+ %
+
+
+ Definir o modo de impulso de CPU
+
+
+ Modo de impulso de CPU
+
+
+ Definir o ciclo de funcionamento da ventoinha/cooler fan para o valor definido pelo usuário
+
+
+ Cooler Fan/Ventoinha manual
+
+
+ Ajustar a resolução da tela principal e taxa de atualização
+
+
+ Resolução de tela e taxa de atualização
+
+
+ Superior direito
+
+
+ Superior esquerdo
+
+
+ Localização da janela
+
+
+ Inferior direito
+
+
+ Inferior esquerdo
+
+
+ Opções de energia
+
+
+ Definir localização da janela de ferramentas rápidas
+
+
+ Aplicativos de terceiros
+
+
+ Nenhum
+
+
+ Fundo das ferramentas rápidas: Nenhum, Mica, Abas ou Acrílico
+
+
+ Automaticamente desligar RTSS quando o Companion é encerrado
+
+
+ Padrão
+
+
+ Perfil atual:
+
+
+ RivaTuner Statistics Server
+
+
+ Automaticamente esconder as ferramentas rápidas quando o usuário clica fora da janela
+
+
+ Ocultar quando perder foco
+
+
+ Esta entrada irá operar como um joystick simples. Ideal para notebook ou portáteis no estilo concha, alternada automática de rolagem de guinada baseado em como o dispositivo está sendo segurado (aberto em 90 ou 180 graus).
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Cruz
+
+
+ Círculo
+
+
+ Quadrado
+
+
+ Triângulo
+
+
+ Share
+
+
+ Sony
+
+
+ Options
+
+
+ Controle DualShock 4 emulado
+
+
+ Sem controle emulado
+
+
+ Controle XBOX 360 emulado
+
+
+ Conectado
+
+
+ Desconectado
+
+
+ Alternar Rolagem de Guinada Auto
+
+
+ Câmera de Joystick
+
+
+ Joystick de direção (tipo volante)
+
+
+ Espaço do jogador
+
+
+ Handheld Companion
+
+
+ Sobreposição
+
+
+ Ferramentas rápidas
+
+
+ Windows
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ Menu
+
+
+ Analógico esquerdo
+
+
+ Analógico direito
+
+
+ Este é seu perfil padrão de controle. Este perfil será aplicado a todas as suas aplicações que não possuem um perfil específico. Algumas opções que requerem a definição de um arquivo executável estarão desabilitadas.
+
+
+ Opa. Parece que esse perfil não possui um arquivo executável definido. Como isto será possível?
+
+
+ Opa. Parece que esse perfil não possui um caminho de diretório até a aplicação. Algumas opções que requerem a definição de um arquivo executável estarão desabilitadas.
+
+
+ Opa. Parece que você não possui o nível de permissão necessário para modificar o conteúdo desta aplicação. Certifique-se de iniciar este programa com privilégios administrativos.
+
+
+ Nada para ver aqui.
+
+
+ Opa. Parece que o arquivo executável deste perfil está em execução. Algumas opções estarão indisponíveis até que a execução seja encerrada.
+
+
+ Padrão
+
+
+ Eco
+
+
+ Alta
+
+
+ Automático
+
+
+ Desabilitado
+
+
+ Manual
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ LB
+
+
+ RB
+
+
+ Guia
+
+
+ Menu
+
+
+ Esta entrada irá operar como um joystick simples. Isto é voltado para aplicações que utilizam joystick tradicional
+
+
+ Esta entrada irá operar como um joystick otimizado para controlar um volante ou um jogo de corrida
+
+
+ Esta entrada irá operar como um joystick otimizado para controlar uma câmera em primeira ou terceira pessoa
+
+
+ Handheld Companion
+
+
+ Opções
+
+
+ STEAM
+
+
+ Centro de comando
+
+
+ Armory crate
+
+
+ M1
+
+
+ Win
+
+
+ Esc
+
+
+ KB
+
+
+ Personalizado
+
+
+ Dispositivo
+
+
+ Troca automática Rolamento e Leme
+
+
+ Câmera de Joystick
+
+
+ Direção de Joystick
+
+
+ Espaço do Jogador
+
+
+ Analógico Esquerdo
+
+
+ Analógico Direito
+
+
+ L2
+
+
+ Analógico Esquerdo
+
+
+ R2
+
+
+ Analógico Direito
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ DPad Baixo
+
+
+ DPad Esquerda
+
+
+ DPad Direita
+
+
+ DPad Cima
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ L5
+
+
+ Analógico Esquerdo
+
+
+ Analógico Esquerdo Baixo
+
+
+ Analógico Esquerdo Esquerda
+
+
+ Analógico Esquerdo Direita
+
+
+ Analógico Esquerdo Cima
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Analógico Direito
+
+
+ Analógico Direito Baixo
+
+
+ Analógico Direito Esquerda
+
+
+ Analógico Direito Direita
+
+
+ Analógico Direito Cima
+
+
+ A
+
+
+ Sempre Ligado
+
+
+ B
+
+
+ Back
+
+
+ DPad Baixo
+
+
+ DPad Esquerda
+
+
+ DPad Direita
+
+
+ DPad Cima
+
+
+ Ombro Esquerda
+
+
+ Polegar Esquerda
+
+
+ Gatilho Esquerda
+
+
+ Ombro Direita
+
+
+ Polegar Direita
+
+
+ Gatilho Direita
+
+
+ Start
+
+
+ X
+
+
+ Y
+
+
+ Opa. Este perfil parece estar em execução algumas opções necessitam que o executável esteja encerrado.
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ LeftStick
+
+
+ RightStick
+
+
+ Yes
+
+
+ No
+
+
+ Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
+
+
+ Warning
+
+
+ Disabled
+
+
+ Injection (recommended)
+
+
+ Redirection
+
+
+ Improve virtual controller detection
+
+
+ Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
+
+
+ Yes
+
+
+ No
+
+
+ Your device must be restarted in order for the changes to take effect. Would you like to restart now?
+
+
+ Restart required
+
+
+ Yes
+
+
+ No
+
+
+ Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
+
+
+ Warning
+
+
+ Change the virtual controller layout
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Back
+
+
+ Exit
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ External
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ GPU
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.resx b/HandheldCompanion/Properties/Resources.resx
index 31a81b919..25434cf4c 100644
--- a/HandheldCompanion/Properties/Resources.resx
+++ b/HandheldCompanion/Properties/Resources.resx
@@ -371,7 +371,7 @@
Stationary pitch
- Change the angle, in degree
+ Change the angle
Background Color
@@ -575,7 +575,7 @@
Deadzone
- Change the steering deadzone, in degree. Improves steering straight
+ Change the steering deadzone. Improves steering straight
Joystick game Input
@@ -593,7 +593,7 @@
Max steering angle
- Change the maximum steering angle value, in degree
+ Change the maximum steering angle value
Steering linearity
@@ -683,16 +683,16 @@
Motion control settings
- Change the global motion control settings
+ Change the motion control settings
OK
-
- Power settings
+
+ Power preset
-
- Change the power settings
+
+ Change the selected power preset
Profile details
@@ -770,9 +770,9 @@
Motion activation
- With motion input disabled, hold selected button(s) to enable motion,
-with motion input enabled, hold selected button(s) to disable motion,
-with motion input toggle, press selected button(s) to switch from enabled to disabled and viceversa.
+ Motion input disabled: hold selected button(s) to enable motion.
+Motion input enabled: hold selected button(s) to disable motion.
+Motion input toggle: press selected button(s) to switch motion state.
Select the device that will receive the motion commands
@@ -1518,12 +1518,6 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Automatically hide quick tools when the user clicks outside of window
-
- HWiNFO
-
-
- Automatically turn HWiNFO off when companion is closed
-
Power options
@@ -1708,7 +1702,7 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Right joystick
- This is your default controller profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled.
+ This is your default profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled.
Oops. It seems this profile does not have an executable. How is this even possible?
@@ -1861,7 +1855,7 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
DPad Left
- PPad Right
+ DPad Right
DPad Up
@@ -2442,23 +2436,23 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Manual mode: {0}
-
+
Balances performance, temperature and acoustic for any scenario.
-
- Performance
+
+ ROG Ally - Performance
-
+
Limits CPU and GPU power, but keeps noise levels quiet.
-
- Silent
+
+ ROG Ally - Silent
-
+
Maximizes power to the CPU and GPU for high-performance gaming and work, with maximum airflow from fans.
-
- Turbo
+
+ ROG Ally - Turbo
Settings, display profile
@@ -2485,7 +2479,7 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Profiles
- Preferred actions, device settings
+ Preferred actions
Actions
@@ -2509,13 +2503,13 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Change the fan settings
- Create a new power profile
+ Create a new power preset
- Create power profile
+ Create power preset
- Delete power profile
+ Delete power preset
Toggle
@@ -2601,15 +2595,6 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Try again
-
- LSDaemon is active
-
-
- You should quit LSDaemon, so that the application can run properly and without any errors
-
-
- LSDaemon is already active on your console. This may cause compatibility issues with the application
-
ASUS services are running
@@ -2619,9 +2604,6 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
ASUS services are already running on your device. This may interfere with the application
-
- Quit LSDaemon
-
Disable ASUS services
@@ -2646,15 +2628,6 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
Emulated controller is managed by profile
-
- HWiNFO Shared Memory limit was reached
-
-
- HWiNFO has reached its shared memory time limit and disabled the shared memory support. This may result in missing or outdated sensor readings
-
-
- You should manually re-activate the shared memory time limit in the HWiNFO settings
-
Core isolation features are turned on
@@ -2667,22 +2640,175 @@ with motion input toggle, press selected button(s) to switch from enabled to dis
You might want to turn off core isolation and restart your system to enable TDP manipulations
+
+ Sub Profiles
+
+
+ Add different profiles to the same game
+
+
+ Select a sub profile to apply
+
+
+ Select next sub profile
+
+
+ Apply next sub profile for the current game
+
+
+ Select previous sub profile
+
+
+ Apply previous sub profile for the current game
+
Sets the fan to max speed
Fan max speed override
+
+ Integer scaling is not available
+
+
+ Deploy integer scaling
+
+
+ Integer scaling feature is not installed, therefore you won't be able to enable or disable it
+
+
+ We need to execute some script to deploy the integer scaling on your system
+
+
+ Manage on-screen overlay
+
+
+ Overlay
+
+
+ This is a default device preset and cannot be edited. These are comparable to the presets provided by the devices original software.
+
+
+ Legion Go - Quiet
+
+
+ Preset similar to Quiet Mode in LS. TDP Limit: 8W
+
+
+ Legion Go - Balanced
+
+
+ Preset similar to Balanced Mode in LS. TDP Limit: 15W
+
+
+ Legion Go - Performance
+
+
+ Preset similar to Performance Mode in LS. TDP Limit: 20W
+
+
+ This is the default preset, you cannot modify the fan curve on this preset.
+
- Legion Space Daemon is active
+ Legion Space Tasks and Services are active
- Disable Legion Space Daemon
+ Disable Legion Space
- Legion Space Daemon is already active on your console. This may cause compatibility issues with the application.
+ Legion Space Tasks and Services are already active on your console. This may cause compatibility issues with the application.
- You should disable Legion Space Daemon, so that the application can run properly and without any errors
+ You should disable Legion Space Tasks and Services, so that the application can run properly and without any errors
+
+
+ Use second color
+
+
+ Graphics settings
+
+
+ Change the graphics settings
+
+
+ Preset selection
+
+
+ Select the preset you would like to edit
+
+
+ Device presets
+
+
+ User presets
+
+
+ Power settings
+
+
+ Resolution is currently overridden by profile
+
+
+ Left
+
+
+ Right
+
+
+ On Screen Overlay
+
+
+ Toggle on screen overlay
+
+
+ GPU Scaling
+
+
+ GPU will scale up lower resolutions to fit the display
+
+
+ Radeon Image Sharpening
+
+
+ Enhances visual detail
+
+
+ Integer scaling
+
+
+ Scales up resolution by multiplying each pixel by an integer
+
+
+ Resolution scale
+
+
+ Resolution scale to which integer scaling will apply
+
+
+ Radeon Super Resolution
+
+
+ In-driver-based upscaling feature for faster framerates
+
+
+ Scaling mode
+
+
+ Choose the method used to stretch and position images to fir the display
+
+
+ Center
+
+
+ Full panel
+
+
+ Preserve aspect ratio
+
+
+ Sharpen effect
+
+
+ 1/1 only supports Exclusive Fullscreen.
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.ru-RU.resx b/HandheldCompanion/Properties/Resources.ru-RU.resx
index dcf976ea3..6f04cbd8c 100644
--- a/HandheldCompanion/Properties/Resources.ru-RU.resx
+++ b/HandheldCompanion/Properties/Resources.ru-RU.resx
@@ -1,2341 +1,2335 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- text/microsoft-resx
-
-
- 2.0
-
-
- System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- О программе
-
-
- Набор служб Windows и оптимизированного под сенсорный дисплей интерфейса для расширения возможностей вашего портативного игрового устройства. Включает в себя следующие фукнции: управление движением(гироском), эмуляцию виртуального контроллера, оверлей быстрого доступа, виртуальные сенсорные панели, визуализация контрллера, систему настроек профиля для каждого приложения. Handheld Companion использует драйвер ViGEmBus и библиотеки ViGEmClient, а также драйвер фильтра режима ядра HidHide. Алгоритмы управления движением основаны на работе Jibbsmart и доступной информации на GyroWiki.
-
-
- Акселерометр
-
-
- Автор
-
-
- Разработчики
-
-
- Описание
-
-
- Помочь проекту
-
-
- Гироскоп
-
-
- Датчик наклона
-
-
- Н/Д
-
-
- При поддержке
-
-
- Ссылки
-
-
- Встроенные
-
-
- Внешние
-
-
- Название датчика
-
-
- Спецификации датчиков
-
-
- Служба
-
-
- Исходный код
-
-
- Версия
-
-
- Вики
-
-
- Администратор
-
-
- A,B,X,Y
-
-
- ЗАДНИЕ КНОПКИ
-
-
- БАМПЕРЫ
-
-
- MENU
-
-
- OEM
-
-
- Скрыть контроллер при подключении
-
-
- Скрыть физический контроллер при подключении
-
-
- Подключить
-
-
- Контроллер
-
-
- Маскировка контроллера
-
-
- Настойки контроллера
-
-
- Отключить
-
-
- Устройства ввода
-
-
- Показать контроллер при закрытии
-
-
- Восстановить видимость всех физических контроллеров при выходе из приложения
-
-
- Вибрация при подключении
-
-
- Вибрировать при подключении контроллера
-
-
- Сила вибрации
-
-
- Изменить силу вибрации контрллера
-
-
- КРЕСТОВИНА
-
-
- Уменьшить яркость
-
-
- Уменьшить текущую яркость экрана на 5%
-
-
- Уменьшить лимит энергомотребления (TDP)
-
-
- Уменьшить TDP системы или текущего профиля на 1 ватт
-
-
- Уменьшить громкость
-
-
- Уменьшить громкость на 5%
-
-
- Раскладка рабочего стола
-
-
- Переключить раскладку рабочего стола
-
-
- Нажмите, чтобы задать кнопку
-
-
- Нажмите, чтобы задать кнопку клавиатуры
-
-
- Увеличить яркость
-
-
- Увеличить якрость экрана на 5%
-
-
- Увеличить лимит энергопотребления (TDP)
-
-
- Увеличить TDP системы или текущего профиля на 1 ватт
-
-
- Увеличить громкость
-
-
- Увеличить громкость на 5%
-
-
- Оверлей
-
-
- Включить поддержку оверлея
-
-
- Отобразить оверлей контроллера
-
-
- Change 3D hotkey by pressing a button or a special key
-
-
- Отобразить виртуальные трекпады
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Открыть окно быстрых настроек
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Настройки вентилятора
-
-
- Установите рабочий цикл вентилятора на заданное пользователем значение
-
-
- Показать центр уведомлений
-
-
- Отображение и скрытие Центра уведомлений Windows
-
-
- Назначить хоткей
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Показать или скрыть рабочий стол
-
-
- Путем нажатия: Windows + D
-
-
- Escape
-
-
- Нажать кнопку: Escape
-
-
- Переключение между оконным и полноэкранным режимом
-
-
- Нажать сочетание: Alt + Enter
-
-
- Guide или PS кнопка
-
-
- Эмулировать Xbox Guide или Sony PS кнопки
-
-
- Показать экранную клавиатуру
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Принудитильное закрытие приложение
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Переключить окно
-
-
- Измените горячую клавишу нажатием кнопки или специальной клавиши
-
-
- Открыть инструмент «Ножницы»
-
-
- Нажать сочетание: Windows + Shift + S
-
-
- Открыть диспетчер задач
-
-
- Нажать сочетание: Ctrl + Shift + Esc
-
-
- Открыть режим представление задач
-
-
- Нажать сочетание: Windows + Tab
-
-
- Переключатель паузы
-
-
- Приостановить или возобновить работу текущего приложения
-
-
- ЛЕВЫЙ СТИК
-
-
- КНОПКИ ЛЕВОГО СТИКА
-
-
- ПРАВЫЙ СТИК
-
-
- КНОПКИ ПРАВОГО СТИКА
-
-
- Handheld Companion
-
-
- О программе
-
-
- Контроллер
-
-
- Хоткеи
-
-
- Оверлей
-
-
- Профили
-
-
- ОК
-
-
- Настройки
-
-
- 8BitDo Lite 2
-
-
- Выравнивание
-
-
- Изменить расположение оверлея контроллера
-
-
- Изменение расположение оверлея трекпадов
-
-
- Всегда поверх все окон
-
-
- Когда включено, оверлей контроллера отображается поверх все окон
-
-
- Назад
-
-
- Face camera
-
-
- Change 3D controller overlay model behaviour for facing the camera
-
-
- Stationary pitch
-
-
- Change the angle, in degree
-
-
- Цвет фона
-
-
- Изменить цвет фона наложения оверлея контроллера
-
-
- Оверлей контроллера
-
-
- Playstation DualSense
-
-
- Эмулируемый контроллер
-
-
- Face camera
-
-
- 3D Model slowly rotates to face camera as default position
-
-
- Ожидаю...
-
-
- MACHENIKE HG510
-
-
- Main trigger
-
-
- Change 3D controller overlay main trigger
-
-
- Движение
-
-
- Модель будет двигаться в соответствии с движениями пользователя на основе информации датчиков
-
-
- N64
-
-
- OEM контроллер
-
-
- Прозрачность
-
-
- Изменить непрозрачность оверлея контроллера
-
-
- Изменить непрозрачность оверлея трекпада
-
-
- Оверлей
-
-
- Уровень отображаемых оверлеем данных
-
-
- Изменение уровня отображаемой информации на экране
-
-
- Скорость обновления
-
-
- Изменить скорость обновления данных
-
-
- Вид контроллера
-
-
- Изменить вид оверлея контроллера
-
-
- Предпросмотр оверлея
-
-
- Настройки рендеринга
-
-
- Сглаживание
-
-
- Изменить уровень сглаживания рендеринга
-
-
- Измените настройки рендеринга оверлея контроллера.
-
-
- Скорость обновления
-
-
- Изменить скорость обновления рендеринга, в обновлениях в секунду
-
-
- Размер
-
-
- Изменит размер отображаемой модели контроллера
-
-
- Изменить размер оверлея трекпадов
-
-
- Старт
-
-
- Fisher-Price controller
-
-
- Настройки трекпадов
-
-
- Xbox One
-
-
- ZD O+
-
-
- Оверлей
-
-
- Продолжить
-
-
- Приостановить
-
-
- Множитель акселерометра
-
-
- Изменяет значение получаемых от акселерометра данных
-
-
- Дополнительные настройки
-
-
- Уменьшение мертвых зон
-
-
- Изменить внутриигровую мёртвую зону, в процентах
-
-
- %
-
-
- Вы уверены что хотите удалить?
-
-
- Этот элемент будет немедленно удален. Это действие нельзя отменить.
-
-
- Вы уверены что хотите переписать профиль?
-
-
- {0} будет перезаписан. Это действие нельзя отменить.
-
-
- Автоматический TDP
-
-
- Автоматическая подстойка TDP на основе текущего FPS и целевого FPS
-
-
- Целевая частота кадров
-
-
- Желаемая частота кадров для автоматического контроля TDP
-
-
- Лимит энергопотребления турбо
-
-
- Изменить лимит энергопотребления для турбо режима
-
-
- Отмена
-
-
- Раскладка контроллера
-
-
- Настройки контроллера
-
-
- Изменить настройки виртуального контроллера
-
-
- Создать новый профиль
-
-
- Удалить
-
-
- Удалить профиль
-
-
- Пользовательские профили для игры
-
-
- Профиль будет применен автоматически при обнаружении указанного приложения
-
-
- Лимит частоты кадров
-
-
- Ограничивает частоту кадров для 3D приложений
-
-
- Глобальные настройки
-
-
- Изменить глобальные настройки профилей
-
-
- Максимальная частота GPU
-
-
- Максимальная частота GPU В МГц
-
-
- Множитель гироскопа
-
-
- Изменяет значение получаемых от гироскопа данных
-
-
- Ось гироскопа
-
-
- Для управления горизонтальным перемещением контроллера вы можете использовать либо вертикальную ось, либо горизонтпльную.
-
-
- Инвертировать горизонтальную ось
-
-
- Инвертировать вертикальную ось
-
-
- % Остаточной мертвый зоны левого стика
-
-
- Регулировка процента внутренней и внешней мертвой зоны левого стика
-
-
- % Остаточной мертвый зоны правого стика
-
-
- Регулировка процента внутренней и внешней мертвой зоны правого стика
-
-
- Настройки управления движением
-
-
- Изменить глобальные настройки управления движением
-
-
- ОК
-
-
- Настройки электропитания
-
-
- Изменить параметры питания
-
-
- Информация о профиле
-
-
- Имя профиля
-
-
- Путь профиля
-
-
- Профили
-
-
- Выбор профиля
-
-
- Выберите профиль, который хотите изменить
-
-
- Настройки профиля
-
-
- Профиль обновлен
-
-
- обновлен.
-
-
- Горизонтальная
-
-
- X
-
-
- Y
-
-
- Тип ввода
-
-
- Физические входы контроллера можно запрограммировать, чтобы они действовали как различные типы устройств.
-
-
- Устройство вывода
-
-
- Выберите устройство, которое будет получать команды движения
-
-
- Постоянный лимит энергопотребления
-
-
- Изменяет установенный лимит энергопотребления
-
-
- Лимит энергопотребления(TDP)
-
-
- Ограничивает мощность процессора для уменьшения общей мощности
-
-
- Improve the stick circularity
-
-
- Circularity stick left
-
-
- Circularity stick right
-
-
- Мертвая зона левого триггера %
-
-
- Настройка внутренней и внешней мертвой зоны левого триггера
-
-
- Мертвая зона правого триггера %
-
-
- Настройка внутренней и внешней мертвой зоны правого триггера
-
-
- Защита от мертвой зоны
-
-
- Компенсирует внутриигровую мертвую зону, улучшает регистрацию небольших движений
-
-
- Включить универсальный контроллер движения
-
-
- Выключено, включение по кнопке
-
-
- Включено, отключение по кнопке
-
-
- Активация управления движением
-
-
- При отключенном управлении движением используйте выбранные кнопки для включения,
-при включенном используйте выбранные кнопки для отключения.
-
-
- Выберите устройство, которое будет получать команды управления движением
-
-
- Универсальные настройки управления движением
-
-
- Преобразовывать движения устройтва в ввод с контроллера
-
-
- Обновить профил
-
-
- Разрешить приложению доступ к физическому контроллеру устройства
-
-
- Расширенная совместимость (XInputPlus)
-
-
- Вертикальная
-
-
- Да
-
-
- Отключить
-
-
- FPS
-
-
- Ручной контроль частоты GPU
-
-
- Устанавливает фиксированную частоту GPU
-
-
- ГГц
-
-
- Режим энергопотребления
-
-
- Баланс
-
-
- Оптимизизация на основе энергопотребления и производительности
-
-
- Экономия
-
-
- Производительный
-
-
- Турбо
-
-
- Лимит энергопотребления (TDP)
-
-
- Ограничивает мощность процессора для уменьшения общего энергомотребления
-
-
- TDP переназначен профилем
-
-
- Постоянный
-
-
- Вт
-
-
- Созданить профиль
-
-
- Ожидание завершения фоновых процессов...
-
-
- Обеспечивает поддержку гироскопа и акселерометра для Windows через эмуляцию контроллера. Если служба включена, встроенный контроллер будет скрыт от приложений, не входящих в белый список. Если служба отключена, встроенный контроллер будет включен, а виртуальный контроллер отключен.
-
-
- Служба игрового контроллера
-
-
- Дополнительные настройки
-
-
- Aiming down sights motion multiplier
-
-
- Кнопка включения
-
-
- An additional motion sensitivity multiplier when aiming down sights or scope through the use of the configured activation button
-
-
- Значение множителя
-
-
- Camera options
-
-
- Custom response curve
-
-
- Output sent to game
-
-
- Movement intensity
-
-
- Agressive
-
-
- Default
-
-
- Preset options
-
-
- Precise
-
-
- Flick duration
-
-
- Change the flick duration, calibrate to 180 degree turn, in milliseconds
-
-
- Flick stick (experimental)
-
-
- Point camera in direction of (right) joystick flick, rotate camera purely in horizontal plane by rotating
-
-
- Enable flick stick
-
-
- Sensitivity
-
-
- Change the motion sensitivity of the horizontal and vertical axis
-
-
- Sensitivity X
-
-
- Change the motion sensitivity of the horizontal axis
-
-
- Sensitivity Y
-
-
- Change the motion sensitivity of the vertical axis
-
-
- Чувствительность стика
-
-
- Change the rotation rate
-
-
- Дополнительные настройки
-
-
- Мертвая зона
-
-
- Change the steering deadzone, in degree. Improves steering straight
-
-
- Joystick game Input
-
-
- Joystick steering
-
-
- Joystick steering options
-
-
- Joystick steering preview
-
-
- Max steering angle
-
-
- Change the maximum steering angle value, in degree
-
-
- Steering linearity
-
-
- Mapping between input and steering. Lower values provide more accuracy near full lock but less accuracy near the center. Higher values provide more accuracy near the center but less accuracy near full lock. 1.0 is a linear mapping
-
-
- Язык
-
-
- Язык приложения
-
-
- Требуется перезапуск
-
-
- Чтобы изменения вступили в силу, перезапустите приложение
-
-
- Тема
-
-
- Тема приложения, светлая или темная
-
-
- Автозапуск
-
-
- Приложение будет запускаться автоматически при входе в Windows.
-
-
- Фон
-
-
- Акрил
-
-
- Фон приложения, пусто, матовый, tabbed, акрил
-
-
- Матовый
-
-
- Пусто
-
-
- Tabbed
-
-
- Проверить обновления
-
-
- Сворачивать при закрытии
-
-
- Приложение будет свернуто в трей вместо закрытия
-
-
- Загрузка
-
-
- Загрузка -
-
-
- Умное энергопотребление
-
-
- Режим умного энергопотребления снижает приоритет фоновых процессов и повышает энергоэффективность
-
-
- Включить профиль рабочего стола при запуске
-
-
- Профиль рабочего стола будет автоматически включен при запуске приложения.
-
-
- Общие настройки
-
-
- Установить сейчас
-
-
- Последняя проверка:
-
-
- Настройки уведомлений
-
-
- Открыть приложение в фоновом режиме
-
-
- По-умолчанию приложение запустится в свернутом виде и появится на панели задач.
-
-
- Встроенны
-
-
- Внешний
-
-
- Настройки датчиков
-
-
- Направление размещения внешнего датчика
-
-
- Выберите, на какой стороне устройства был установлен датчик
-
-
- Внешний датчик перевернут
-
-
- Датчик был установлен вверх ногами, возможно через USB-C переходник.
-
-
- Выбор датчика
-
-
- Выберите нужный датчик, используемый для управление движением
-
-
- Настройки
-
-
- Тип запуска
-
-
- Используется диспетчером служб для определения типа запуска службы.
-
-
- Максимальное энергопотребление
-
-
- Максимальная мощность в ваттах для процессора
-
-
- Минимальное энергопотребление
-
-
- Минимальная мощность в ваттах для процессора
-
-
- Переопределение настраиваемой мощности (cTDP)
-
-
- Позволяет изменять минимальные и максимальные значения мощности (TDP) вне зависимости от спецификаций ЦП.
-
-
- Темная
-
-
- Использовать системное значение
-
-
- Светлая
-
-
- Всплывающие уведомления
-
-
- Получать уведомления от приложения в центре уведомлений Windows
-
-
- Доступны обновления
-
-
- Проверка обновлений...
-
-
- Не удалось скачать файл обновления.
-
-
- Не удалось подключиться к github.
-
-
- Не удалось найти файл обновления.
-
-
- Упс. Произошла ошибка
-
-
- У вас последняя версия
-
-
- Контроллер теперь скрыт, а входные данные перенаправляются на виртуальный контроллер
-
-
- ЛЕВЫЙ ТРЕКПАД
-
-
- ФУНКЦИИ ЛЕВЫЙ ТРЕКПАД
-
-
- ПРАВЫЙ ТРЕКПАД
-
-
- ФУНКЦИИ ПРАВЫЙТРЕКПАД
-
-
- ЛЕВЫЙ ТРИГГЕР
-
-
- ФУНКЦИИ ЛЕВЫЙ ТРИГГЕР
-
-
- ПРАВЫЙ ТРИГГЕР
-
-
- ФУНКЦИИ ПРАВЫЙ ТРИГГЕР
-
-
- Пользователь
-
-
- Запустите от имени администратора чтобы разблокировать эти настройки
-
-
- Connect
-
-
- Disconnect
-
-
- Hide
-
-
- Unhide
-
-
- Virtual
-
-
- Manufacturer
-
-
- Product name
-
-
- This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
-
-
- Desktop layout
-
-
- Define desktop layout
-
-
- Define controller layout when in desktop mode
-
-
- Edit
-
-
- Enable desktop layout
-
-
- Non-game controller layouts
-
-
- You might want to click on Connect next to your plugged controller.
-
-
- You have no physical controller connected. No inputs will be sent to HC or its service.
-
-
- Please make sure you connected a compatible XInput or DInput device.
-
-
- No physical controller detected
-
-
- No physical controller connected
-
-
- You might want to start companion service or make sure your virtual controller status is set to: Connected
-
-
- Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
-
-
- No virtual controller detected
-
-
- You might want to unmute your virtual controller or unhide your physical controller.
-
-
- Your physical controller is hidden, yet you have muted your virtual controller.
-
-
- Physical controller is hidden
-
-
- You might want to hide your physical controller or mute your virtual controller.
-
-
- Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
-
-
- Physical controller is not hidden
-
-
- HD rumble
-
-
- Use high-definition rumble engine, at the cost of higher CPU usage
-
-
- Приостановить виртуальные контроллер
-
-
- Временно отключает виртуальный контрллер в Steam приложених
-
-
- Настройки контроллера
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Win
-
-
- Esc
-
-
- KB
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- AYA
-
-
- ≈
-
-
- RC
-
-
- LC
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- Single-touch swipe
-
-
- Multi-touch swipe
-
-
- Cross
-
-
- Circle
-
-
- Square
-
-
- Triangle
-
-
- Share
-
-
- Single-touch click
-
-
- Single-touch tap
-
-
- Multi-touch click
-
-
- Multi-touch tap
-
-
- Sony
-
-
- Options
-
-
- A
-
-
- Always On
-
-
- B
-
-
- Back
-
-
- DPad Down
-
-
- DPad Left
-
-
- DPad Right
-
-
- DPad Up
-
-
- Left Shoulder
-
-
- Left Thumb
-
-
- Left Trigger
-
-
- Right Shoulder
-
-
- Right Thumb
-
-
- Right Trigger
-
-
- Start
-
-
- X
-
-
- Y
-
-
- Emulated DualShock 4 controller
-
-
- No emulated controller
-
-
- Emulated XBOX 360 controller
-
-
- Connected
-
-
- Disconnected
-
-
- Auto Roll Yaw Swap
-
-
- Joystick camera
-
-
- Joystick steering
-
-
- Player space
-
-
- Custom
-
-
- Device
-
-
- Handheld Companion
-
-
- Handheld Companion
-
-
- Overlay
-
-
- Quick tools
-
-
- Windows
-
-
- A
-
-
- Alt
-
-
- Apostrophe
-
-
- B
-
-
- Backslash
-
-
- Backspace
-
-
- C
-
-
- Comma
-
-
- Control
-
-
- D
-
-
- Delete
-
-
- E
-
-
- End
-
-
- Enter
-
-
- Equal
-
-
- Escape
-
-
- F
-
-
- F1
-
-
- F10
-
-
- F11
-
-
- F12
-
-
- F2
-
-
- F3
-
-
- F4
-
-
- F5
-
-
- F6
-
-
- F7
-
-
- F8
-
-
- F9
-
-
- G
-
-
- Grave
-
-
- H
-
-
- Home
-
-
- I
-
-
- Insert
-
-
- J
-
-
- K
-
-
- L
-
-
- M
-
-
- Minus
-
-
- N
-
-
- O
-
-
- P
-
-
- Pause
-
-
- Period
-
-
- Q
-
-
- R
-
-
- S
-
-
- Semicolon
-
-
- Shift
-
-
- Slash
-
-
- Space
-
-
- T
-
-
- Tab
-
-
- U
-
-
- V
-
-
- W
-
-
- X
-
-
- Y
-
-
- Z
-
-
- Auto Roll Yaw Swap
-
-
- Joystick Camera
-
-
- Joystick Steering
-
-
- Player Space
-
-
- LeftStick
-
-
- MoveCursor
-
-
- RightStick
-
-
- ScrollWheel
-
-
- Left Stick
-
-
- Right Stick
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- View
-
-
- STEAM
-
-
- Menu
-
-
- Left joystick
-
-
- Right joystick
-
-
- ZL
-
-
- ZR
-
-
- B
-
-
- A
-
-
- Y
-
-
- X
-
-
- Minus
-
-
- L
-
-
- R
-
-
- Home
-
-
- Capture
-
-
- Plus
-
-
- This is your default controller profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled.
-
-
- Oops. This profile seems to be running. Some options requiring an executable may be disabled.
-
-
- Oops. It seems this profile does not have an executable. How is this even possible?
-
-
- Oops. It seems this profile does not have a path to the application. Some options requiring an executable might be disabled.
-
-
- Oops. It seems you do not have the necessary permission level to modify the content of this application. Make sure you have started this program in administrator mode.
-
-
- Nothing to see here.
-
-
- Oops. It seems this profile excutable is running. Some options requiring an executable might be disabled.
-
-
- Default
-
-
- Eco
-
-
- High
-
-
- Command center
-
-
- Armory crate
-
-
- M1
-
-
- Automatic
-
-
- Disabled
-
-
- Manual
-
-
- Options
-
-
- L2
-
-
- LeftStick
-
-
- Left Thumb
-
-
- R2
-
-
- Right Thumb
-
-
- A
-
-
- B
-
-
- X
-
-
- Y
-
-
- B5
-
-
- B6
-
-
- B7
-
-
- B8
-
-
- View
-
-
- DPad Down
-
-
- DPad Left
-
-
- PPad Right
-
-
- DPad Up
-
-
- LB
-
-
- L2
-
-
- L3
-
-
- L4
-
-
- AYA
-
-
- RightStick
-
-
- L5
-
-
- Left Thumb
-
-
- Left Thumb Down
-
-
- Left Thumb Left
-
-
- Left Thumb Right
-
-
- Left Thumb Up
-
-
- OEM1
-
-
- OEM2
-
-
- OEM3
-
-
- RB
-
-
- R2
-
-
- R3
-
-
- R4
-
-
- R5
-
-
- Right Thumb
-
-
- Right Thumb Down
-
-
- Right Thumb Left
-
-
- Right Thumb Right
-
-
- Right Thumb Up
-
-
- Guide
-
-
- Menu
-
-
- This input will operate as a joystick optimized for controlling a steering wheel or a racing game
-
-
- Apply template
-
-
- Buttons
-
-
- Cancel
-
-
- COMMUNITY
-
-
- Confirm
-
-
- Dpad
-
-
- Export for current controller
-
-
- Export layout
-
-
- Gyro
-
-
- Joysticks
-
-
- Layout author
-
-
- Layout description
-
-
- Layout title
-
-
- Save game information with the layout
-
-
- Show current controller templates only
-
-
- Layout template picker
-
-
- TEMPLATES
-
-
- Trackpads
-
-
- Triggers
-
-
- This input will operate as a simple joystick. This is intended for traditional joystick applications
-
-
- Back
-
-
- Exit
-
-
- Main Window
-
-
- Navigate
-
-
- Quick Tools
-
-
- Select
-
-
- Yes
-
-
- No
-
-
- Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
-
-
- Warning
-
-
- ms
-
-
- Disabled
-
-
- Extended
-
-
- External
-
-
- Full
-
-
- Minimal
-
-
- This input will operate as a joystick optimized for controlling a first or third person camera
-
-
- Are you sure you want to apply this template? All layout settings will be overridden.
-
-
- You can't undo this action. Previously applied template: {0}
-
-
- Change the virtual controller layout
-
-
- CPU
-
-
- Energy performance preference (EPP)
-
-
- CPU/GPU power balance
-
-
- Specifies power distribution policy between CPU and GPU
-
-
- GPU
-
-
- Power limit target
-
-
- Disabled
-
-
- Injection (recommended)
-
-
- Redirection
-
-
- CPU boost mode
-
-
- Set current CPU boost mode
-
-
- Display resolution and refresh rate
-
-
- Adjust main display resolution and refresh rate
-
-
- Fan override
-
-
- Set the fan duty cycle to user-defined value
-
-
- %
-
-
- Current profile:
-
-
- Default
-
-
- Power limit target
-
-
- Improve virtual controller detection
-
-
- Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
-
-
- Yes
-
-
- No
-
-
- Your device must be restarted in order for the changes to take effect. Would you like to restart now?
-
-
- Restart required
-
-
- Hide when loses focus
-
-
- Automatically hide quick tools when the user clicks outside of window
-
-
- HWiNFO
-
-
- Automatically turn HWiNFO off when companion is closed
-
-
- Native display orientation
-
-
- Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
-
-
- Detect
-
-
- Not set
-
-
- Power options
-
-
- Quicktools backdrop, none, mica, tabbed, acrylic
-
-
- Quicktools options
-
-
- Window location
-
-
- Bottom left
-
-
- Bottom right
-
-
- Define quicktools window location
-
-
- Top left
-
-
- Top right
-
-
- RivaTuner Statistics Server
-
-
- Automatically turn RTSS off when companion is closed
-
-
- None
-
-
- Third-party applications
-
-
- Yes
-
-
- No
-
-
- Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
-
-
- Warning
-
-
- M2
-
-
- Mouse wheel click
-
-
- Mouse wheel up
-
-
- Mouse wheel down
-
-
- Y1
-
-
- Y2
-
-
- M3
-
-
- Y3
-
-
- LegionR
-
-
- LegionL
-
-
- M2
-
-
- Gamepad: {0}
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ О программе
+
+
+ Набор служб Windows и оптимизированного под сенсорный дисплей интерфейса для расширения возможностей вашего портативного игрового устройства. Включает в себя следующие фукнции: управление движением(гироском), эмуляцию виртуального контроллера, оверлей быстрого доступа, виртуальные сенсорные панели, визуализация контрллера, систему настроек профиля для каждого приложения. Handheld Companion использует драйвер ViGEmBus и библиотеки ViGEmClient, а также драйвер фильтра режима ядра HidHide. Алгоритмы управления движением основаны на работе Jibbsmart и доступной информации на GyroWiki.
+
+
+ Акселерометр
+
+
+ Автор
+
+
+ Разработчики
+
+
+ Описание
+
+
+ Помочь проекту
+
+
+ Гироскоп
+
+
+ Датчик наклона
+
+
+ Н/Д
+
+
+ При поддержке
+
+
+ Ссылки
+
+
+ Встроенные
+
+
+ Внешние
+
+
+ Название датчика
+
+
+ Спецификации датчиков
+
+
+ Служба
+
+
+ Исходный код
+
+
+ Версия
+
+
+ Вики
+
+
+ Администратор
+
+
+ A,B,X,Y
+
+
+ ЗАДНИЕ КНОПКИ
+
+
+ БАМПЕРЫ
+
+
+ MENU
+
+
+ OEM
+
+
+ Скрыть контроллер при подключении
+
+
+ Скрыть физический контроллер при подключении
+
+
+ Подключить
+
+
+ Контроллер
+
+
+ Маскировка контроллера
+
+
+ Настойки контроллера
+
+
+ Отключить
+
+
+ Устройства ввода
+
+
+ Показать контроллер при закрытии
+
+
+ Восстановить видимость всех физических контроллеров при выходе из приложения
+
+
+ Вибрация при подключении
+
+
+ Вибрировать при подключении контроллера
+
+
+ Сила вибрации
+
+
+ Изменить силу вибрации контрллера
+
+
+ КРЕСТОВИНА
+
+
+ Уменьшить яркость
+
+
+ Уменьшить текущую яркость экрана на 5%
+
+
+ Уменьшить лимит энергомотребления (TDP)
+
+
+ Уменьшить TDP системы или текущего профиля на 1 ватт
+
+
+ Уменьшить громкость
+
+
+ Уменьшить громкость на 5%
+
+
+ Раскладка рабочего стола
+
+
+ Переключить раскладку рабочего стола
+
+
+ Нажмите, чтобы задать кнопку
+
+
+ Нажмите, чтобы задать кнопку клавиатуры
+
+
+ Увеличить яркость
+
+
+ Увеличить якрость экрана на 5%
+
+
+ Увеличить лимит энергопотребления (TDP)
+
+
+ Увеличить TDP системы или текущего профиля на 1 ватт
+
+
+ Увеличить громкость
+
+
+ Увеличить громкость на 5%
+
+
+ Оверлей
+
+
+ Включить поддержку оверлея
+
+
+ Отобразить оверлей контроллера
+
+
+ Change 3D hotkey by pressing a button or a special key
+
+
+ Отобразить виртуальные трекпады
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Открыть окно быстрых настроек
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Настройки вентилятора
+
+
+ Установите рабочий цикл вентилятора на заданное пользователем значение
+
+
+ Показать центр уведомлений
+
+
+ Отображение и скрытие Центра уведомлений Windows
+
+
+ Назначить хоткей
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Показать или скрыть рабочий стол
+
+
+ Путем нажатия: Windows + D
+
+
+ Escape
+
+
+ Нажать кнопку: Escape
+
+
+ Переключение между оконным и полноэкранным режимом
+
+
+ Нажать сочетание: Alt + Enter
+
+
+ Guide или PS кнопка
+
+
+ Эмулировать Xbox Guide или Sony PS кнопки
+
+
+ Показать экранную клавиатуру
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Принудитильное закрытие приложение
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Переключить окно
+
+
+ Измените горячую клавишу нажатием кнопки или специальной клавиши
+
+
+ Открыть инструмент «Ножницы»
+
+
+ Нажать сочетание: Windows + Shift + S
+
+
+ Открыть диспетчер задач
+
+
+ Нажать сочетание: Ctrl + Shift + Esc
+
+
+ Открыть режим представление задач
+
+
+ Нажать сочетание: Windows + Tab
+
+
+ Переключатель паузы
+
+
+ Приостановить или возобновить работу текущего приложения
+
+
+ ЛЕВЫЙ СТИК
+
+
+ КНОПКИ ЛЕВОГО СТИКА
+
+
+ ПРАВЫЙ СТИК
+
+
+ КНОПКИ ПРАВОГО СТИКА
+
+
+ Handheld Companion
+
+
+ О программе
+
+
+ Контроллер
+
+
+ Хоткеи
+
+
+ Оверлей
+
+
+ Профили
+
+
+ ОК
+
+
+ Настройки
+
+
+ 8BitDo Lite 2
+
+
+ Выравнивание
+
+
+ Изменить расположение оверлея контроллера
+
+
+ Изменение расположение оверлея трекпадов
+
+
+ Всегда поверх все окон
+
+
+ Когда включено, оверлей контроллера отображается поверх все окон
+
+
+ Назад
+
+
+ Face camera
+
+
+ Change 3D controller overlay model behaviour for facing the camera
+
+
+ Stationary pitch
+
+
+ Change the angle
+
+
+ Цвет фона
+
+
+ Изменить цвет фона наложения оверлея контроллера
+
+
+ Оверлей контроллера
+
+
+ Playstation DualSense
+
+
+ Эмулируемый контроллер
+
+
+ Face camera
+
+
+ 3D Model slowly rotates to face camera as default position
+
+
+ Ожидаю...
+
+
+ MACHENIKE HG510
+
+
+ Main trigger
+
+
+ Change 3D controller overlay main trigger
+
+
+ Движение
+
+
+ Модель будет двигаться в соответствии с движениями пользователя на основе информации датчиков
+
+
+ N64
+
+
+ OEM контроллер
+
+
+ Прозрачность
+
+
+ Изменить непрозрачность оверлея контроллера
+
+
+ Изменить непрозрачность оверлея трекпада
+
+
+ Оверлей
+
+
+ Уровень отображаемых оверлеем данных
+
+
+ Изменение уровня отображаемой информации на экране
+
+
+ Скорость обновления
+
+
+ Изменить скорость обновления данных
+
+
+ Вид контроллера
+
+
+ Изменить вид оверлея контроллера
+
+
+ Предпросмотр оверлея
+
+
+ Настройки рендеринга
+
+
+ Сглаживание
+
+
+ Изменить уровень сглаживания рендеринга
+
+
+ Измените настройки рендеринга оверлея контроллера.
+
+
+ Скорость обновления
+
+
+ Изменить скорость обновления рендеринга, в обновлениях в секунду
+
+
+ Размер
+
+
+ Изменит размер отображаемой модели контроллера
+
+
+ Изменить размер оверлея трекпадов
+
+
+ Старт
+
+
+ Fisher-Price controller
+
+
+ Настройки трекпадов
+
+
+ Xbox One
+
+
+ ZD O+
+
+
+ Оверлей
+
+
+ Продолжить
+
+
+ Приостановить
+
+
+ Множитель акселерометра
+
+
+ Изменяет значение получаемых от акселерометра данных
+
+
+ Дополнительные настройки
+
+
+ Уменьшение мертвых зон
+
+
+ Изменить внутриигровую мёртвую зону, в процентах
+
+
+ %
+
+
+ Вы уверены что хотите удалить?
+
+
+ Этот элемент будет немедленно удален. Это действие нельзя отменить.
+
+
+ Вы уверены что хотите переписать профиль?
+
+
+ {0} будет перезаписан. Это действие нельзя отменить.
+
+
+ Автоматический TDP
+
+
+ Автоматическая подстойка TDP на основе текущего FPS и целевого FPS
+
+
+ Целевая частота кадров
+
+
+ Желаемая частота кадров для автоматического контроля TDP
+
+
+ Лимит энергопотребления турбо
+
+
+ Изменить лимит энергопотребления для турбо режима
+
+
+ Отмена
+
+
+ Раскладка контроллера
+
+
+ Настройки контроллера
+
+
+ Изменить настройки виртуального контроллера
+
+
+ Создать новый профиль
+
+
+ Удалить
+
+
+ Удалить профиль
+
+
+ Пользовательские профили для игры
+
+
+ Профиль будет применен автоматически при обнаружении указанного приложения
+
+
+ Лимит частоты кадров
+
+
+ Ограничивает частоту кадров для 3D приложений
+
+
+ Глобальные настройки
+
+
+ Изменить глобальные настройки профилей
+
+
+ Максимальная частота GPU
+
+
+ Максимальная частота GPU В МГц
+
+
+ Множитель гироскопа
+
+
+ Изменяет значение получаемых от гироскопа данных
+
+
+ Ось гироскопа
+
+
+ Для управления горизонтальным перемещением контроллера вы можете использовать либо вертикальную ось, либо горизонтпльную.
+
+
+ Инвертировать горизонтальную ось
+
+
+ Инвертировать вертикальную ось
+
+
+ % Остаточной мертвый зоны левого стика
+
+
+ Регулировка процента внутренней и внешней мертвой зоны левого стика
+
+
+ % Остаточной мертвый зоны правого стика
+
+
+ Регулировка процента внутренней и внешней мертвой зоны правого стика
+
+
+ Настройки управления движением
+
+
+ Изменить глобальные настройки управления движением
+
+
+ ОК
+
+
+ Настройки электропитания
+
+
+ Изменить параметры питания
+
+
+ Информация о профиле
+
+
+ Имя профиля
+
+
+ Путь профиля
+
+
+ Профили
+
+
+ Выбор профиля
+
+
+ Выберите профиль, который хотите изменить
+
+
+ Настройки профиля
+
+
+ Профиль обновлен
+
+
+ обновлен.
+
+
+ Горизонтальная
+
+
+ X
+
+
+ Y
+
+
+ Тип ввода
+
+
+ Физические входы контроллера можно запрограммировать, чтобы они действовали как различные типы устройств.
+
+
+ Устройство вывода
+
+
+ Выберите устройство, которое будет получать команды движения
+
+
+ Постоянный лимит энергопотребления
+
+
+ Изменяет установенный лимит энергопотребления
+
+
+ Лимит энергопотребления(TDP)
+
+
+ Ограничивает мощность процессора для уменьшения общей мощности
+
+
+ Improve the stick circularity
+
+
+ Circularity stick left
+
+
+ Circularity stick right
+
+
+ Мертвая зона левого триггера %
+
+
+ Настройка внутренней и внешней мертвой зоны левого триггера
+
+
+ Мертвая зона правого триггера %
+
+
+ Настройка внутренней и внешней мертвой зоны правого триггера
+
+
+ Защита от мертвой зоны
+
+
+ Компенсирует внутриигровую мертвую зону, улучшает регистрацию небольших движений
+
+
+ Включить универсальный контроллер движения
+
+
+ Выключено, включение по кнопке
+
+
+ Включено, отключение по кнопке
+
+
+ Активация управления движением
+
+
+ При отключенном управлении движением используйте выбранные кнопки для включения,
+при включенном используйте выбранные кнопки для отключения.
+
+
+ Выберите устройство, которое будет получать команды управления движением
+
+
+ Универсальные настройки управления движением
+
+
+ Преобразовывать движения устройтва в ввод с контроллера
+
+
+ Обновить профил
+
+
+ Разрешить приложению доступ к физическому контроллеру устройства
+
+
+ Расширенная совместимость (XInputPlus)
+
+
+ Вертикальная
+
+
+ Да
+
+
+ Отключить
+
+
+ FPS
+
+
+ Ручной контроль частоты GPU
+
+
+ Устанавливает фиксированную частоту GPU
+
+
+ ГГц
+
+
+ Режим энергопотребления
+
+
+ Баланс
+
+
+ Оптимизизация на основе энергопотребления и производительности
+
+
+ Экономия
+
+
+ Производительный
+
+
+ Турбо
+
+
+ Лимит энергопотребления (TDP)
+
+
+ Ограничивает мощность процессора для уменьшения общего энергомотребления
+
+
+ TDP переназначен профилем
+
+
+ Постоянный
+
+
+ Вт
+
+
+ Созданить профиль
+
+
+ Ожидание завершения фоновых процессов...
+
+
+ Обеспечивает поддержку гироскопа и акселерометра для Windows через эмуляцию контроллера. Если служба включена, встроенный контроллер будет скрыт от приложений, не входящих в белый список. Если служба отключена, встроенный контроллер будет включен, а виртуальный контроллер отключен.
+
+
+ Служба игрового контроллера
+
+
+ Дополнительные настройки
+
+
+ Aiming down sights motion multiplier
+
+
+ Кнопка включения
+
+
+ An additional motion sensitivity multiplier when aiming down sights or scope through the use of the configured activation button
+
+
+ Значение множителя
+
+
+ Camera options
+
+
+ Custom response curve
+
+
+ Output sent to game
+
+
+ Movement intensity
+
+
+ Agressive
+
+
+ Default
+
+
+ Preset options
+
+
+ Precise
+
+
+ Flick duration
+
+
+ Change the flick duration, calibrate to 180 degree turn, in milliseconds
+
+
+ Flick stick (experimental)
+
+
+ Point camera in direction of (right) joystick flick, rotate camera purely in horizontal plane by rotating
+
+
+ Enable flick stick
+
+
+ Sensitivity
+
+
+ Change the motion sensitivity of the horizontal and vertical axis
+
+
+ Sensitivity X
+
+
+ Change the motion sensitivity of the horizontal axis
+
+
+ Sensitivity Y
+
+
+ Change the motion sensitivity of the vertical axis
+
+
+ Чувствительность стика
+
+
+ Change the rotation rate
+
+
+ Дополнительные настройки
+
+
+ Мертвая зона
+
+
+ Change the steering deadzone. Improves steering straight
+
+
+ Joystick game Input
+
+
+ Joystick steering
+
+
+ Joystick steering options
+
+
+ Joystick steering preview
+
+
+ Max steering angle
+
+
+ Change the maximum steering angle value
+
+
+ Steering linearity
+
+
+ Mapping between input and steering. Lower values provide more accuracy near full lock but less accuracy near the center. Higher values provide more accuracy near the center but less accuracy near full lock. 1.0 is a linear mapping
+
+
+ Язык
+
+
+ Язык приложения
+
+
+ Требуется перезапуск
+
+
+ Чтобы изменения вступили в силу, перезапустите приложение
+
+
+ Тема
+
+
+ Тема приложения, светлая или темная
+
+
+ Автозапуск
+
+
+ Приложение будет запускаться автоматически при входе в Windows.
+
+
+ Фон
+
+
+ Акрил
+
+
+ Фон приложения, пусто, матовый, tabbed, акрил
+
+
+ Матовый
+
+
+ Пусто
+
+
+ Tabbed
+
+
+ Проверить обновления
+
+
+ Сворачивать при закрытии
+
+
+ Приложение будет свернуто в трей вместо закрытия
+
+
+ Загрузка
+
+
+ Загрузка -
+
+
+ Умное энергопотребление
+
+
+ Режим умного энергопотребления снижает приоритет фоновых процессов и повышает энергоэффективность
+
+
+ Включить профиль рабочего стола при запуске
+
+
+ Профиль рабочего стола будет автоматически включен при запуске приложения.
+
+
+ Общие настройки
+
+
+ Установить сейчас
+
+
+ Последняя проверка:
+
+
+ Настройки уведомлений
+
+
+ Открыть приложение в фоновом режиме
+
+
+ По-умолчанию приложение запустится в свернутом виде и появится на панели задач.
+
+
+ Встроенны
+
+
+ Внешний
+
+
+ Настройки датчиков
+
+
+ Направление размещения внешнего датчика
+
+
+ Выберите, на какой стороне устройства был установлен датчик
+
+
+ Внешний датчик перевернут
+
+
+ Датчик был установлен вверх ногами, возможно через USB-C переходник.
+
+
+ Выбор датчика
+
+
+ Выберите нужный датчик, используемый для управление движением
+
+
+ Настройки
+
+
+ Тип запуска
+
+
+ Используется диспетчером служб для определения типа запуска службы.
+
+
+ Максимальное энергопотребление
+
+
+ Максимальная мощность в ваттах для процессора
+
+
+ Минимальное энергопотребление
+
+
+ Минимальная мощность в ваттах для процессора
+
+
+ Переопределение настраиваемой мощности (cTDP)
+
+
+ Позволяет изменять минимальные и максимальные значения мощности (TDP) вне зависимости от спецификаций ЦП.
+
+
+ Темная
+
+
+ Использовать системное значение
+
+
+ Светлая
+
+
+ Всплывающие уведомления
+
+
+ Получать уведомления от приложения в центре уведомлений Windows
+
+
+ Доступны обновления
+
+
+ Проверка обновлений...
+
+
+ Не удалось скачать файл обновления.
+
+
+ Не удалось подключиться к github.
+
+
+ Не удалось найти файл обновления.
+
+
+ Упс. Произошла ошибка
+
+
+ У вас последняя версия
+
+
+ Контроллер теперь скрыт, а входные данные перенаправляются на виртуальный контроллер
+
+
+ ЛЕВЫЙ ТРЕКПАД
+
+
+ ФУНКЦИИ ЛЕВЫЙ ТРЕКПАД
+
+
+ ПРАВЫЙ ТРЕКПАД
+
+
+ ФУНКЦИИ ПРАВЫЙТРЕКПАД
+
+
+ ЛЕВЫЙ ТРИГГЕР
+
+
+ ФУНКЦИИ ЛЕВЫЙ ТРИГГЕР
+
+
+ ПРАВЫЙ ТРИГГЕР
+
+
+ ФУНКЦИИ ПРАВЫЙ ТРИГГЕР
+
+
+ Пользователь
+
+
+ Запустите от имени администратора чтобы разблокировать эти настройки
+
+
+ Connect
+
+
+ Disconnect
+
+
+ Hide
+
+
+ Unhide
+
+
+ Virtual
+
+
+ Manufacturer
+
+
+ Product name
+
+
+ This input will operate as a simple joystick. Ideal for laptop and clamshell type handhelds, automatic yaw roll swap based on how device is being held (90 or 180 degree open).
+
+
+ Desktop layout
+
+
+ Define desktop layout
+
+
+ Define controller layout when in desktop mode
+
+
+ Edit
+
+
+ Enable desktop layout
+
+
+ Non-game controller layouts
+
+
+ You might want to click on Connect next to your plugged controller.
+
+
+ You have no physical controller connected. No inputs will be sent to HC or its service.
+
+
+ Please make sure you connected a compatible XInput or DInput device.
+
+
+ No physical controller detected
+
+
+ No physical controller connected
+
+
+ You might want to start companion service or make sure your virtual controller status is set to: Connected
+
+
+ Your physical controller is hidden, yet you have no virtual controller available. No inputs will be sent to games.
+
+
+ No virtual controller detected
+
+
+ You might want to unmute your virtual controller or unhide your physical controller.
+
+
+ Your physical controller is hidden, yet you have muted your virtual controller.
+
+
+ Physical controller is hidden
+
+
+ You might want to hide your physical controller or mute your virtual controller.
+
+
+ Your physical controller is not hidden, yet you have an unmuted virtual controller. You might encounter double inputs in games.
+
+
+ Physical controller is not hidden
+
+
+ HD rumble
+
+
+ Use high-definition rumble engine, at the cost of higher CPU usage
+
+
+ Приостановить виртуальные контроллер
+
+
+ Временно отключает виртуальный контрллер в Steam приложених
+
+
+ Настройки контроллера
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Win
+
+
+ Esc
+
+
+ KB
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ AYA
+
+
+ ≈
+
+
+ RC
+
+
+ LC
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ Single-touch swipe
+
+
+ Multi-touch swipe
+
+
+ Cross
+
+
+ Circle
+
+
+ Square
+
+
+ Triangle
+
+
+ Share
+
+
+ Single-touch click
+
+
+ Single-touch tap
+
+
+ Multi-touch click
+
+
+ Multi-touch tap
+
+
+ Sony
+
+
+ Options
+
+
+ A
+
+
+ Always On
+
+
+ B
+
+
+ Back
+
+
+ DPad Down
+
+
+ DPad Left
+
+
+ DPad Right
+
+
+ DPad Up
+
+
+ Left Shoulder
+
+
+ Left Thumb
+
+
+ Left Trigger
+
+
+ Right Shoulder
+
+
+ Right Thumb
+
+
+ Right Trigger
+
+
+ Start
+
+
+ X
+
+
+ Y
+
+
+ Emulated DualShock 4 controller
+
+
+ No emulated controller
+
+
+ Emulated XBOX 360 controller
+
+
+ Connected
+
+
+ Disconnected
+
+
+ Auto Roll Yaw Swap
+
+
+ Joystick camera
+
+
+ Joystick steering
+
+
+ Player space
+
+
+ Custom
+
+
+ Device
+
+
+ Handheld Companion
+
+
+ Handheld Companion
+
+
+ Overlay
+
+
+ Quick tools
+
+
+ Windows
+
+
+ A
+
+
+ Alt
+
+
+ Apostrophe
+
+
+ B
+
+
+ Backslash
+
+
+ Backspace
+
+
+ C
+
+
+ Comma
+
+
+ Control
+
+
+ D
+
+
+ Delete
+
+
+ E
+
+
+ End
+
+
+ Enter
+
+
+ Equal
+
+
+ Escape
+
+
+ F
+
+
+ F1
+
+
+ F10
+
+
+ F11
+
+
+ F12
+
+
+ F2
+
+
+ F3
+
+
+ F4
+
+
+ F5
+
+
+ F6
+
+
+ F7
+
+
+ F8
+
+
+ F9
+
+
+ G
+
+
+ Grave
+
+
+ H
+
+
+ Home
+
+
+ I
+
+
+ Insert
+
+
+ J
+
+
+ K
+
+
+ L
+
+
+ M
+
+
+ Minus
+
+
+ N
+
+
+ O
+
+
+ P
+
+
+ Pause
+
+
+ Period
+
+
+ Q
+
+
+ R
+
+
+ S
+
+
+ Semicolon
+
+
+ Shift
+
+
+ Slash
+
+
+ Space
+
+
+ T
+
+
+ Tab
+
+
+ U
+
+
+ V
+
+
+ W
+
+
+ X
+
+
+ Y
+
+
+ Z
+
+
+ Auto Roll Yaw Swap
+
+
+ Joystick Camera
+
+
+ Joystick Steering
+
+
+ Player Space
+
+
+ LeftStick
+
+
+ MoveCursor
+
+
+ RightStick
+
+
+ ScrollWheel
+
+
+ Left Stick
+
+
+ Right Stick
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ View
+
+
+ STEAM
+
+
+ Menu
+
+
+ Left joystick
+
+
+ Right joystick
+
+
+ ZL
+
+
+ ZR
+
+
+ B
+
+
+ A
+
+
+ Y
+
+
+ X
+
+
+ Minus
+
+
+ L
+
+
+ R
+
+
+ Home
+
+
+ Capture
+
+
+ Plus
+
+
+ This is your default controller profile. This profile will be applied for all your applications that do not have a specific profile. Some options requiring an executable might be disabled.
+
+
+ Oops. This profile seems to be running. Some options requiring an executable may be disabled.
+
+
+ Oops. It seems this profile does not have an executable. How is this even possible?
+
+
+ Oops. It seems this profile does not have a path to the application. Some options requiring an executable might be disabled.
+
+
+ Oops. It seems you do not have the necessary permission level to modify the content of this application. Make sure you have started this program in administrator mode.
+
+
+ Nothing to see here.
+
+
+ Oops. It seems this profile excutable is running. Some options requiring an executable might be disabled.
+
+
+ Default
+
+
+ Eco
+
+
+ High
+
+
+ Command center
+
+
+ Armory crate
+
+
+ M1
+
+
+ Automatic
+
+
+ Disabled
+
+
+ Manual
+
+
+ Options
+
+
+ L2
+
+
+ LeftStick
+
+
+ Left Thumb
+
+
+ R2
+
+
+ Right Thumb
+
+
+ A
+
+
+ B
+
+
+ X
+
+
+ Y
+
+
+ B5
+
+
+ B6
+
+
+ B7
+
+
+ B8
+
+
+ View
+
+
+ DPad Down
+
+
+ DPad Left
+
+
+ DPad Right
+
+
+ DPad Up
+
+
+ LB
+
+
+ L2
+
+
+ L3
+
+
+ L4
+
+
+ AYA
+
+
+ RightStick
+
+
+ L5
+
+
+ Left Thumb
+
+
+ Left Thumb Down
+
+
+ Left Thumb Left
+
+
+ Left Thumb Right
+
+
+ Left Thumb Up
+
+
+ OEM1
+
+
+ OEM2
+
+
+ OEM3
+
+
+ RB
+
+
+ R2
+
+
+ R3
+
+
+ R4
+
+
+ R5
+
+
+ Right Thumb
+
+
+ Right Thumb Down
+
+
+ Right Thumb Left
+
+
+ Right Thumb Right
+
+
+ Right Thumb Up
+
+
+ Guide
+
+
+ Menu
+
+
+ This input will operate as a joystick optimized for controlling a steering wheel or a racing game
+
+
+ Apply template
+
+
+ Buttons
+
+
+ Cancel
+
+
+ COMMUNITY
+
+
+ Confirm
+
+
+ Dpad
+
+
+ Export for current controller
+
+
+ Export layout
+
+
+ Gyro
+
+
+ Joysticks
+
+
+ Layout author
+
+
+ Layout description
+
+
+ Layout title
+
+
+ Save game information with the layout
+
+
+ Show current controller templates only
+
+
+ Layout template picker
+
+
+ TEMPLATES
+
+
+ Trackpads
+
+
+ Triggers
+
+
+ This input will operate as a simple joystick. This is intended for traditional joystick applications
+
+
+ Back
+
+
+ Exit
+
+
+ Main Window
+
+
+ Navigate
+
+
+ Quick Tools
+
+
+ Select
+
+
+ Yes
+
+
+ No
+
+
+ Improve virtual controller detection might not work if you close Handheld Companion. Are you sure ?
+
+
+ Warning
+
+
+ ms
+
+
+ Disabled
+
+
+ Extended
+
+
+ External
+
+
+ Full
+
+
+ Minimal
+
+
+ This input will operate as a joystick optimized for controlling a first or third person camera
+
+
+ Are you sure you want to apply this template? All layout settings will be overridden.
+
+
+ You can't undo this action. Previously applied template: {0}
+
+
+ Change the virtual controller layout
+
+
+ CPU
+
+
+ Energy performance preference (EPP)
+
+
+ CPU/GPU power balance
+
+
+ Specifies power distribution policy between CPU and GPU
+
+
+ GPU
+
+
+ Power limit target
+
+
+ Disabled
+
+
+ Injection (recommended)
+
+
+ Redirection
+
+
+ CPU boost mode
+
+
+ Set current CPU boost mode
+
+
+ Display resolution and refresh rate
+
+
+ Adjust main display resolution and refresh rate
+
+
+ Fan override
+
+
+ Set the fan duty cycle to user-defined value
+
+
+ %
+
+
+ Current profile:
+
+
+ Default
+
+
+ Power limit target
+
+
+ Improve virtual controller detection
+
+
+ Forces the virtual controller to be detected as first controller during Windows start. Enable this if your app/game doesn't detect your inputs (requires device reboot).
+
+
+ Yes
+
+
+ No
+
+
+ Your device must be restarted in order for the changes to take effect. Would you like to restart now?
+
+
+ Restart required
+
+
+ Hide when loses focus
+
+
+ Automatically hide quick tools when the user clicks outside of window
+
+
+ Native display orientation
+
+
+ Some features depend on knowing the native display orientation to work properly. If this was not detected properly, set your display's orientation to the orientation that matches your controller, then click Detect
+
+
+ Detect
+
+
+ Not set
+
+
+ Power options
+
+
+ Quicktools backdrop, none, mica, tabbed, acrylic
+
+
+ Quicktools options
+
+
+ Window location
+
+
+ Bottom left
+
+
+ Bottom right
+
+
+ Define quicktools window location
+
+
+ Top left
+
+
+ Top right
+
+
+ RivaTuner Statistics Server
+
+
+ Automatically turn RTSS off when companion is closed
+
+
+ None
+
+
+ Third-party applications
+
+
+ Yes
+
+
+ No
+
+
+ Disabling this setting will also disable "Improve virtual controller detection". Do you want to continue?
+
+
+ Warning
+
+
+ M2
+
+
+ Mouse wheel click
+
+
+ Mouse wheel up
+
+
+ Mouse wheel down
+
+
+ Y1
+
+
+ Y2
+
+
+ M3
+
+
+ Y3
+
+
+ LegionR
+
+
+ LegionL
+
+
+ M2
+
+
+ Gamepad: {0}
+
\ No newline at end of file
diff --git a/HandheldCompanion/Properties/Resources.zh-CN.resx b/HandheldCompanion/Properties/Resources.zh-CN.resx
index d387da295..9f7a69ae4 100644
--- a/HandheldCompanion/Properties/Resources.zh-CN.resx
+++ b/HandheldCompanion/Properties/Resources.zh-CN.resx
@@ -1486,12 +1486,6 @@
当程序退出时自动退出RTSS
-
- 当应用退出时自动退出HWiNFO
-
-
- HWiNFO
-
默认
diff --git a/HandheldCompanion/Properties/Resources.zh-Hant.resx b/HandheldCompanion/Properties/Resources.zh-Hant.resx
index 38cde275d..7453fc228 100644
--- a/HandheldCompanion/Properties/Resources.zh-Hant.resx
+++ b/HandheldCompanion/Properties/Resources.zh-Hant.resx
@@ -1486,12 +1486,6 @@
當程序退出時自動退出RTSS
-
- 當應用退出時自動退出HWiNFO
-
-
- HWiNFO
-
默認
diff --git a/HandheldCompanion/Properties/Settings.Designer.cs b/HandheldCompanion/Properties/Settings.Designer.cs
index 54fcf05d5..53819a602 100644
--- a/HandheldCompanion/Properties/Settings.Designer.cs
+++ b/HandheldCompanion/Properties/Settings.Designer.cs
@@ -7,11 +7,10 @@
// the code is regenerated.
//
//------------------------------------------------------------------------------
-
using System.Configuration;
-namespace HandheldCompanion.Properties {
+namespace HandheldCompanion.Properties {
[SettingsProvider(typeof(CustomSettingsProvider))]
internal sealed partial class Settings : ApplicationSettingsBase
@@ -720,18 +719,6 @@ public bool PlatformRTSSEnabled {
}
}
- [global::System.Configuration.UserScopedSettingAttribute()]
- [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
- [global::System.Configuration.DefaultSettingValueAttribute("True")]
- public bool PlatformHWiNFOEnabled {
- get {
- return ((bool)(this["PlatformHWiNFOEnabled"]));
- }
- set {
- this["PlatformHWiNFOEnabled"] = value;
- }
- }
-
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("3")]
@@ -899,6 +886,18 @@ public bool LEDAmbilightVerticalBlackBarDetection {
}
}
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool LEDUseSecondColor {
+ get {
+ return ((bool)(this["LEDUseSecondColor"]));
+ }
+ set {
+ this["LEDUseSecondColor"] = value;
+ }
+ }
+
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
@@ -981,5 +980,29 @@ public bool LegionControllerPassthrough {
this["LegionControllerPassthrough"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("False")]
+ public bool OnScreenDisplayToggle {
+ get {
+ return ((bool)(this["OnScreenDisplayToggle"]));
+ }
+ set {
+ this["OnScreenDisplayToggle"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("2")]
+ public int LastOnScreenDisplayLevel {
+ get {
+ return ((int)(this["LastOnScreenDisplayLevel"]));
+ }
+ set {
+ this["LastOnScreenDisplayLevel"] = value;
+ }
+ }
}
}
diff --git a/HandheldCompanion/Properties/Settings.settings b/HandheldCompanion/Properties/Settings.settings
index 74c119a81..825e9dcf7 100644
--- a/HandheldCompanion/Properties/Settings.settings
+++ b/HandheldCompanion/Properties/Settings.settings
@@ -176,9 +176,6 @@
True
-
- True
-
3
@@ -221,6 +218,9 @@
False
+
+ False
+
0
@@ -242,5 +242,11 @@
False
+
+ False
+
+
+ 2
+
\ No newline at end of file
diff --git a/HandheldCompanion/Resources/device_aya_kun.png b/HandheldCompanion/Resources/device_aya_kun.png
new file mode 100644
index 000000000..b109cfc3c
Binary files /dev/null and b/HandheldCompanion/Resources/device_aya_kun.png differ
diff --git a/HandheldCompanion/Resources/libryzenadj.dll b/HandheldCompanion/Resources/libryzenadj.dll
index 06e28e1bf..c45d7a7c1 100644
Binary files a/HandheldCompanion/Resources/libryzenadj.dll and b/HandheldCompanion/Resources/libryzenadj.dll differ
diff --git a/HandheldCompanion/Styles/NavigationView.xaml b/HandheldCompanion/Styles/NavigationView.xaml
index a1a1e7886..e0f904a22 100644
--- a/HandheldCompanion/Styles/NavigationView.xaml
+++ b/HandheldCompanion/Styles/NavigationView.xaml
@@ -6,7 +6,7 @@
xmlns:primitives="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern">
-
+
diff --git a/HandheldCompanion/Utils/RegistryWatcher.cs b/HandheldCompanion/Utils/RegistryWatcher.cs
new file mode 100644
index 000000000..cf22b9c5e
--- /dev/null
+++ b/HandheldCompanion/Utils/RegistryWatcher.cs
@@ -0,0 +1,107 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Management;
+using System.Security.Principal;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HandheldCompanion.Utils
+{
+ public class RegistryChangedEventArgs : EventArgs
+ {
+ public readonly object? Data;
+
+ public RegistryChangedEventArgs(object? data)
+ {
+ Data = data;
+ }
+ }
+
+ public enum WatchedRegistry
+ {
+ CurrentUser,
+ LocalMachine,
+ }
+
+ public sealed class RegistryWatcher : IDisposable
+ {
+ public event EventHandler? RegistryChanged;
+
+ private readonly RegistryKey _registry;
+ private readonly string _key;
+ private readonly string _value;
+ private ManagementEventWatcher? _eventWatcher;
+ private readonly WqlEventQuery _query;
+
+ public RegistryWatcher(WatchedRegistry watchedRegistry, string key, string value)
+ {
+ _key = key;
+ _value = value;
+
+ var currentUser = WindowsIdentity.GetCurrent();
+ var keyPath = _key.Replace("\\", "\\\\");
+ var queryString = watchedRegistry switch
+ {
+ WatchedRegistry.LocalMachine =>
+ $"SELECT * FROM RegistryValueChangeEvent " +
+ $"WHERE Hive='HKEY_LOCAL_MACHINE' AND " +
+ $"KeyPath='{keyPath}' AND " +
+ $"ValueName='{_value}'",
+ WatchedRegistry.CurrentUser =>
+ "SELECT * FROM RegistryValueChangeEvent " +
+ "WHERE Hive='HKEY_USERS' AND " +
+ $"KeyPath='{currentUser.User!.Value}\\\\{keyPath}' AND " +
+ $"ValueName='{_value}'",
+ _ => throw new ArgumentOutOfRangeException(nameof(watchedRegistry), watchedRegistry, "This part of registry is not implemented")
+ };
+ _query = new WqlEventQuery(queryString);
+ _registry = watchedRegistry switch
+ {
+ WatchedRegistry.LocalMachine => Registry.LocalMachine,
+ WatchedRegistry.CurrentUser => Registry.CurrentUser,
+ _ => throw new ArgumentException("This part of registry is not implemented")
+ };
+ }
+
+ public void StartWatching()
+ {
+ var scope = new ManagementScope("\\\\.\\root\\default");
+ _eventWatcher = new ManagementEventWatcher(scope, _query);
+ _eventWatcher.EventArrived += KeyWatcherOnEventArrived;
+ _eventWatcher.Start();
+
+ SendData();
+ }
+
+ public void StopWatching()
+ {
+ if (_eventWatcher == null)
+ {
+ return;
+ }
+ _eventWatcher.EventArrived -= KeyWatcherOnEventArrived;
+ _eventWatcher.Stop();
+ _eventWatcher.Dispose();
+ _eventWatcher = null;
+ }
+
+ private void KeyWatcherOnEventArrived(object sender, EventArrivedEventArgs e)
+ {
+ SendData();
+ }
+
+ private void SendData()
+ {
+ using var key = _registry.OpenSubKey(_key);
+ var data = key?.GetValue(_value);
+ RegistryChanged?.Invoke(this, new RegistryChangedEventArgs(data));
+ }
+
+ public void Dispose()
+ {
+ StopWatching();
+ }
+ }
+}
diff --git a/HandheldCompanion/Utils/WPFUtils.cs b/HandheldCompanion/Utils/WPFUtils.cs
index f016c231d..ee6080da2 100644
--- a/HandheldCompanion/Utils/WPFUtils.cs
+++ b/HandheldCompanion/Utils/WPFUtils.cs
@@ -280,6 +280,28 @@ public static T FindParent(DependencyObject child) where T : DependencyObject
return parent;
}
+ // Helper method to find all visual children of a given type
+ public static IEnumerable FindVisualChildren(DependencyObject parent) where T : DependencyObject
+ {
+ if (parent != null)
+ {
+ for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
+ {
+ var child = VisualTreeHelper.GetChild(parent, i);
+
+ if (child is T)
+ {
+ yield return (T)child;
+ }
+
+ foreach (var childOfChild in FindVisualChildren(child))
+ {
+ yield return childOfChild;
+ }
+ }
+ }
+ }
+
public static void SendKeyToControl(Control control, int keyCode)
{
SendMessage(GetControlHandle(control).Handle.ToInt32(), WM_KEYDOWN, keyCode, IntPtr.Zero);
diff --git a/HandheldCompanion/Views/Pages/AboutPage.xaml b/HandheldCompanion/Views/Pages/AboutPage.xaml
index 40bb5f4ae..500aef30d 100644
--- a/HandheldCompanion/Views/Pages/AboutPage.xaml
+++ b/HandheldCompanion/Views/Pages/AboutPage.xaml
@@ -1,284 +1,284 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- DroiX
-
-
-
-
-
-
-
-
-
-
- SourceCode
-
-
-
-
- Wiki
-
-
-
-
- Donate
-
-
-
-
- Patreon
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ DroiX
+
+
+
+
+
+
+
+
+
+
+ SourceCode
+
+
+
+
+ Wiki
+
+
+
+
+ Donate
+
+
+
+
+ Patreon
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Pages/ControllerPage.xaml b/HandheldCompanion/Views/Pages/ControllerPage.xaml
index db14b2a3f..ebcd1992b 100644
--- a/HandheldCompanion/Views/Pages/ControllerPage.xaml
+++ b/HandheldCompanion/Views/Pages/ControllerPage.xaml
@@ -373,12 +373,13 @@
Grid.Column="1"
Margin="12,0,0,0"
ScrollViewer.PanningMode="HorizontalOnly">
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} %, ElementName=SliderStrength, Mode=OneWay}" />
diff --git a/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs b/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
index a78366cf5..f3798813c 100644
--- a/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/ControllerPage.xaml.cs
@@ -3,7 +3,7 @@
using HandheldCompanion.Managers;
using HandheldCompanion.Misc;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Linq;
using System.Threading;
diff --git a/HandheldCompanion/Views/Pages/DevicePage.xaml b/HandheldCompanion/Views/Pages/DevicePage.xaml
index c415f307d..f5187b60a 100644
--- a/HandheldCompanion/Views/Pages/DevicePage.xaml
+++ b/HandheldCompanion/Views/Pages/DevicePage.xaml
@@ -1,548 +1,585 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Pages/DevicePage.xaml.cs b/HandheldCompanion/Views/Pages/DevicePage.xaml.cs
index 012d2a8b6..438369a94 100644
--- a/HandheldCompanion/Views/Pages/DevicePage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/DevicePage.xaml.cs
@@ -1,315 +1,335 @@
-using ColorPicker;
-using ColorPicker.Models;
-using HandheldCompanion.Devices;
-using HandheldCompanion.Managers;
-using HandheldCompanion.Misc;
-using Inkore.UI.WPF.Modern.Controls;
-using System;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-using Windows.UI.ViewManagement;
-using static HandheldCompanion.Utils.DeviceUtils;
-using Page = System.Windows.Controls.Page;
-
-namespace HandheldCompanion.Views.Pages
-{
- ///
- /// Interaction logic for DevicePage.xaml
- ///
- public partial class DevicePage : Page
- {
- private Color prevMainColor = new();
- private Color prevSecondColor = new();
-
- public DevicePage()
- {
- InitializeComponent();
-
- // Adjust UI element availability based on device capabilities
- DynamicLightingPanel.IsEnabled = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLighting);
- LEDBrightness.IsEnabled = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLightingBrightness);
-
- LEDSolidColor.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.SolidColor);
- LEDBreathing.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Breathing);
- LEDRainbow.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Rainbow);
- LEDWave.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Wave);
- LEDWheel.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Wheel);
- LEDGradient.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Gradient);
- LEDAmbilight.IsEnabled = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(LEDLevel.Ambilight);
- }
-
- public DevicePage(string? Tag) : this()
- {
- this.Tag = Tag;
-
- SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
- MainWindow.uiSettings.ColorValuesChanged += OnColorValuesChanged;
- }
-
- private void Page_Loaded(object? sender, RoutedEventArgs? e)
- {
- }
-
- public void Page_Closed()
- {
- }
-
- private void SettingsManager_SettingValueChanged(string? name, object value)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- switch (name)
- {
- case "ConfigurableTDPOverride":
- Toggle_cTDP.IsOn = Convert.ToBoolean(value);
- break;
- case "ConfigurableTDPOverrideDown":
- NumberBox_TDPMin.Value = Convert.ToDouble(value);
- break;
- case "ConfigurableTDPOverrideUp":
- NumberBox_TDPMax.Value = Convert.ToDouble(value);
- break;
- case "LEDSettingsEnabled":
- UseDynamicLightingToggle.IsOn = Convert.ToBoolean(value);
- break;
- case "LEDSettingsUseAccentColor":
- MatchAccentColor.IsOn = Convert.ToBoolean(value);
- break;
- case "LEDSettingsLevel":
- {
- foreach (Control control in LEDSettingsLevel.Items)
- {
- if (control is not ComboBoxItem)
- continue;
-
- ComboBoxItem comboBoxItem = (ComboBoxItem)control;
- if (Convert.ToInt32(comboBoxItem.Tag) == Convert.ToInt32(value))
- {
- LEDSettingsLevel.SelectedItem = comboBoxItem;
- break;
- }
- }
- }
- break;
- case "LEDBrightness":
- SliderLEDBrightness.Value = Convert.ToDouble(value);
- break;
- case "LEDSpeed":
- SliderLEDSpeed.Value = Convert.ToDouble(value);
- break;
- case "LEDDirection":
- LEDDirection.SelectedIndex = Convert.ToInt32(value);
- break;
- case "LEDMainColor":
- MainColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(value));
- break;
- case "LEDSecondColor":
- SecondColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(value));
- break;
- case "LEDAmbilightVerticalBlackBarDetection":
- Toggle_AmbilightVerticalBlackBarDetection.IsOn = Convert.ToBoolean(value);
- break;
- }
- });
- }
-
- private void OnColorValuesChanged(UISettings sender, object args)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- if (MatchAccentColor.IsOn)
- SetAccentColor();
- });
- }
-
- private async void Toggle_cTDP_Toggled(object? sender, RoutedEventArgs? e)
- {
- if (!IsLoaded)
- return;
-
- if (Toggle_cTDP.IsOn)
- {
- // todo: localize me !
- var result = Dialog.ShowAsync(
- "Warning",
- "Altering minimum and maximum CPU power values might cause instabilities. Product warranties may not apply if the processor is operated beyond its specifications. Use at your own risk.",
- ContentDialogButton.Primary, "Cancel", Properties.Resources.ProfilesPage_OK);
-
- await result; // sync call
-
- switch (result.Result)
- {
- case ContentDialogResult.Primary:
- break;
- default:
- case ContentDialogResult.None:
- // restore previous state
- Toggle_cTDP.IsOn = false;
- return;
- }
- }
-
- SettingsManager.SetProperty("ConfigurableTDPOverride", Toggle_cTDP.IsOn);
- SettingsManager.SetProperty("ConfigurableTDPOverrideUp", NumberBox_TDPMax.Value);
- SettingsManager.SetProperty("ConfigurableTDPOverrideDown", NumberBox_TDPMin.Value);
- }
-
- private void NumberBox_TDPMax_ValueChanged(NumberBox? sender, NumberBoxValueChangedEventArgs? args)
- {
- var value = NumberBox_TDPMax.Value;
- if (double.IsNaN(value))
- return;
-
- NumberBox_TDPMin.Maximum = value;
-
- if (!IsLoaded)
- return;
-
- // update current device cTDP
- MainWindow.CurrentDevice.cTDP[1] = value;
-
- SettingsManager.SetProperty("ConfigurableTDPOverrideUp", value);
- }
-
- private void NumberBox_TDPMin_ValueChanged(NumberBox? sender, NumberBoxValueChangedEventArgs? args)
- {
- var value = NumberBox_TDPMin.Value;
- if (double.IsNaN(value))
- return;
-
- NumberBox_TDPMax.Minimum = value;
-
- if (!IsLoaded)
- return;
-
- // update current device cTDP
- MainWindow.CurrentDevice.cTDP[0] = value;
-
- SettingsManager.SetProperty("ConfigurableTDPOverrideDown", value);
- }
-
- private void UseDynamicLightingToggle_Toggled(object sender, RoutedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDSettingsEnabled", UseDynamicLightingToggle.IsOn);
- }
-
- private void MatchAccentColor_Toggled(object sender, RoutedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- MainColorPicker.IsEnabled = !MatchAccentColor.IsOn;
- SecondColorPicker.IsEnabled = !MatchAccentColor.IsOn;
-
- if (MatchAccentColor.IsOn)
- SetAccentColor();
-
- SettingsManager.SetProperty("LEDSettingsUseAccentColor", MatchAccentColor.IsOn);
- }
-
- private void SetAccentColor()
- {
- MainColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(MainWindow.uiSettings.GetColorValue(UIColorType.Accent).ToString()));
- SecondColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(MainWindow.uiSettings.GetColorValue(UIColorType.Accent).ToString()));
-
- SettingsManager.SetProperty("LEDMainColor", MainColorPicker.SelectedColor);
- SettingsManager.SetProperty("LEDSecondColor", MainColorPicker.SelectedColor);
- }
-
- private void LEDSettingsLevel_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- ComboBoxItem comboBoxItem = (ComboBoxItem)LEDSettingsLevel.SelectedItem;
- int level = Convert.ToInt32(comboBoxItem.Tag);
-
- SettingsManager.SetProperty("LEDSettingsLevel", level);
- }
-
- private void MainColorPicker_ColorChanged(object sender, RoutedEventArgs e)
- {
- // workaround: NotifyableColor is raising ColorChanged event infinitely
- ColorRoutedEventArgs colorArgs = (ColorRoutedEventArgs)e;
- if (prevMainColor == colorArgs.Color)
- {
- MainColorPicker.Color = new NotifyableColor(new PickerControlBase());
- return;
- }
- prevMainColor = colorArgs.Color;
-
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDMainColor", prevMainColor.ToString());
- }
-
- private void SecondColorPicker_ColorChanged(object sender, RoutedEventArgs e)
- {
- // workaround: NotifyableColor is raising ColorChanged event infinitely
- ColorRoutedEventArgs colorArgs = (ColorRoutedEventArgs)e;
- if (prevSecondColor == colorArgs.Color)
- {
- SecondColorPicker.Color = new NotifyableColor(new PickerControlBase());
- return;
- }
- prevSecondColor = colorArgs.Color;
-
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDSecondColor", prevSecondColor.ToString());
- }
-
- private void SliderLEDBrightness_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- var value = SliderLEDBrightness.Value;
- if (double.IsNaN(value))
- return;
-
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDBrightness", value);
- }
-
- private async void Toggle_AmbilightVerticalBlackBarDetection_Toggled(object? sender, RoutedEventArgs? e)
- {
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDAmbilightVerticalBlackBarDetection", Toggle_AmbilightVerticalBlackBarDetection.IsOn);
- }
-
- private void Expander_Expanded(object sender, RoutedEventArgs e)
- {
- ((Expander)sender).BringIntoView();
- }
-
- private void SliderLEDSpeed_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- var value = SliderLEDSpeed.Value;
- if (double.IsNaN(value))
- return;
-
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDSpeed", value);
- }
-
- private void LEDDirection_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("LEDDirection", LEDDirection.SelectedIndex);
- }
- }
-}
+using ColorPicker;
+using ColorPicker.Models;
+using HandheldCompanion.Devices;
+using HandheldCompanion.Managers;
+using HandheldCompanion.Misc;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using Windows.UI.ViewManagement;
+using static HandheldCompanion.Utils.DeviceUtils;
+using Page = System.Windows.Controls.Page;
+
+namespace HandheldCompanion.Views.Pages
+{
+ ///
+ /// Interaction logic for DevicePage.xaml
+ ///
+ public partial class DevicePage : Page
+ {
+ private Color prevMainColor = new();
+ private Color prevSecondColor = new();
+
+ public DevicePage()
+ {
+ InitializeComponent();
+
+ // Adjust UI element availability based on device capabilities
+ DynamicLightingPanel.IsEnabled = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLighting);
+ LEDBrightness.Visibility = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLightingBrightness) ? Visibility.Visible : Visibility.Collapsed;
+ StackSecondColor.Visibility = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLightingSecondLEDColor) ? Visibility.Visible : Visibility.Collapsed;
+
+ SetControlEnabledAndVisible(LEDSolidColor, LEDLevel.SolidColor);
+ SetControlEnabledAndVisible(LEDBreathing, LEDLevel.Breathing);
+ SetControlEnabledAndVisible(LEDRainbow, LEDLevel.Rainbow);
+ SetControlEnabledAndVisible(LEDWave, LEDLevel.Wave);
+ SetControlEnabledAndVisible(LEDWheel, LEDLevel.Wheel);
+ SetControlEnabledAndVisible(LEDGradient, LEDLevel.Gradient);
+ SetControlEnabledAndVisible(LEDAmbilight, LEDLevel.Ambilight);
+
+ }
+
+ public DevicePage(string? Tag) : this()
+ {
+ this.Tag = Tag;
+
+ SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ MainWindow.uiSettings.ColorValuesChanged += OnColorValuesChanged;
+ }
+
+ private void Page_Loaded(object? sender, RoutedEventArgs? e)
+ {
+ }
+
+ public void Page_Closed()
+ {
+ }
+
+ private void SettingsManager_SettingValueChanged(string? name, object value)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ switch (name)
+ {
+ case "ConfigurableTDPOverride":
+ Toggle_cTDP.IsOn = Convert.ToBoolean(value);
+ break;
+ case "ConfigurableTDPOverrideDown":
+ NumberBox_TDPMin.Value = Convert.ToDouble(value);
+ break;
+ case "ConfigurableTDPOverrideUp":
+ NumberBox_TDPMax.Value = Convert.ToDouble(value);
+ break;
+ case "LEDSettingsEnabled":
+ UseDynamicLightingToggle.IsOn = Convert.ToBoolean(value);
+ break;
+ case "LEDSettingsUseAccentColor":
+ MatchAccentColor.IsOn = Convert.ToBoolean(value);
+ break;
+ case "LEDSettingsLevel":
+ {
+ foreach (Control control in LEDSettingsLevel.Items)
+ {
+ if (control is not ComboBoxItem)
+ continue;
+
+ ComboBoxItem comboBoxItem = (ComboBoxItem)control;
+ if (Convert.ToInt32(comboBoxItem.Tag) == Convert.ToInt32(value))
+ {
+ LEDSettingsLevel.SelectedItem = comboBoxItem;
+ break;
+ }
+ }
+ }
+ break;
+ case "LEDBrightness":
+ SliderLEDBrightness.Value = Convert.ToDouble(value);
+ break;
+ case "LEDSpeed":
+ SliderLEDSpeed.Value = Convert.ToDouble(value);
+ break;
+ case "LEDDirection":
+ LEDDirection.SelectedIndex = Convert.ToInt32(value);
+ break;
+ case "LEDMainColor":
+ MainColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(value));
+ break;
+ case "LEDSecondColor":
+ SecondColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(value));
+ break;
+ case "LEDAmbilightVerticalBlackBarDetection":
+ Toggle_AmbilightVerticalBlackBarDetection.IsOn = Convert.ToBoolean(value);
+ break;
+ case "LEDUseSecondColor":
+ Toggle_UseSecondColor.IsOn = Convert.ToBoolean(value);
+ break;
+ }
+ });
+ }
+
+ private void OnColorValuesChanged(UISettings sender, object args)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ if (MatchAccentColor.IsOn)
+ SetAccentColor();
+ });
+ }
+
+ private async void Toggle_cTDP_Toggled(object? sender, RoutedEventArgs? e)
+ {
+ if (!IsLoaded)
+ return;
+
+ if (Toggle_cTDP.IsOn)
+ {
+ // todo: localize me !
+ var result = Dialog.ShowAsync(
+ "Warning",
+ "Altering minimum and maximum CPU power values might cause instabilities. Product warranties may not apply if the processor is operated beyond its specifications. Use at your own risk.",
+ ContentDialogButton.Primary, "Cancel", Properties.Resources.ProfilesPage_OK);
+
+ await result; // sync call
+
+ switch (result.Result)
+ {
+ case ContentDialogResult.Primary:
+ break;
+ default:
+ case ContentDialogResult.None:
+ // restore previous state
+ Toggle_cTDP.IsOn = false;
+ return;
+ }
+ }
+
+ SettingsManager.SetProperty("ConfigurableTDPOverride", Toggle_cTDP.IsOn);
+ SettingsManager.SetProperty("ConfigurableTDPOverrideUp", NumberBox_TDPMax.Value);
+ SettingsManager.SetProperty("ConfigurableTDPOverrideDown", NumberBox_TDPMin.Value);
+ }
+
+ private void NumberBox_TDPMax_ValueChanged(NumberBox? sender, NumberBoxValueChangedEventArgs? args)
+ {
+ var value = NumberBox_TDPMax.Value;
+ if (double.IsNaN(value))
+ return;
+
+ NumberBox_TDPMin.Maximum = value;
+
+ if (!IsLoaded)
+ return;
+
+ // update current device cTDP
+ MainWindow.CurrentDevice.cTDP[1] = value;
+
+ SettingsManager.SetProperty("ConfigurableTDPOverrideUp", value);
+ }
+
+ private void NumberBox_TDPMin_ValueChanged(NumberBox? sender, NumberBoxValueChangedEventArgs? args)
+ {
+ var value = NumberBox_TDPMin.Value;
+ if (double.IsNaN(value))
+ return;
+
+ NumberBox_TDPMax.Minimum = value;
+
+ if (!IsLoaded)
+ return;
+
+ // update current device cTDP
+ MainWindow.CurrentDevice.cTDP[0] = value;
+
+ SettingsManager.SetProperty("ConfigurableTDPOverrideDown", value);
+ }
+
+ private void UseDynamicLightingToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDSettingsEnabled", UseDynamicLightingToggle.IsOn);
+ }
+
+ private void MatchAccentColor_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ MainColorPicker.IsEnabled = !MatchAccentColor.IsOn;
+ SecondColorPicker.IsEnabled = !MatchAccentColor.IsOn;
+
+ if (MatchAccentColor.IsOn)
+ SetAccentColor();
+
+ SettingsManager.SetProperty("LEDSettingsUseAccentColor", MatchAccentColor.IsOn);
+ }
+
+ private void SetAccentColor()
+ {
+ MainColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(MainWindow.uiSettings.GetColorValue(UIColorType.Accent).ToString()));
+ SecondColorPicker.SelectedColor = (Color)ColorConverter.ConvertFromString(Convert.ToString(MainWindow.uiSettings.GetColorValue(UIColorType.Accent).ToString()));
+
+ SettingsManager.SetProperty("LEDMainColor", MainColorPicker.SelectedColor);
+ SettingsManager.SetProperty("LEDSecondColor", MainColorPicker.SelectedColor);
+ }
+
+ private void LEDSettingsLevel_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ ComboBoxItem comboBoxItem = (ComboBoxItem)LEDSettingsLevel.SelectedItem;
+ int level = Convert.ToInt32(comboBoxItem.Tag);
+
+ SettingsManager.SetProperty("LEDSettingsLevel", level);
+ }
+
+ private void MainColorPicker_ColorChanged(object sender, RoutedEventArgs e)
+ {
+ // workaround: NotifyableColor is raising ColorChanged event infinitely
+ ColorRoutedEventArgs colorArgs = (ColorRoutedEventArgs)e;
+ if (prevMainColor == colorArgs.Color)
+ {
+ MainColorPicker.Color = new NotifyableColor(new PickerControlBase());
+ return;
+ }
+ prevMainColor = colorArgs.Color;
+
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDMainColor", prevMainColor.ToString());
+ }
+
+ private void SecondColorPicker_ColorChanged(object sender, RoutedEventArgs e)
+ {
+ // workaround: NotifyableColor is raising ColorChanged event infinitely
+ ColorRoutedEventArgs colorArgs = (ColorRoutedEventArgs)e;
+ if (prevSecondColor == colorArgs.Color)
+ {
+ SecondColorPicker.Color = new NotifyableColor(new PickerControlBase());
+ return;
+ }
+ prevSecondColor = colorArgs.Color;
+
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDSecondColor", prevSecondColor.ToString());
+ }
+
+ private void SliderLEDBrightness_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ var value = SliderLEDBrightness.Value;
+ if (double.IsNaN(value))
+ return;
+
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDBrightness", value);
+ }
+
+ private async void Toggle_AmbilightVerticalBlackBarDetection_Toggled(object? sender, RoutedEventArgs? e)
+ {
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDAmbilightVerticalBlackBarDetection", Toggle_AmbilightVerticalBlackBarDetection.IsOn);
+ }
+
+ private async void Toggle_UseSecondColor_Toggled(object? sender, RoutedEventArgs? e)
+ {
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDUseSecondColor", Toggle_UseSecondColor.IsOn);
+ }
+
+ private void Expander_Expanded(object sender, RoutedEventArgs e)
+ {
+ ((Expander)sender).BringIntoView();
+ }
+
+ private void SliderLEDSpeed_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ var value = SliderLEDSpeed.Value;
+ if (double.IsNaN(value))
+ return;
+
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDSpeed", value);
+ }
+
+ private void LEDDirection_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("LEDDirection", LEDDirection.SelectedIndex);
+ }
+
+ private void SetControlEnabledAndVisible(UIElement control, LEDLevel level)
+ {
+ bool isCapabilitySupported = MainWindow.CurrentDevice.DynamicLightingCapabilities.HasFlag(level);
+ control.IsEnabled = isCapabilitySupported;
+ control.Visibility = isCapabilitySupported ? Visibility.Visible : Visibility.Collapsed;
+ }
+ }
+}
diff --git a/HandheldCompanion/Views/Pages/HotkeysPage.xaml.cs b/HandheldCompanion/Views/Pages/HotkeysPage.xaml.cs
index 7888ae918..dff69fa66 100644
--- a/HandheldCompanion/Views/Pages/HotkeysPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/HotkeysPage.xaml.cs
@@ -1,6 +1,6 @@
using HandheldCompanion.Managers;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System.Windows;
using System.Windows.Controls;
using Page = System.Windows.Controls.Page;
diff --git a/HandheldCompanion/Views/Pages/Layout/ButtonsPage.xaml.cs b/HandheldCompanion/Views/Pages/Layout/ButtonsPage.xaml.cs
index 7448ff32c..72779a7cc 100644
--- a/HandheldCompanion/Views/Pages/Layout/ButtonsPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/Layout/ButtonsPage.xaml.cs
@@ -1,7 +1,7 @@
using HandheldCompanion.Controllers;
using HandheldCompanion.Controls;
using HandheldCompanion.Inputs;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/HandheldCompanion/Views/Pages/Layout/ILayoutPage.cs b/HandheldCompanion/Views/Pages/Layout/ILayoutPage.cs
index 656995276..00bdc7f5e 100644
--- a/HandheldCompanion/Views/Pages/Layout/ILayoutPage.cs
+++ b/HandheldCompanion/Views/Pages/Layout/ILayoutPage.cs
@@ -2,7 +2,7 @@
using HandheldCompanion.Controllers;
using HandheldCompanion.Controls;
using HandheldCompanion.Inputs;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System.Collections.Generic;
using System.Windows;
using Page = System.Windows.Controls.Page;
diff --git a/HandheldCompanion/Views/Pages/LayoutPage.xaml.cs b/HandheldCompanion/Views/Pages/LayoutPage.xaml.cs
index 9e21645c1..4bd9eb7b7 100644
--- a/HandheldCompanion/Views/Pages/LayoutPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/LayoutPage.xaml.cs
@@ -5,7 +5,7 @@
using HandheldCompanion.Managers;
using HandheldCompanion.Misc;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Nefarius.Utilities.DeviceManagement.PnP;
using System;
using System.Collections.Generic;
diff --git a/HandheldCompanion/Views/Pages/NotificationsPage.xaml b/HandheldCompanion/Views/Pages/NotificationsPage.xaml
index 1eca3b82d..d1c1d791a 100644
--- a/HandheldCompanion/Views/Pages/NotificationsPage.xaml
+++ b/HandheldCompanion/Views/Pages/NotificationsPage.xaml
@@ -1,66 +1,64 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Pages/OverlayPage.xaml b/HandheldCompanion/Views/Pages/OverlayPage.xaml
index 74be973ce..c6ee0c961 100644
--- a/HandheldCompanion/Views/Pages/OverlayPage.xaml
+++ b/HandheldCompanion/Views/Pages/OverlayPage.xaml
@@ -9,7 +9,7 @@
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
Name="Overlay"
Title="{x:Static resx:Resources.OverlayPage_Overlay}"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1800"
d:DesignWidth="1000"
KeepAlive="True"
@@ -55,6 +55,7 @@
@@ -97,14 +98,17 @@
-
-
+
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} ms, ElementName=SliderOnScreenUpdateRate, Mode=OneWay}" />
@@ -207,7 +212,10 @@
-
+
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} px, ElementName=SliderControllerSize, Mode=OneWay}" />
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=SliderControllerOpacity, Mode=OneWay}" />
-
+
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} FPS, ElementName=Slider_Framerate, Mode=OneWay}" />
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1} °, ElementName=Slider_RestingPitch, Mode=OneWay}" />
-
+
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} px, ElementName=SliderTrackpadsSize, Mode=OneWay}" />
-
-
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=SliderTrackpadsOpacity, Mode=OneWay}" />
+
+
+
-
-
+
+
+
+
+
-
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
- Device profiles
- User profiles
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -223,14 +261,25 @@
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -303,15 +344,25 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -380,15 +423,25 @@
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
-
-
+ AutoToolTipPrecision="0"
+ IsMoveToPointEnabled="True"
+ IsSnapToTickEnabled="True"
+ LargeChange="10"
+ Maximum="100"
+ Minimum="0"
+ SmallChange="1"
+ Style="{DynamicResource SliderStyle1}"
+ TickFrequency="10"
+ TickPlacement="BottomRight"
+ ToolTip="{Binding Value, StringFormat=N0, RelativeSource={RelativeSource Self}, Mode=OneWay}"
+ ValueChanged="EPPSlider_ValueChanged" />
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Text="{x:Static resx:Resources.ProfilesPage_CPU}" />
+
+
+
+
@@ -476,21 +507,32 @@
CornerRadius="{DynamicResource ControlCornerRadius}">
-
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -554,21 +588,32 @@
Name="StackProfileGPUClock"
IsEnabled="False"
Spacing="6">
-
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -630,14 +667,30 @@
Background="{DynamicResource ExpanderHeaderBackground}"
CornerRadius="{DynamicResource ControlCornerRadius}">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+ {
+ AutoTDPSlider.Maximum = desktopScreen.devMode.dmDisplayFrequency;
+ });
+ }
+
private void PowerProfileManager_Deleted(PowerProfile profile)
{
// UI thread (async)
@@ -224,7 +235,7 @@ private void PerformanceManager_EPPChanged(uint EPP)
private void PerformanceManager_Initialized()
{
- Processor processor = MainWindow.performanceManager.GetProcessor();
+ Processor processor = PerformanceManager.GetProcessor();
if (processor is null)
return;
@@ -407,12 +418,31 @@ private void UpdateUI()
{
using (new ScopedLock(updateLock))
{
+ if (selectedProfile.DeviceDefault)
+ {
+ WarningBorder.Visibility = Visibility.Visible;
+ WarningContent.Text = Properties.Resources.ProfilesPage_DefaultDeviceProfile;
+ }
+ else if (selectedProfile.Default)
+ {
+ WarningBorder.Visibility = Visibility.Visible;
+ WarningContent.Text = Properties.Resources.ProfilesPage_DefaultProfile;
+ }
+ else
+ {
+ WarningBorder.Visibility = Visibility.Collapsed;
+ WarningContent.Text = string.Empty;
+ }
+
+ // Disable everything for device power profiles
+ PowerPanel.IsEnabled = !selectedProfile.DeviceDefault;
+ FanPanel.IsEnabled = !selectedProfile.DeviceDefault;
+
// update PowerProfile settings
PowerProfileName.Text = selectedProfile.Name;
PowerProfileDescription.Text = selectedProfile.Description;
// we shouldn't allow users to modify some of default profile settings
- FanMode.IsEnabled = !selectedProfile.Default;
ButtonProfileDelete.IsEnabled = !selectedProfile.Default;
ButtonProfileMore.IsEnabled = !selectedProfile.Default;
diff --git a/HandheldCompanion/Views/Pages/Profiles/SettingsMode0.xaml b/HandheldCompanion/Views/Pages/Profiles/SettingsMode0.xaml
index 3e1015d59..083e8592e 100644
--- a/HandheldCompanion/Views/Pages/Profiles/SettingsMode0.xaml
+++ b/HandheldCompanion/Views/Pages/Profiles/SettingsMode0.xaml
@@ -52,11 +52,13 @@
Grid.Column="1"
Margin="12,0,0,0"
ScrollViewer.PanningMode="HorizontalOnly">
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=SliderSensitivityX, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=SliderSensitivityY, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=tb_ProfileAimingDownSightsMultiplier, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} ms, ElementName=tb_ProfileFlickDuration, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=tb_ProfileStickSensitivity, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} °, ElementName=SliderSteeringAngle, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=SliderPower, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1} °, ElementName=SliderDeadzoneAngle, Mode=OneWay}" />
+
+
+
+
+
@@ -137,57 +149,127 @@
Height="40"
FontFamily="{DynamicResource SymbolThemeFontFamily}"
Foreground="{DynamicResource SystemControlForegroundBaseHighBrush}"
- Glyph="" />
+ Glyph="" />
+ Text="{x:Static resx:Resources.ProfilesPage_ProfilePath}" />
+ BorderThickness="1"
+ IsEnabled="False"
+ IsReadOnly="True" />
+
-
+ Glyph="" />
+ Text="{x:Static resx:Resources.ProfilesPage_SubProfiles}" />
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ Margin="12,0,0,0"
+ d:Visibility="Visible"
+ ScrollViewer.PanningMode="HorizontalOnly"
+ Visibility="{Binding ElementName=RSRToggle, Path=IsOn, Converter={StaticResource BooleanToVisibilityConverter}}">
-
-
+
-
-
+ AutoToolTipPrecision="0"
+ IsMoveToPointEnabled="True"
+ IsSnapToTickEnabled="True"
+ LargeChange="5"
+ Maximum="100"
+ Minimum="0"
+ SmallChange="1"
+ Style="{DynamicResource SliderStyle1}"
+ TickFrequency="5"
+ TickPlacement="BottomRight"
+ ToolTip="{Binding Value, StringFormat={}{0:N0} %, RelativeSource={RelativeSource Self}, Mode=OneWay}"
+ ValueChanged="RSRSlider_ValueChanged" />
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ SelectionChanged="IntegerScalingComboBox_SelectionChanged" />
+
+
+
+
+
+
-
+
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
+
-
+
+
+
+ ValueChanged="RISSlider_ValueChanged" />
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -515,11 +765,11 @@
Glyph="" />
-
+
@@ -585,11 +835,13 @@
Grid.Column="1"
Margin="12,0,0,0"
ScrollViewer.PanningMode="HorizontalOnly">
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=tb_ProfileGyroValue, Mode=OneWay}" />
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=tb_ProfileAcceleroValue, Mode=OneWay}" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HandheldCompanion/Views/Pages/ProfilesPage.xaml.cs b/HandheldCompanion/Views/Pages/ProfilesPage.xaml.cs
index 1d2b1b130..7636336d3 100644
--- a/HandheldCompanion/Views/Pages/ProfilesPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/ProfilesPage.xaml.cs
@@ -4,13 +4,17 @@
using HandheldCompanion.Managers;
using HandheldCompanion.Managers.Desktop;
using HandheldCompanion.Misc;
+using HandheldCompanion.Platforms;
using HandheldCompanion.Utils;
using HandheldCompanion.Views.Pages.Profiles;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Microsoft.Win32;
+using SharpDX.Win32;
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
+using System.Linq;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
@@ -28,6 +32,7 @@ public partial class ProfilesPage : Page
{
// when set on start cannot be null anymore
public static Profile selectedProfile;
+ private static Profile selectedMainProfile;
private readonly SettingsMode0 page0 = new("SettingsMode0");
private readonly SettingsMode1 page1 = new("SettingsMode1");
@@ -37,56 +42,115 @@ public partial class ProfilesPage : Page
private const int UpdateInterval = 500;
private static Timer UpdateTimer;
+ public ProfilesPage(string Tag) : this()
+ {
+ this.Tag = Tag;
+ }
+
public ProfilesPage()
{
InitializeComponent();
+
+ // manage events
+ ProfileManager.Deleted += ProfileDeleted;
+ ProfileManager.Updated += ProfileUpdated;
+ ProfileManager.Applied += ProfileApplied;
+ ProfileManager.Initialized += ProfileManagerLoaded;
+ PowerProfileManager.Updated += PowerProfileManager_Updated;
+ PowerProfileManager.Deleted += PowerProfileManager_Deleted;
+ SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ SystemManager.Initialized += SystemManager_Initialized;
+ SystemManager.PrimaryScreenChanged += SystemManager_PrimaryScreenChanged;
+ SystemManager.StateChanged_RSR += SystemManager_StateChanged_RSR;
+ SystemManager.StateChanged_IntegerScaling += SystemManager_StateChanged_IntegerScaling;
+ SystemManager.StateChanged_GPUScaling += SystemManager_StateChanged_GPUScaling;
+ PlatformManager.RTSS.Updated += RTSS_Updated;
UpdateTimer = new Timer(UpdateInterval);
UpdateTimer.AutoReset = false;
UpdateTimer.Elapsed += (sender, e) => SubmitProfile();
+
+ // auto-sort
+ cB_Profiles.Items.SortDescriptions.Add(new SortDescription(string.Empty, ListSortDirection.Descending));
+
+ // force call
+ RTSS_Updated(PlatformManager.RTSS.Status);
}
- public ProfilesPage(string Tag) : this()
+ private void SystemManager_Initialized()
{
- this.Tag = Tag;
+ bool HasScalingModeSupport = ADLXWrapper.HasScalingModeSupport();
+ bool HasIntegerScalingSupport = ADLXWrapper.HasIntegerScalingSupport();
+ bool HasRSRSupport = ADLXWrapper.HasRSRSupport();
+ bool HasGPUScalingSupport = ADLXWrapper.HasGPUScalingSupport();
+ bool IsGPUScalingEnabled = ADLXWrapper.GetGPUScaling();
- ProfileManager.Deleted += ProfileDeleted;
- ProfileManager.Updated += ProfileUpdated;
- ProfileManager.Applied += ProfileApplied;
-
- PowerProfileManager.Updated += PowerProfileManager_Updated;
- PowerProfileManager.Deleted += PowerProfileManager_Deleted;
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ StackProfileRSR.IsEnabled = HasGPUScalingSupport && IsGPUScalingEnabled && HasRSRSupport;
+ StackProfileIS.IsEnabled = HasGPUScalingSupport && IsGPUScalingEnabled && HasIntegerScalingSupport;
+ GPUScalingToggle.IsEnabled = HasGPUScalingSupport;
+ GPUScalingComboBox.IsEnabled = HasGPUScalingSupport && HasScalingModeSupport;
- ProfileManager.Initialized += ProfileManagerLoaded;
+ DesktopScreen desktopScreen = SystemManager.GetDesktopScreen();
+ desktopScreen.screenDividers.ForEach(d => IntegerScalingComboBox.Items.Add(d));
+ });
+ }
- SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ private void SystemManager_StateChanged_RSR(bool Supported, bool Enabled, int Sharpness)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ using (new ScopedLock(updateLock))
+ {
+ StackProfileRSR.IsEnabled = Supported;
+ }
+ });
+ }
- SystemManager.DisplaySettingsChanged += SystemManager_DisplaySettingsChanged;
- SystemManager.RSRStateChanged += SystemManager_RSRStateChanged;
+ private void SystemManager_StateChanged_GPUScaling(bool Supported, bool Enabled, int Mode)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(async () =>
+ {
+ using (new ScopedLock(updateLock))
+ {
+ GPUScalingToggle.IsEnabled = Supported;
+ StackProfileRIS.IsEnabled = Supported; // check if processor is AMD should be enough
+ StackProfileRSR.IsEnabled = Supported;
+ StackProfileIS.IsEnabled = Supported;
+ }
+ });
+ }
- // auto-sort
- cB_Profiles.Items.SortDescriptions.Add(new SortDescription(string.Empty, ListSortDirection.Descending));
+ private void SystemManager_StateChanged_IntegerScaling(bool Supported, bool Enabled)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ using (new ScopedLock(updateLock))
+ {
+ StackProfileIS.IsEnabled = Supported;
+ }
+ });
}
- private void SystemManager_RSRStateChanged(int RSRState, int RSRSharpness)
+ private void RTSS_Updated(PlatformStatus status)
{
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- switch (RSRState)
+ switch (status)
{
- case -1:
- RSRToggle.IsEnabled = false;
+ case PlatformStatus.Ready:
+ var Processor = PerformanceManager.GetProcessor();
+ StackProfileFramerate.IsEnabled = true;
break;
- case 0:
- RSRToggle.IsEnabled = true;
- RSRToggle.IsOn = false;
- RSRSlider.Value = RSRSharpness;
- break;
- case 1:
- RSRToggle.IsEnabled = true;
- RSRToggle.IsOn = true;
- RSRSlider.Value = RSRSharpness;
+ case PlatformStatus.Stalled:
+ // StackProfileFramerate.IsEnabled = false;
+ // StackProfileAutoTDP.IsEnabled = false;
break;
}
});
@@ -103,17 +167,19 @@ public void SettingsManager_SettingValueChanged(string name, object value)
});
}
- private void SystemManager_DisplaySettingsChanged(ScreenResolution resolution)
+ private void SystemManager_PrimaryScreenChanged(DesktopScreen desktopScreen)
{
+ List frameLimits = desktopScreen.GetFramelimits();
+
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- var screenFrequency = SystemManager.GetDesktopScreen().GetFrequency();
+ cB_Framerate.Items.Clear();
+
+ foreach (ScreenFramelimit frameLimit in frameLimits)
+ cB_Framerate.Items.Add(frameLimit);
- FramerateQuarter.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Quarter));
- FramerateThird.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Third));
- FramerateHalf.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Half));
- FramerateFull.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Full));
+ cB_Framerate.SelectedItem = desktopScreen.GetClosest(selectedProfile.FramerateValue);
});
}
@@ -403,23 +469,15 @@ private void cB_Profiles_SelectionChanged(object sender, SelectionChangedEventAr
if (cB_Profiles.SelectedItem is null)
return;
- // if an update is pending, cut it short, it will disturb profile selection though
- if (UpdateTimer.Enabled)
- {
- UpdateTimer.Stop();
- SubmitProfile();
- }
-
- selectedProfile = (Profile)cB_Profiles.SelectedItem;
-
- UpdateUI();
+ selectedMainProfile = (Profile)cB_Profiles.SelectedItem;
+ UpdateSubProfiles();
}
private void UpdateMotionControlsVisibility()
{
bool MotionMapped = false;
if (selectedProfile.Layout.GyroLayout.TryGetValue(AxisLayoutFlags.Gyroscope, out IActions action))
- if (action is not null && action.ActionType != ActionType.Disabled)
+ if (action is not null && action.actionType != ActionType.Disabled)
MotionMapped = true;
// UI thread (async)
@@ -429,6 +487,7 @@ private void UpdateMotionControlsVisibility()
});
}
+ private DesktopScreen desktopScreen;
private void UpdateUI()
{
if (selectedProfile is null)
@@ -439,19 +498,36 @@ private void UpdateUI()
{
using (new ScopedLock(updateLock))
{
- // disable delete button if is default profile or running
- b_DeleteProfile.IsEnabled = !selectedProfile.ErrorCode.HasFlag(ProfileErrorCode.Default & ProfileErrorCode.Running);
+ // disable delete button if is default profile or any sub profile is running
+ b_DeleteProfile.IsEnabled = !selectedProfile.ErrorCode.HasFlag(ProfileErrorCode.Default & ProfileErrorCode.Running); //TODO consider sub profiles pertaining to this main profile is running
// prevent user from renaming default profile
- tB_ProfileName.IsEnabled = !selectedProfile.Default;
+ b_ProfileRename.IsEnabled = !selectedMainProfile.Default;
// prevent user from disabling default profile
Toggle_EnableProfile.IsEnabled = !selectedProfile.Default;
// prevent user from disabling default profile layout
Toggle_ControllerLayout.IsEnabled = !selectedProfile.Default;
// prevent user from using Wrapper on default profile
cB_Wrapper.IsEnabled = !selectedProfile.Default;
+ UseFullscreenOptimizations.IsEnabled = !selectedProfile.Default;
+ UseHighDPIAwareness.IsEnabled = !selectedProfile.Default;
+
+ // sub profiles
+ b_SubProfileCreate.IsEnabled = !selectedMainProfile.Default;
+
+ // enable delete and rename if not default sub profile
+ if (cb_SubProfilePicker.SelectedIndex == 0) // main profile
+ {
+ b_SubProfileDelete.IsEnabled = false;
+ b_SubProfileRename.IsEnabled = false;
+ }
+ else // actual sub profile
+ {
+ b_SubProfileDelete.IsEnabled = true;
+ b_SubProfileRename.IsEnabled = true;
+ }
// Profile info
- tB_ProfileName.Text = selectedProfile.Name;
+ tB_ProfileName.Text = selectedMainProfile.Name;
tB_ProfilePath.Text = selectedProfile.Path;
Toggle_EnableProfile.IsOn = selectedProfile.Enabled;
@@ -483,13 +559,32 @@ private void UpdateUI()
UpdateMotionControlsVisibility();
+ // Framerate limit
+ desktopScreen = SystemManager.GetDesktopScreen();
+ if (desktopScreen is not null)
+ cB_Framerate.SelectedItem = desktopScreen.GetClosest(selectedProfile.FramerateValue);
+
+ // GPU Scaling
+ GPUScalingToggle.IsOn = selectedProfile.GPUScaling;
+ GPUScalingComboBox.SelectedIndex = selectedProfile.ScalingMode;
+
// RSR
RSRToggle.IsOn = selectedProfile.RSREnabled;
RSRSlider.Value = selectedProfile.RSRSharpness;
- // Framerate limit
- FramerateToggle.IsOn = selectedProfile.FramerateEnabled;
- FramerateSlider.Value = selectedProfile.FramerateValue;
+ // Integer Scaling
+ IntegerScalingToggle.IsOn = selectedProfile.IntegerScalingEnabled;
+
+ if (desktopScreen is not null)
+ IntegerScalingComboBox.SelectedItem = desktopScreen.screenDividers.FirstOrDefault(d => d.divider == selectedProfile.IntegerScalingDivider);
+
+ // RIS
+ RISToggle.IsOn = selectedProfile.RISEnabled;
+ RISSlider.Value = selectedProfile.RISSharpness;
+
+ // Compatibility settings
+ UseFullscreenOptimizations.IsOn = selectedProfile.FullScreenOptimization;
+ UseHighDPIAwareness.IsOn = selectedProfile.HighDPIAware;
// Layout settings
Toggle_ControllerLayout.IsOn = selectedProfile.LayoutEnabled;
@@ -535,17 +630,55 @@ private void UpdateUI()
cB_Wrapper_Redirection.IsEnabled = false;
break;
}
+
+ // update dropdown lists
+ cB_Profiles.Items.Refresh();
+ cb_SubProfilePicker.Items.Refresh();
}
});
}
+ private void UpdateSubProfiles()
+ {
+ if (selectedMainProfile is null)
+ return;
+
+ var ind = 0; // default or main profile itself
+
+ // add main profile as first subprofile
+ cb_SubProfilePicker.Items.Clear();
+ cb_SubProfilePicker.Items.Add(selectedMainProfile);
+
+ // if main profile is not default, occupy sub profiles dropdown list
+ if (!selectedMainProfile.Default)
+ {
+ foreach (Profile subprofile in ProfileManager.GetSubProfilesFromPath(selectedMainProfile.Path, false))
+ {
+ cb_SubProfilePicker.Items.Add(subprofile);
+
+ // select sub profile if it's favorite for main profile
+ if (subprofile.IsFavoriteSubProfile)
+ ind = cb_SubProfilePicker.Items.IndexOf(subprofile);
+ }
+ }
+
+ // refresh sub profiles dropdown
+ cb_SubProfilePicker.Items.Refresh();
+
+ // set subprofile to be applied
+ cb_SubProfilePicker.SelectedIndex = ind;
+
+ // update UI elements
+ UpdateUI();
+ }
+
private async void b_DeleteProfile_Click(object sender, RoutedEventArgs e)
{
if (selectedProfile is null)
return;
var result = Dialog.ShowAsync(
- $"{Properties.Resources.ProfilesPage_AreYouSureDelete1} \"{selectedProfile.Name}\"?",
+ $"{Properties.Resources.ProfilesPage_AreYouSureDelete1} \"{selectedMainProfile.Name}\"?",
$"{Properties.Resources.ProfilesPage_AreYouSureDelete2}",
ContentDialogButton.Primary,
$"{Properties.Resources.ProfilesPage_Cancel}",
@@ -555,7 +688,7 @@ private async void b_DeleteProfile_Click(object sender, RoutedEventArgs e)
switch (result.Result)
{
case ContentDialogResult.Primary:
- ProfileManager.DeleteProfile(selectedProfile);
+ ProfileManager.DeleteProfile(selectedMainProfile);
cB_Profiles.SelectedIndex = 0;
break;
}
@@ -613,65 +746,6 @@ private void Toggle_EnableProfile_Toggled(object sender, RoutedEventArgs e)
UpdateProfile();
}
- private void FramerateToggle_Toggled(object sender, RoutedEventArgs e)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- if (FramerateToggle.IsOn)
- {
- FramerateSlider_ValueChanged(null, null);
- }
- else
- {
- foreach (Control control in FramerateModeGrid.Children)
- {
- if (control is not Label)
- continue;
-
- control.SetResourceReference(Control.ForegroundProperty, "SystemControlForegroundBaseMediumBrush");
- }
- }
- });
-
- // wait until lock is released
- if (updateLock)
- return;
-
- selectedProfile.FramerateEnabled = FramerateToggle.IsOn;
- UpdateProfile();
- }
-
- private void FramerateSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- var value = (int)FramerateSlider.Value;
-
- foreach (Control control in FramerateModeGrid.Children)
- {
- if (control is not Label)
- continue;
-
- control.SetResourceReference(Control.ForegroundProperty, "SystemControlForegroundBaseMediumBrush");
- }
-
- Label label = (Label)FramerateModeGrid.Children[value];
- label.SetResourceReference(Control.ForegroundProperty, "AccentButtonBackground");
- });
-
- if (!FramerateSlider.IsInitialized)
- return;
-
- // wait until lock is released
- if (updateLock)
- return;
-
- selectedProfile.FramerateValue = (int)FramerateSlider.Value;
- UpdateProfile();
- }
-
private void ControllerSettingsButton_Click(object sender, RoutedEventArgs e)
{
// prepare layout editor
@@ -715,28 +789,56 @@ private void ProfileApplied(Profile profile, UpdateSource source)
public void ProfileUpdated(Profile profile, UpdateSource source, bool isCurrent)
{
+ // self call - update ui and return
+ switch (source)
+ {
+ case UpdateSource.ProfilesPage:
+ case UpdateSource.ProfilesPageUpdateOnly:
+ return;
+ case UpdateSource.QuickProfilesPage:
+ {
+ isCurrent = selectedProfile.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase);
+ if (!isCurrent) return;
+ }
+ break;
+ }
+
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
var idx = -1;
- foreach (Profile pr in cB_Profiles.Items)
+ if (!profile.IsSubProfile && cb_SubProfilePicker.Items.IndexOf(profile) != 0)
{
- var isCurrent = pr.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase);
- if (isCurrent)
+ foreach (Profile pr in cB_Profiles.Items)
{
- idx = cB_Profiles.Items.IndexOf(pr);
- break;
+ bool isCurrent = pr.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase);
+ if (isCurrent)
+ {
+ idx = cB_Profiles.Items.IndexOf(pr);
+ break;
+ }
}
+
+ if (idx != -1)
+ cB_Profiles.Items[idx] = profile;
+ else
+ cB_Profiles.Items.Add(profile);
+
+ cB_Profiles.Items.Refresh();
+
+ cB_Profiles.SelectedItem = profile;
}
- if (idx != -1)
- cB_Profiles.Items[idx] = profile;
- else
- cB_Profiles.Items.Add(profile);
+ else if (!profile.IsFavoriteSubProfile)
+ cB_Profiles.SelectedItem = profile;
- cB_Profiles.Items.Refresh();
+ else // TODO updateUI to show main & sub profile selected
+ {
+ Profile mainProfile = ProfileManager.GetProfileForSubProfile(profile);
+ cB_Profiles.SelectedItem = mainProfile;
+ }
- cB_Profiles.SelectedItem = profile;
+ UpdateSubProfiles(); // TODO check
});
}
@@ -745,18 +847,42 @@ public void ProfileDeleted(Profile profile)
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- var idx = -1;
- foreach (Profile pr in cB_Profiles.Items)
+ if (!profile.IsSubProfile)
{
- var isCurrent = pr.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase);
- if (isCurrent)
+ // Profiles
+ var idx = -1;
+ foreach (Profile pr in cB_Profiles.Items)
{
- idx = cB_Profiles.Items.IndexOf(pr);
- break;
+ var isCurrent = pr.Path.Equals(profile.Path, StringComparison.InvariantCultureIgnoreCase);
+ if (isCurrent)
+ {
+ idx = cB_Profiles.Items.IndexOf(pr);
+ break;
+ }
}
+
+ cB_Profiles.Items.RemoveAt(idx);
}
+ else
+ {
+ var idx = -1;
+ foreach (Profile pr in cb_SubProfilePicker.Items)
+ {
+ // sub profiles
+ var isCurrent = profile.Guid == pr.Guid;
+ if (isCurrent)
+ {
+ idx = cb_SubProfilePicker.Items.IndexOf(pr);
+ break;
+ }
+ }
- cB_Profiles.Items.RemoveAt(idx);
+ if (idx == -1)
+ return;
+
+ cb_SubProfilePicker.Items.RemoveAt(idx);
+ cb_SubProfilePicker.SelectedIndex = 0;
+ }
});
}
@@ -768,16 +894,6 @@ private void ProfileManagerLoaded()
#endregion
- private void tB_ProfileName_TextChanged(object sender, TextChangedEventArgs e)
- {
- // wait until lock is released
- if (updateLock)
- return;
-
- selectedProfile.Name = tB_ProfileName.Text;
- UpdateProfile();
- }
-
private void tb_ProfileGyroValue_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
if (!tb_ProfileGyroValue.IsInitialized)
@@ -869,22 +985,38 @@ public void SubmitProfile(UpdateSource source = UpdateSource.ProfilesPage)
{
if (selectedProfile is null)
return;
+
+ LogManager.LogInformation($"Submitting profile in ProfilesPage: {selectedProfile} - is Sub Profile? {selectedProfile.IsSubProfile}");
- ProfileManager.UpdateOrCreateProfile(selectedProfile, source);
+ switch (source)
+ {
+ case UpdateSource.ProfilesPageUpdateOnly: // when renaming main profile, update main profile only but don't apply it
+ ProfileManager.UpdateOrCreateProfile(selectedMainProfile, source);
+ break;
+ default:
+ ProfileManager.UpdateOrCreateProfile(selectedProfile, source);
+ break;
+ }
}
private void RSRToggle_Toggled(object sender, RoutedEventArgs e)
{
+ if (selectedProfile is null)
+ return;
+
// wait until lock is released
if (updateLock)
return;
- selectedProfile.RSREnabled = RSRToggle.IsOn;
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.RadeonSuperResolution, RSRToggle.IsOn);
UpdateProfile();
}
private void RSRSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
+ if (selectedProfile is null)
+ return;
+
if (!RSRSlider.IsInitialized)
return;
@@ -896,6 +1028,104 @@ private void RSRSlider_ValueChanged(object sender, RoutedPropertyChangedEventArg
UpdateProfile();
}
+ private void RISToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.RadeonImageSharpening, RISToggle.IsOn);
+ UpdateProfile();
+ }
+
+ private void RISSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ if (!RISSlider.IsInitialized)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ selectedProfile.RISSharpness = (int)RISSlider.Value;
+ UpdateProfile();
+ }
+
+ private void IntegerScalingToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.IntegerScaling, IntegerScalingToggle.IsOn);
+ UpdateProfile();
+ }
+
+ private void IntegerScalingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (IntegerScalingComboBox.SelectedIndex == -1 || selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ var divider = 1;
+ if (IntegerScalingComboBox.SelectedItem is ScreenDivider screenDivider)
+ {
+ divider = screenDivider.divider;
+ }
+
+ selectedProfile.IntegerScalingDivider = divider;
+ UpdateProfile();
+ }
+
+ private void GPUScalingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (GPUScalingComboBox.SelectedIndex == -1 || selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ int selectedIndex = GPUScalingComboBox.SelectedIndex;
+ // RSR does not work with ScalingMode.Center
+ if (selectedProfile.RSREnabled && selectedIndex == 2)
+ {
+ selectedProfile.ScalingMode = 1;
+ GPUScalingComboBox.SelectedIndex = 1;
+ }
+ else
+ {
+ selectedProfile.ScalingMode = GPUScalingComboBox.SelectedIndex;
+ }
+
+ UpdateProfile();
+ }
+
+ private void GPUScaling_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.GPUScaling, GPUScalingToggle.IsOn);
+ UpdateProfile();
+ }
+
private void cB_EmulatedController_Changed(object sender, SelectionChangedEventArgs e)
{
// wait until lock is released
@@ -916,4 +1146,238 @@ private void cB_EmulatedController_Changed(object sender, SelectionChangedEventA
UpdateProfile();
}
+ private void cb_SubProfilePicker_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ if (cb_SubProfilePicker.SelectedIndex == -1)
+ return;
+
+ LogManager.LogInformation($"Subprofile changed in ProfilesPage - ind: {cb_SubProfilePicker.SelectedIndex} - {cb_SubProfilePicker.SelectedItem}");
+
+ // selected sub profile
+ if (selectedProfile != cb_SubProfilePicker.SelectedItem)
+ {
+ selectedProfile = (Profile)cb_SubProfilePicker.SelectedItem;
+ UpdateProfile();
+ }
+
+ UpdateUI();
+ }
+
+ private void b_SubProfileCreate_Click(object sender, RoutedEventArgs e)
+ {
+ // create a new sub profile matching the original profile's settings
+ Profile newSubProfile = (Profile)selectedProfile.Clone();
+ newSubProfile.Name = "(New Sub Profile)";
+ newSubProfile.Guid = Guid.NewGuid(); // must be unique
+ newSubProfile.IsSubProfile = true;
+ newSubProfile.IsFavoriteSubProfile = true;
+ ProfileManager.UpdateOrCreateProfile(newSubProfile);
+ UpdateSubProfiles();
+ }
+
+ private async void b_SubProfileDelete_Click(object sender, RoutedEventArgs e)
+ {
+ // return if original profile or nothing is selected
+ if (cb_SubProfilePicker.SelectedIndex <= 0)
+ return;
+
+ // get selected subprofile from dropdown
+ Profile subProfile = (Profile)cb_SubProfilePicker.SelectedItem;
+
+ // user confirmation
+ var result = Dialog.ShowAsync(
+ $"{Properties.Resources.ProfilesPage_AreYouSureDelete1} \"{subProfile.Name}\"?",
+ $"{Properties.Resources.ProfilesPage_AreYouSureDelete2}",
+ ContentDialogButton.Primary,
+ $"{Properties.Resources.ProfilesPage_Cancel}",
+ $"{Properties.Resources.ProfilesPage_Delete}");
+ await result; // sync call
+
+ // delete sub profile if confirmed
+ switch (result.Result)
+ {
+ case ContentDialogResult.Primary:
+ ProfileManager.DeleteSubProfile(subProfile);
+ break;
+ }
+ }
+
+ private void b_SubProfileRename_Click(object sender, RoutedEventArgs e)
+ {
+ tb_SubProfileName.Text = selectedProfile.Name;
+ SubProfileRenameDialog.ShowAsync();
+ }
+
+ private void SubProfileRenameDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // update subprofile name
+ selectedProfile.Name = tb_SubProfileName.Text;
+
+ // serialize subprofile
+ SubmitProfile();
+
+ UpdateSubProfiles();
+ }
+
+ private void SubProfileRenameDialog_CloseButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ // restore subprofile rename dialog
+ tb_SubProfileName.Text = selectedProfile.Name;
+ }
+
+ private void ProfileRenameDialog_CloseButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ // restore profile name textbox
+ tB_ProfileName.Text = selectedMainProfile.Name;
+ }
+
+ private void ProfileRenameDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
+ {
+ // change main profile name
+ selectedMainProfile.Name = tB_ProfileName.Text;
+
+ // change it in
+ int ind = cB_Profiles.Items.IndexOf(selectedMainProfile);
+ cB_Profiles.Items[ind] = selectedMainProfile;
+ cB_Profiles.Items.Refresh();
+ cB_Profiles.SelectedIndex = ind;
+
+ SubmitProfile(UpdateSource.ProfilesPageUpdateOnly);
+ }
+
+ private void b_ProfileRename_Click(object sender, RoutedEventArgs e)
+ {
+ tB_ProfileName.Text = selectedMainProfile.Name;
+ ProfileRenameDialog.ShowAsync();
+ }
+
+ private void cB_Framerate_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ // return if combobox selected item is null
+ if (cB_Framerate.SelectedIndex == -1)
+ return;
+
+ if (cB_Framerate.SelectedItem is ScreenFramelimit screenFramelimit)
+ {
+ selectedProfile.FramerateValue = screenFramelimit.limit;
+ UpdateProfile();
+ }
+ }
+
+ private enum UpdateGraphicsSettingsSource
+ {
+ GPUScaling,
+ RadeonSuperResolution,
+ RadeonImageSharpening,
+ IntegerScaling
+ }
+
+ private void UpdateGraphicsSettings(UpdateGraphicsSettingsSource source, bool isEnabled)
+ {
+ using (new ScopedLock(updateLock))
+ {
+ switch (source)
+ {
+ case UpdateGraphicsSettingsSource.GPUScaling:
+ {
+ selectedProfile.GPUScaling = isEnabled;
+ if (!isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+ selectedProfile.IntegerScalingEnabled = false;
+
+ RSRToggle.IsOn = false;
+ IntegerScalingToggle.IsOn = false;
+ }
+ }
+ break;
+ // RSR is incompatible with RIS and IS
+ case UpdateGraphicsSettingsSource.RadeonSuperResolution:
+ {
+ selectedProfile.RSREnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RISEnabled = false;
+ selectedProfile.IntegerScalingEnabled = false;
+
+ RISToggle.IsOn = false;
+ IntegerScalingToggle.IsOn = false;
+
+ // RSR does not support ScalingMode.Center
+ if (selectedProfile.ScalingMode == 2)
+ {
+ selectedProfile.ScalingMode = 1;
+ GPUScalingComboBox.SelectedIndex = 1;
+ }
+ }
+ }
+ break;
+ // Image Sharpening is incompatible with RSR
+ case UpdateGraphicsSettingsSource.RadeonImageSharpening:
+ {
+ selectedProfile.RISEnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+
+ RSRToggle.IsOn = false;
+ }
+ }
+ break;
+
+ // Integer Scaling is incompatible with RSR
+ case UpdateGraphicsSettingsSource.IntegerScaling:
+ {
+ selectedProfile.IntegerScalingEnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+
+ RSRToggle.IsOn = false;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ private void UseFullscreenOptimizations_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ selectedProfile.FullScreenOptimization = UseFullscreenOptimizations.IsOn;
+ UpdateProfile();
+ }
+
+ private void UseHighDPIAwareness_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ selectedProfile.HighDPIAware = UseHighDPIAwareness.IsOn;
+ UpdateProfile();
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Pages/SettingsPage.xaml b/HandheldCompanion/Views/Pages/SettingsPage.xaml
index b89085817..fe2a35f9f 100644
--- a/HandheldCompanion/Views/Pages/SettingsPage.xaml
+++ b/HandheldCompanion/Views/Pages/SettingsPage.xaml
@@ -463,10 +463,8 @@
Margin="12,0,0,0"
HorizontalAlignment="Stretch"
SelectionChanged="cB_QuicktoolsPosition_SelectionChanged">
-
-
-
-
+
+
@@ -833,44 +831,6 @@
Toggled="Toggle_RTSS_Toggled" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs b/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
index 435b84cca..8ec67e7dd 100644
--- a/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
+++ b/HandheldCompanion/Views/Pages/SettingsPage.xaml.cs
@@ -4,9 +4,10 @@
using HandheldCompanion.Managers.Desktop;
using HandheldCompanion.Misc;
using HandheldCompanion.Platforms;
-using Inkore.UI.WPF.Modern;
-using Inkore.UI.WPF.Modern.Controls;
-using Inkore.UI.WPF.Modern.Controls.Primitives;
+using iNKORE.UI.WPF.Modern;
+using iNKORE.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls.Helpers;
+using iNKORE.UI.WPF.Modern.Helpers.Styles;
using Nefarius.Utilities.DeviceManagement.PnP;
using System;
using System.Collections.Generic;
@@ -46,17 +47,15 @@ public SettingsPage()
UpdateDevice();
// initialize manager(s)
- MainWindow.updateManager.Updated += UpdateManager_Updated;
+ UpdateManager.Updated += UpdateManager_Updated;
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
ControllerManager.ControllerSelected += ControllerManager_ControllerSelected;
PlatformManager.RTSS.Updated += RTSS_Updated;
- PlatformManager.HWiNFO.Updated += HWiNFO_Updated;
// force call
// todo: make PlatformManager static
RTSS_Updated(PlatformManager.RTSS.Status);
- HWiNFO_Updated(PlatformManager.HWiNFO.Status);
}
public SettingsPage(string? Tag) : this()
@@ -73,23 +72,6 @@ private void ControllerManager_ControllerSelected(IController Controller)
});
}
- private void HWiNFO_Updated(PlatformStatus status)
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- switch (status)
- {
- case PlatformStatus.Ready:
- Toggle_HWiNFO.IsEnabled = true;
- break;
- case PlatformStatus.Stalled:
- Toggle_HWiNFO.IsOn = false;
- break;
- }
- });
- }
-
private void RTSS_Updated(PlatformStatus status)
{
// UI thread (async)
@@ -226,10 +208,6 @@ private void SettingsManager_SettingValueChanged(string? name, object value)
case "PlatformRTSSEnabled":
Toggle_RTSS.IsOn = Convert.ToBoolean(value);
break;
- case "PlatformHWiNFOEnabled":
- Toggle_HWiNFO.IsOn = Convert.ToBoolean(value);
- break;
-
case "QuickToolsLocation":
cB_QuicktoolsPosition.SelectedIndex = Convert.ToInt32(value);
break;
@@ -252,7 +230,7 @@ public void UpdateDevice(PnPDevice device = null)
private void Page_Loaded(object? sender, RoutedEventArgs? e)
{
- MainWindow.updateManager.Start();
+ UpdateManager.Start();
}
public void Page_Closed()
@@ -323,7 +301,7 @@ private void UpdateManager_Updated(UpdateStatus status, UpdateFile updateFile, o
{
LabelUpdate.Text = Properties.Resources.SettingsPage_UpToDate;
LabelUpdateDate.Text = Properties.Resources.SettingsPage_LastChecked +
- MainWindow.updateManager.GetTime();
+ UpdateManager.GetTime();
LabelUpdateDate.Visibility = Visibility.Visible;
GridUpdateSymbol.Visibility = Visibility.Visible;
@@ -358,13 +336,13 @@ private void UpdateManager_Updated(UpdateStatus status, UpdateFile updateFile, o
// Set download button action
update.updateDownload.Click += (sender, e) =>
{
- MainWindow.updateManager.DownloadUpdateFile(update);
+ UpdateManager.DownloadUpdateFile(update);
};
// Set button action
update.updateInstall.Click += (sender, e) =>
{
- MainWindow.updateManager.InstallUpdate(update);
+ UpdateManager.InstallUpdate(update);
};
CurrentUpdates.Children.Add(border);
@@ -408,7 +386,7 @@ private void UpdateManager_Updated(UpdateStatus status, UpdateFile updateFile, o
private void B_CheckUpdate_Click(object? sender, RoutedEventArgs? e)
{
- new Thread(() => { MainWindow.updateManager.StartProcess(); }).Start();
+ new Thread(() => { UpdateManager.StartProcess(); }).Start();
}
private void cB_Language_SelectionChanged(object? sender, SelectionChangedEventArgs? e)
@@ -577,14 +555,6 @@ private void Toggle_RTSS_Toggled(object sender, RoutedEventArgs e)
SettingsManager.SetProperty("PlatformRTSSEnabled", Toggle_RTSS.IsOn);
}
- private void Toggle_HWiNFO_Toggled(object sender, RoutedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- SettingsManager.SetProperty("PlatformHWiNFOEnabled", Toggle_HWiNFO.IsOn);
- }
-
private void cB_QuicktoolsPosition_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (!IsLoaded)
diff --git a/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml b/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml
index b12e6427f..8c4d2a828 100644
--- a/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml
+++ b/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml
@@ -15,65 +15,285 @@
KeepAlive="True"
mc:Ignorable="d">
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+ Glyph="" />
-
+ VerticalAlignment="Center"
+ Style="{StaticResource BodyTextBlockStyle}"
+ Text="Wifi" />
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml.cs
index 81167047d..f08808f74 100644
--- a/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml.cs
+++ b/HandheldCompanion/Views/QuickPages/QuickDevicePage.xaml.cs
@@ -1,10 +1,17 @@
using HandheldCompanion.Devices;
using HandheldCompanion.Managers;
-using HandheldCompanion.Platforms;
-using Inkore.UI.WPF.Modern.Controls;
+using HandheldCompanion.Managers.Desktop;
+using HandheldCompanion.Misc;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Timers;
using System.Windows;
using System.Windows.Controls;
+using Windows.Devices.Bluetooth;
+using Windows.Devices.Radios;
using Page = System.Windows.Controls.Page;
namespace HandheldCompanion.Views.QuickPages;
@@ -14,83 +21,240 @@ namespace HandheldCompanion.Views.QuickPages;
///
public partial class QuickDevicePage : Page
{
- public QuickDevicePage(string Tag) : this()
- {
- this.Tag = Tag;
- }
+ private IReadOnlyList radios;
+ private Timer radioTimer;
public QuickDevicePage()
{
InitializeComponent();
- FullFanSpeedToggler.Visibility = MainWindow.CurrentDevice is LegionGo ? Visibility.Visible : Visibility.Collapsed;
+ SystemManager.PrimaryScreenChanged += DesktopManager_PrimaryScreenChanged;
+ SystemManager.DisplaySettingsChanged += DesktopManager_DisplaySettingsChanged;
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ ProfileManager.Applied += ProfileManager_Applied;
+ ProfileManager.Discarded += ProfileManager_Discarded;
+
+ LegionGoPanel.Visibility = MainWindow.CurrentDevice is LegionGo ? Visibility.Visible : Visibility.Collapsed;
+ DynamicLightingPanel.IsEnabled = MainWindow.CurrentDevice.Capabilities.HasFlag(DeviceCapabilities.DynamicLighting);
+
+ NightLightToggle.IsEnabled = NightLight.Supported;
+ NightLightToggle.IsOn = NightLight.Enabled;
- PlatformManager.RTSS.Updated += RTSS_Updated;
- PlatformManager.HWiNFO.Updated += HWiNFO_Updated;
+ // manage events
+ NightLight.Toggled += NightLight_Toggled;
- // force call
- // todo: make PlatformManager static
- RTSS_Updated(PlatformManager.RTSS.Status);
- HWiNFO_Updated(PlatformManager.HWiNFO.Status);
+ radioTimer = new(1000);
+ radioTimer.Elapsed += RadioTimer_Elapsed;
+ radioTimer.Start();
}
- private void HWiNFO_Updated(PlatformStatus status)
+ public QuickDevicePage(string Tag) : this()
{
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
+ this.Tag = Tag;
+ }
+
+ private void ProfileManager_Applied(Profile profile, UpdateSource source)
+ {
+ // Go to profile integer scaling resolution
+ if (profile.IntegerScalingEnabled)
{
- switch (status)
+ DesktopScreen desktopScreen = SystemManager.GetDesktopScreen();
+ var profileResolution = desktopScreen?.screenDividers.FirstOrDefault(d => d.divider == profile.IntegerScalingDivider);
+ if (profileResolution is not null)
{
- case PlatformStatus.Ready:
- OverlayDisplayLevelExtended.IsEnabled = true;
- OverlayDisplayLevelFull.IsEnabled = true;
- break;
- case PlatformStatus.Stalled:
- // OverlayDisplayLevelExtended.IsEnabled = false;
- // OverlayDisplayLevelFull.IsEnabled = false;
- break;
+ SetResolution(profileResolution.resolution);
}
+ }
+ else
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ // Revert back to resolution in device settings
+ SetResolution();
+ });
+ }
+
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ var canChangeDisplay = !profile.IntegerScalingEnabled;
+ DisplayStack.IsEnabled = canChangeDisplay;
+ ResolutionOverrideStack.Visibility = canChangeDisplay ? Visibility.Collapsed : Visibility.Visible;
+
});
}
- private void RTSS_Updated(PlatformStatus status)
+ private void ProfileManager_Discarded(Profile profile)
{
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- switch (status)
+ SetResolution();
+
+ if (profile.IntegerScalingEnabled)
{
- case PlatformStatus.Ready:
- ComboBoxOverlayDisplayLevel.IsEnabled = true;
- break;
- case PlatformStatus.Stalled:
- ComboBoxOverlayDisplayLevel.SelectedIndex = 0;
- break;
+ DisplayStack.IsEnabled = true;
+ ResolutionOverrideStack.Visibility = Visibility.Collapsed;
}
});
}
- private void SettingsManager_SettingValueChanged(string name, object value)
+ private void NightLight_Toggled(bool enabled)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ NightLightToggle.IsOn = enabled;
+ });
+ }
+
+ private void SettingsManager_SettingValueChanged(string? name, object value)
{
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
switch (name)
{
- case "OnScreenDisplayLevel":
- ComboBoxOverlayDisplayLevel.SelectedIndex = Convert.ToInt32(value);
+ case "LEDSettingsEnabled":
+ UseDynamicLightingToggle.IsOn = Convert.ToBoolean(value);
break;
}
});
}
- private void ComboBoxOverlayDisplayLevel_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ private void RadioTimer_Elapsed(object? sender, ElapsedEventArgs e)
+ {
+ new Task(async () =>
+ {
+ // Get the Bluetooth adapter
+ BluetoothAdapter adapter = await BluetoothAdapter.GetDefaultAsync();
+
+ // Get the Bluetooth radio
+ radios = await Radio.GetRadiosAsync();
+
+ // UI thread (async)
+ _ = Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ // WIFI
+ WifiToggle.IsEnabled = radios.Where(radio => radio.Kind == RadioKind.WiFi).Any();
+ WifiToggle.IsOn = radios.Where(radio => radio.Kind == RadioKind.WiFi && radio.State == RadioState.On).Any();
+
+ // Bluetooth
+ BluetoothToggle.IsEnabled = radios.Where(radio => radio.Kind == RadioKind.Bluetooth).Any();
+ BluetoothToggle.IsOn = radios.Where(radio => radio.Kind == RadioKind.Bluetooth && radio.State == RadioState.On).Any();
+ });
+ }).Start();
+ }
+
+ private void DesktopManager_PrimaryScreenChanged(DesktopScreen screen)
+ {
+ ComboBoxResolution.Items.Clear();
+ foreach (ScreenResolution resolution in screen.screenResolutions)
+ ComboBoxResolution.Items.Add(resolution);
+ }
+
+ private void DesktopManager_DisplaySettingsChanged(ScreenResolution resolution)
+ {
+ // We don't want to change the combobox when it's changed from profile integer scaling
+ var currentProfile = ProfileManager.GetCurrent();
+ if (ComboBoxResolution.SelectedItem is not null && currentProfile is not null && currentProfile.IntegerScalingEnabled)
+ return;
+
+ ComboBoxResolution.SelectedItem = resolution;
+
+ int screenFrequency = SystemManager.GetDesktopScreen().GetCurrentFrequency();
+ foreach (ComboBoxItem comboBoxItem in ComboBoxFrequency.Items)
+ {
+ if (comboBoxItem.Tag is int frequency)
+ {
+ if (frequency == screenFrequency)
+ {
+ ComboBoxFrequency.SelectedItem = comboBoxItem;
+ break;
+ }
+ }
+ }
+ }
+
+ private void ComboBoxResolution_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (ComboBoxResolution.SelectedItem is null)
+ return;
+
+ ScreenResolution resolution = (ScreenResolution)ComboBoxResolution.SelectedItem;
+ int screenFrequency = SystemManager.GetDesktopScreen().GetCurrentFrequency();
+
+ ComboBoxFrequency.Items.Clear();
+ foreach (int frequency in resolution.Frequencies.Keys)
+ {
+ ComboBoxItem comboBoxItem = new()
+ {
+ Content = $"{frequency} Hz",
+ Tag = frequency,
+ };
+
+ ComboBoxFrequency.Items.Add(comboBoxItem);
+
+ if (frequency == screenFrequency)
+ ComboBoxFrequency.SelectedItem = comboBoxItem;
+ }
+
+ SetResolution();
+ }
+
+ private void ComboBoxFrequency_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (ComboBoxFrequency.SelectedItem is null)
+ return;
+
+ SetResolution();
+ }
+
+ private void SetResolution()
+ {
+ if (ComboBoxResolution.SelectedItem is null)
+ return;
+
+ if (ComboBoxFrequency.SelectedItem is null)
+ return;
+
+ ScreenResolution resolution = (ScreenResolution)ComboBoxResolution.SelectedItem;
+ int frequency = (int)((ComboBoxItem)ComboBoxFrequency.SelectedItem).Tag;
+
+ // update current screen resolution
+ SystemManager.SetResolution(resolution.Width, resolution.Height, frequency, resolution.BitsPerPel);
+ }
+
+ public void SetResolution(ScreenResolution resolution)
+ {
+ // update current screen resolution
+ SystemManager.SetResolution(resolution.Width, resolution.Height, SystemManager.GetDesktopScreen().GetCurrentFrequency(), resolution.BitsPerPel);
+ }
+
+ private void WIFIToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ foreach (Radio radio in radios.Where(r => r.Kind == RadioKind.WiFi))
+ _ = radio.SetStateAsync(WifiToggle.IsOn ? RadioState.On : RadioState.Off);
+ }
+
+ private void BluetoothToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ foreach (Radio radio in radios.Where(r => r.Kind == RadioKind.Bluetooth))
+ _ = radio.SetStateAsync(BluetoothToggle.IsOn ? RadioState.On : RadioState.Off);
+ }
+
+ private void UseDynamicLightingToggle_Toggled(object sender, RoutedEventArgs e)
{
if (!IsLoaded)
return;
- SettingsManager.SetProperty("OnScreenDisplayLevel", ComboBoxOverlayDisplayLevel.SelectedIndex);
+ SettingsManager.SetProperty("LEDSettingsEnabled", UseDynamicLightingToggle.IsOn);
+ }
+
+ internal void Close()
+ {
+ radioTimer.Stop();
}
private void Toggle_cFFanSpeed_Toggled(object sender, RoutedEventArgs e)
@@ -101,4 +265,9 @@ private void Toggle_cFFanSpeed_Toggled(object sender, RoutedEventArgs e)
device.SetFanFullSpeed(toggleSwitch.IsOn);
}
}
+
+ private void NightLightToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ NightLight.Enabled = NightLightToggle.IsOn;
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml b/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml
index ed654d326..dfdbb25c8 100644
--- a/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml
+++ b/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml
@@ -1,268 +1,301 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml.cs
index 49645cd5d..a3d1e5eb2 100644
--- a/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml.cs
+++ b/HandheldCompanion/Views/QuickPages/QuickHomePage.xaml.cs
@@ -1,98 +1,188 @@
-using HandheldCompanion.Managers;
-using HandheldCompanion.Utils;
-using System;
-using System.Windows;
-using System.Windows.Controls;
-using Page = System.Windows.Controls.Page;
-
-namespace HandheldCompanion.Views.QuickPages;
-
-///
-/// Interaction logic for QuickHomePage.xaml
-///
-public partial class QuickHomePage : Page
-{
- private LockObject brightnessLock = new();
- private LockObject volumeLock = new();
-
- public QuickHomePage(string Tag) : this()
- {
- this.Tag = Tag;
-
- SystemManager.VolumeNotification += SystemManager_VolumeNotification;
- SystemManager.BrightnessNotification += SystemManager_BrightnessNotification;
- SystemManager.Initialized += SystemManager_Initialized;
- }
-
- public QuickHomePage()
- {
- InitializeComponent();
- }
-
- private void QuickButton_Click(object sender, RoutedEventArgs e)
- {
- Button button = (Button)sender;
- MainWindow.overlayquickTools.NavView_Navigate(button.Name);
- }
-
- private void SystemManager_Initialized()
- {
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- if (SystemManager.HasBrightnessSupport())
- {
- SliderBrightness.IsEnabled = true;
- SliderBrightness.Value = SystemManager.GetBrightness();
- }
-
- if (SystemManager.HasVolumeSupport())
- {
- SliderVolume.IsEnabled = true;
- SliderVolume.Value = SystemManager.GetVolume();
- }
- });
- }
-
- private void SystemManager_BrightnessNotification(int brightness)
- {
- // UI thread
- Application.Current.Dispatcher.Invoke(() =>
- {
- // wait until lock is released
- if (brightnessLock)
- SliderBrightness.Value = brightness;
- });
- }
-
- private void SystemManager_VolumeNotification(float volume)
- {
- // UI thread
- Application.Current.Dispatcher.Invoke(() =>
- {
- // todo: update volume icon on update
-
- // wait until lock is released
- if (volumeLock)
- SliderVolume.Value = Math.Round(volume);
- });
- }
-
- private void SliderBrightness_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- using (new ScopedLock(brightnessLock))
- SystemManager.SetBrightness(SliderBrightness.Value);
- }
-
- private void SliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- if (!IsLoaded)
- return;
-
- using (new ScopedLock(volumeLock))
- SystemManager.SetVolume(SliderVolume.Value);
- }
-}
\ No newline at end of file
+using HandheldCompanion.Managers;
+using HandheldCompanion.Properties;
+using HandheldCompanion.Utils;
+using System;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using Page = System.Windows.Controls.Page;
+
+namespace HandheldCompanion.Views.QuickPages;
+
+///
+/// Interaction logic for QuickHomePage.xaml
+///
+public partial class QuickHomePage : Page
+{
+ private LockObject brightnessLock = new();
+ private LockObject volumeLock = new();
+
+ public QuickHomePage(string Tag) : this()
+ {
+ this.Tag = Tag;
+
+ HotkeysManager.HotkeyCreated += HotkeysManager_HotkeyCreated;
+ HotkeysManager.HotkeyUpdated += HotkeysManager_HotkeyUpdated;
+
+ SystemManager.VolumeNotification += SystemManager_VolumeNotification;
+ SystemManager.BrightnessNotification += SystemManager_BrightnessNotification;
+ SystemManager.Initialized += SystemManager_Initialized;
+
+ ProfileManager.Applied += ProfileManager_Applied;
+ SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+ }
+
+ public QuickHomePage()
+ {
+ InitializeComponent();
+ }
+
+ private void HotkeysManager_HotkeyUpdated(Hotkey hotkey)
+ {
+ UpdatePins();
+ }
+
+ private void HotkeysManager_HotkeyCreated(Hotkey hotkey)
+ {
+ UpdatePins();
+ }
+
+ private void UpdatePins()
+ {
+ // todo, implement quick hotkey order
+ QuickHotkeys.Children.Clear();
+
+ foreach (var hotkey in HotkeysManager.Hotkeys.Values.Where(item => item.IsPinned))
+ QuickHotkeys.Children.Add(hotkey.GetPin());
+ }
+
+ private void QuickButton_Click(object sender, RoutedEventArgs e)
+ {
+ Button button = (Button)sender;
+ MainWindow.overlayquickTools.NavView_Navigate(button.Name);
+ }
+
+ private void SystemManager_Initialized()
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ if (SystemManager.HasBrightnessSupport())
+ {
+ SliderBrightness.IsEnabled = true;
+ SliderBrightness.Value = SystemManager.GetBrightness();
+ }
+
+ if (SystemManager.HasVolumeSupport())
+ {
+ SliderVolume.IsEnabled = true;
+ SliderVolume.Value = SystemManager.GetVolume();
+ UpdateVolumeIcon((float)SliderVolume.Value);
+ }
+ });
+ }
+
+ private void SystemManager_BrightnessNotification(int brightness)
+ {
+ // UI thread
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ // wait until lock is released
+ if (brightnessLock)
+ return;
+
+ SliderBrightness.Value = brightness;
+ });
+ }
+
+ private void SystemManager_VolumeNotification(float volume)
+ {
+ // UI thread
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ // wait until lock is released
+ if (volumeLock)
+ return;
+
+ UpdateVolumeIcon(volume);
+ SliderVolume.Value = Math.Round(volume);
+ });
+ }
+
+ private void SliderBrightness_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ using (new ScopedLock(brightnessLock))
+ SystemManager.SetBrightness(SliderBrightness.Value);
+ }
+
+ private void SliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ using (new ScopedLock(volumeLock))
+ SystemManager.SetVolume(SliderVolume.Value);
+ }
+
+ private void ProfileManager_Applied(Profile profile, UpdateSource source)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ t_CurrentProfile.Text = profile.ToString();
+ });
+ }
+
+ private void SettingsManager_SettingValueChanged(string name, object value)
+ {
+ string[] onScreenDisplayLevels = {
+ Properties.Resources.OverlayPage_OverlayDisplayLevel_Disabled,
+ Properties.Resources.OverlayPage_OverlayDisplayLevel_Minimal,
+ Properties.Resources.OverlayPage_OverlayDisplayLevel_Extended,
+ Properties.Resources.OverlayPage_OverlayDisplayLevel_Full,
+ Properties.Resources.OverlayPage_OverlayDisplayLevel_External,
+ };
+
+ switch (name)
+ {
+ case "OnScreenDisplayLevel":
+ {
+ var overlayLevel = Convert.ToInt16(value);
+
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ t_CurrentOverlayLevel.Text = onScreenDisplayLevels[overlayLevel];
+ });
+ }
+ break;
+ }
+ }
+
+ private void UpdateVolumeIcon(float volume)
+ {
+ string glyph;
+
+ if (volume == 0)
+ {
+ glyph = "\uE992"; // Mute icon
+ }
+ else if (volume <= 33)
+ {
+ glyph = "\uE993"; // Low volume icon
+ }
+ else if (volume <= 65)
+ {
+ glyph = "\uE994"; // Medium volume icon
+ }
+ else
+ {
+ glyph = "\uE995"; // High volume icon (default)
+ }
+
+ VolumeIcon.Glyph = glyph;
+ }
+}
diff --git a/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml b/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml
new file mode 100644
index 000000000..3b4499326
--- /dev/null
+++ b/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml.cs
new file mode 100644
index 000000000..85eca2e48
--- /dev/null
+++ b/HandheldCompanion/Views/QuickPages/QuickOverlayPage.xaml.cs
@@ -0,0 +1,94 @@
+using HandheldCompanion.Devices;
+using HandheldCompanion.Managers;
+using HandheldCompanion.Platforms;
+using iNKORE.UI.WPF.Modern.Controls;
+using System;
+using System.Windows;
+using System.Windows.Controls;
+using Page = System.Windows.Controls.Page;
+
+namespace HandheldCompanion.Views.QuickPages;
+
+///
+/// Interaction logic for QuickOverlayPage.xaml
+///
+public partial class QuickOverlayPage : Page
+{
+ public QuickOverlayPage(string Tag) : this()
+ {
+ this.Tag = Tag;
+ }
+
+ public QuickOverlayPage()
+ {
+ InitializeComponent();
+
+ SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
+
+ PlatformManager.RTSS.Updated += RTSS_Updated;
+ PlatformManager.LibreHardwareMonitor.Updated += LibreHardwareMonitor_Updated;
+
+ // force call
+ // todo: make PlatformManager static
+ RTSS_Updated(PlatformManager.RTSS.Status);
+ LibreHardwareMonitor_Updated(PlatformManager.LibreHardwareMonitor.Status);
+ }
+
+ private void LibreHardwareMonitor_Updated(PlatformStatus status)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ switch (status)
+ {
+ case PlatformStatus.Ready:
+ OverlayDisplayLevelExtended.IsEnabled = true;
+ OverlayDisplayLevelFull.IsEnabled = true;
+ break;
+ case PlatformStatus.Stalled:
+ // OverlayDisplayLevelExtended.IsEnabled = false;
+ // OverlayDisplayLevelFull.IsEnabled = false;
+ break;
+ }
+ });
+ }
+
+ private void RTSS_Updated(PlatformStatus status)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ switch (status)
+ {
+ case PlatformStatus.Ready:
+ ComboBoxOverlayDisplayLevel.IsEnabled = true;
+ break;
+ case PlatformStatus.Stalled:
+ ComboBoxOverlayDisplayLevel.SelectedIndex = 0;
+ break;
+ }
+ });
+ }
+
+ private void SettingsManager_SettingValueChanged(string name, object value)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ switch (name)
+ {
+ case "OnScreenDisplayLevel":
+ ComboBoxOverlayDisplayLevel.SelectedIndex = Convert.ToInt32(value);
+ break;
+ }
+ });
+ }
+
+ private void ComboBoxOverlayDisplayLevel_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (!IsLoaded)
+ return;
+
+ SettingsManager.SetProperty("OnScreenDisplayLevel", ComboBoxOverlayDisplayLevel.SelectedIndex);
+ }
+}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickPerformancePage.xaml b/HandheldCompanion/Views/QuickPages/QuickPerformancePage.xaml
index c71cc5762..eeb1cb290 100644
--- a/HandheldCompanion/Views/QuickPages/QuickPerformancePage.xaml
+++ b/HandheldCompanion/Views/QuickPages/QuickPerformancePage.xaml
@@ -17,7 +17,7 @@
-
+
@@ -28,14 +28,30 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} Cores, ElementName=CPUCoreSlider, Mode=OneWay}" />
+
+
@@ -93,14 +103,30 @@
Spacing="6">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} W, ElementName=TDPSlider, Mode=OneWay}" />
+
+
@@ -160,14 +180,29 @@
Spacing="6">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} FPS, ElementName=AutoTDPSlider, Mode=OneWay}" />
+
+
@@ -227,16 +251,30 @@
CornerRadius="{DynamicResource ControlCornerRadius}">
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ AutoToolTipPrecision="0"
+ IsMoveToPointEnabled="True"
+ IsSnapToTickEnabled="True"
+ LargeChange="10"
+ Maximum="100"
+ Minimum="0"
+ SmallChange="1"
+ Style="{DynamicResource SliderStyle1}"
+ TickFrequency="10"
+ TickPlacement="BottomRight"
+ ToolTip="{Binding Value, StringFormat=N0, RelativeSource={RelativeSource Self}, Mode=OneWay}"
+ ValueChanged="EPPSlider_ValueChanged" />
+
+
+
+
+
+
+
@@ -306,16 +332,31 @@
CornerRadius="{DynamicResource ControlCornerRadius}">
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} Mhz, ElementName=CPUSlider, Mode=OneWay}" />
+
+
@@ -373,16 +405,31 @@
Name="StackProfileGPUClock"
IsEnabled="False"
Spacing="6">
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} Mhz, ElementName=GPUSlider, Mode=OneWay}" />
+
+
@@ -437,14 +475,30 @@
Background="{DynamicResource ExpanderHeaderBackground}"
CornerRadius="{DynamicResource ControlCornerRadius}">
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
+
+
+
+
+
+
+
+
{
- switch (listener)
- {
- case "increaseTDP":
- {
- if (selectedProfile is null || !selectedProfile.TDPOverrideEnabled)
- return;
-
- TDPSlider.Value++;
- }
- break;
- case "decreaseTDP":
- {
- if (selectedProfile is null || !selectedProfile.TDPOverrideEnabled)
- return;
-
- TDPSlider.Value--;
- }
- break;
- }
+ AutoTDPSlider.Maximum = desktopScreen.devMode.dmDisplayFrequency;
});
}
@@ -130,7 +110,7 @@ private void RTSS_Updated(PlatformStatus status)
switch (status)
{
case PlatformStatus.Ready:
- var Processor = MainWindow.performanceManager.GetProcessor();
+ var Processor = PerformanceManager.GetProcessor();
StackProfileAutoTDP.IsEnabled = true && Processor is not null ? Processor.CanChangeTDP : false;
break;
case PlatformStatus.Stalled:
@@ -181,7 +161,7 @@ private void PerformanceManager_EPPChanged(uint EPP)
private void PerformanceManager_Initialized()
{
- Processor processor = MainWindow.performanceManager.GetProcessor();
+ Processor processor = PerformanceManager.GetProcessor();
if (processor is null)
return;
@@ -281,18 +261,8 @@ private void UpdateUI()
{
using (new ScopedLock(updateLock))
{
- switch (selectedProfile.Default)
- {
- case true:
- // we shouldn't allow users to mess with default profile fan mode
- FanMode.IsEnabled = false;
- break;
- case false:
- FanMode.IsEnabled = true;
- break;
- }
-
// we shouldn't allow users to modify some of default profile settings
+ PowerSettingsPanel.IsEnabled = !selectedProfile.DeviceDefault;
Button_PowerSettings_Delete.IsEnabled = !selectedProfile.Default;
// page name
@@ -315,7 +285,7 @@ private void UpdateUI()
// AutoTDP
AutoTDPToggle.IsOn = selectedProfile.AutoTDPEnabled;
- AutoTDPRequestedFPSSlider.Value = selectedProfile.AutoTDPRequestedFPS;
+ AutoTDPSlider.Value = selectedProfile.AutoTDPRequestedFPS;
// EPP
EPPToggle.IsOn = selectedProfile.EPPOverrideEnabled;
@@ -383,7 +353,7 @@ private void AutoTDPToggle_Toggled(object sender, RoutedEventArgs e)
return;
selectedProfile.AutoTDPEnabled = AutoTDPToggle.IsOn;
- AutoTDPRequestedFPSSlider.Value = selectedProfile.AutoTDPRequestedFPS;
+ AutoTDPSlider.Value = selectedProfile.AutoTDPRequestedFPS;
UpdateProfile();
}
@@ -396,7 +366,7 @@ private void AutoTDPRequestedFPSSlider_ValueChanged(object sender, RoutedPropert
if (updateLock)
return;
- selectedProfile.AutoTDPRequestedFPS = (int)AutoTDPRequestedFPSSlider.Value;
+ selectedProfile.AutoTDPRequestedFPS = (int)AutoTDPSlider.Value;
UpdateProfile();
}
diff --git a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml
index 96e380cd8..abbbedea3 100644
--- a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml
+++ b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml
@@ -9,7 +9,7 @@
Name="QuickProfiles"
Title="{x:Static resx:Resources.QuickProfilesPage_Title}"
Margin="15,0,0,0"
- d:Background="White"
+ d:Background="Black"
d:DesignHeight="1500"
d:DesignWidth="640"
KeepAlive="True"
@@ -99,10 +99,45 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -120,11 +155,11 @@
Glyph="" />
-
+
@@ -143,6 +178,7 @@
+
@@ -168,6 +204,7 @@
+
@@ -188,68 +225,10 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
+
@@ -257,247 +236,315 @@
+
-
-
+ Style="{DynamicResource InvertedToggleSwitchStyle}"
+ Toggled="Toggle_ControllerLayout_Toggled" />
-
+
+
-
+
-
-
+
+
-
+
-
-
-
-
+ SelectionChanged="cB_Output_SelectionChanged" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ SelectionChanged="cB_Input_SelectionChanged" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+ SelectionChanged="cB_UMC_MotionDefaultOffOn_SelectionChanged">
+
+
+
+
+
+
+
+
+
+
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0}, ElementName=SliderUMCAntiDeadzone, Mode=OneWay}" />
+ ToolTip="{Binding Value, StringFormat=N0, RelativeSource={RelativeSource Self}, Mode=OneWay}"
+ ValueChanged="SliderUMCAntiDeadzone_ValueChanged" />
-
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N1}, ElementName=Slider_GyroWeight, Mode=OneWay}" />
+ ValueChanged="Slider_GyroWeight_ValueChanged" />
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
@@ -508,36 +555,94 @@
Glyph="" />
-
+
-
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
@@ -547,136 +652,228 @@
Margin="12,0,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
+ IsEnabled="{Binding ElementName=GPUScalingToggle, Path=IsOn}"
Style="{DynamicResource InvertedToggleSwitchStyle}"
Toggled="RSRToggle_Toggled" />
-
-
+
+
+
+
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} %, ElementName=RSRSlider, Mode=OneWay}" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ SelectionChanged="IntegerScalingComboBox_SelectionChanged" />
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
+
+ Toggled="RISToggle_Toggled" />
+
+
+ Visibility="{Binding ElementName=RISToggle, Path=IsOn, Converter={StaticResource BooleanToVisibilityConverter}}">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ HorizontalContentAlignment="Center"
+ IsReadOnly="True"
+ Text="{Binding Value, StringFormat={}{0:N0} %, ElementName=RISSlider, Mode=OneWay}" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs
index d894d48c7..fb71e0a7e 100644
--- a/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs
+++ b/HandheldCompanion/Views/QuickPages/QuickProfilesPage.xaml.cs
@@ -6,8 +6,9 @@
using HandheldCompanion.Misc;
using HandheldCompanion.Platforms;
using HandheldCompanion.Utils;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
+using System.Collections.Generic;
using System.Linq;
using System.Timers;
using System.Windows;
@@ -42,19 +43,19 @@ public QuickProfilesPage()
{
InitializeComponent();
+ // manage events
ProcessManager.ForegroundChanged += ProcessManager_ForegroundChanged;
-
- ProfileManager.Applied += ProfileApplied;
-
+ ProfileManager.Applied += ProfileManager_Applied;
PowerProfileManager.Updated += PowerProfileManager_Updated;
PowerProfileManager.Deleted += PowerProfileManager_Deleted;
-
- SystemManager.DisplaySettingsChanged += SystemManager_DisplaySettingsChanged;
- SystemManager.RSRStateChanged += SystemManager_RSRStateChanged;
-
+ SystemManager.Initialized += SystemManager_Initialized;
+ SystemManager.PrimaryScreenChanged += SystemManager_PrimaryScreenChanged;
+ SystemManager.StateChanged_RSR += SystemManager_StateChanged_RSR;
+ SystemManager.StateChanged_IntegerScaling += SystemManager_StateChanged_IntegerScaling;
+ SystemManager.StateChanged_GPUScaling += SystemManager_StateChanged_GPUScaling;
HotkeysManager.HotkeyCreated += TriggerCreated;
-
InputsManager.TriggerUpdated += TriggerUpdated;
+ PlatformManager.RTSS.Updated += RTSS_Updated;
foreach (var mode in (MotionOuput[])Enum.GetValues(typeof(MotionOuput)))
{
@@ -160,32 +161,67 @@ public QuickProfilesPage()
UpdateTimer.AutoReset = false;
UpdateTimer.Elapsed += (sender, e) => SubmitProfile();
- PlatformManager.RTSS.Updated += RTSS_Updated;
-
// force call
RTSS_Updated(PlatformManager.RTSS.Status);
}
- private void SystemManager_RSRStateChanged(int RSRState, int RSRSharpness)
+ private void SystemManager_Initialized()
+ {
+ bool HasScalingModeSupport = ADLXWrapper.HasScalingModeSupport();
+ bool HasIntegerScalingSupport = ADLXWrapper.HasIntegerScalingSupport();
+ bool HasRSRSupport = ADLXWrapper.HasRSRSupport();
+ bool HasGPUScalingSupport = ADLXWrapper.HasGPUScalingSupport();
+ bool IsGPUScalingEnabled = ADLXWrapper.GetGPUScaling();
+
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ StackProfileRSR.IsEnabled = HasGPUScalingSupport && IsGPUScalingEnabled && HasRSRSupport;
+ StackProfileIS.IsEnabled = HasGPUScalingSupport && IsGPUScalingEnabled && HasIntegerScalingSupport;
+ StackProfileRIS.IsEnabled = HasGPUScalingSupport; // check if processor is AMD should be enough
+ GPUScalingToggle.IsEnabled = HasGPUScalingSupport;
+ GPUScalingComboBox.IsEnabled = HasGPUScalingSupport && HasScalingModeSupport;
+
+ DesktopScreen desktopScreen = SystemManager.GetDesktopScreen();
+ desktopScreen.screenDividers.ForEach(d => IntegerScalingComboBox.Items.Add(d));
+ });
+ }
+
+ private void SystemManager_StateChanged_RSR(bool Supported, bool Enabled, int Sharpness)
{
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- switch (RSRState)
+ using (new ScopedLock(updateLock))
{
- case -1:
- StackProfileRSR.IsEnabled = false;
- break;
- case 0:
- StackProfileRSR.IsEnabled = true;
- RSRToggle.IsOn = false;
- RSRSlider.Value = RSRSharpness;
- break;
- case 1:
- StackProfileRSR.IsEnabled = true;
- RSRToggle.IsOn = true;
- RSRSlider.Value = RSRSharpness;
- break;
+ StackProfileRSR.IsEnabled = Supported;
+ }
+ });
+ }
+
+ private void SystemManager_StateChanged_GPUScaling(bool Supported, bool Enabled, int Mode)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(async () =>
+ {
+ using (new ScopedLock(updateLock))
+ {
+ GPUScalingToggle.IsEnabled = Supported;
+ StackProfileRIS.IsEnabled = Supported; // check if processor is AMD should be enough
+ StackProfileRSR.IsEnabled = Supported;
+ StackProfileIS.IsEnabled = Supported;
+ }
+ });
+ }
+
+ private void SystemManager_StateChanged_IntegerScaling(bool Supported, bool Enabled)
+ {
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ using (new ScopedLock(updateLock))
+ {
+ StackProfileIS.IsEnabled = Supported;
}
});
}
@@ -198,7 +234,7 @@ private void RTSS_Updated(PlatformStatus status)
switch (status)
{
case PlatformStatus.Ready:
- var Processor = MainWindow.performanceManager.GetProcessor();
+ var Processor = PerformanceManager.GetProcessor();
StackProfileFramerate.IsEnabled = true;
break;
case PlatformStatus.Stalled:
@@ -209,17 +245,19 @@ private void RTSS_Updated(PlatformStatus status)
});
}
- private void SystemManager_DisplaySettingsChanged(ScreenResolution resolution)
+ private void SystemManager_PrimaryScreenChanged(DesktopScreen desktopScreen)
{
+ List frameLimits = desktopScreen.GetFramelimits();
+
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- var screenFrequency = SystemManager.GetDesktopScreen().GetFrequency();
+ cB_Framerate.Items.Clear();
+
+ foreach (ScreenFramelimit frameLimit in frameLimits)
+ cB_Framerate.Items.Add(frameLimit);
- FramerateQuarter.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Quarter));
- FramerateThird.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Third));
- FramerateHalf.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Half));
- FramerateFull.Content = Convert.ToString(screenFrequency.GetValue(Frequency.Full));
+ cB_Framerate.SelectedItem = desktopScreen.GetClosest(selectedProfile.FramerateValue);
});
}
@@ -341,100 +379,140 @@ private void PowerProfile_Clicked(PowerProfile powerProfile)
private void PowerProfile_Selected(PowerProfile powerProfile)
{
+ if (selectedProfile is null)
+ return;
+
// UI thread (async)
Application.Current.Dispatcher.BeginInvoke(() =>
{
- // update UI
SelectedPowerProfileName.Text = powerProfile.Name;
-
- // update profile
- selectedProfile.PowerProfile = powerProfile.Guid;
- UpdateProfile();
});
+
+ // update profile
+ selectedProfile.PowerProfile = powerProfile.Guid;
+ UpdateProfile();
}
- private void ProfileApplied(Profile profile, UpdateSource source)
+ private DesktopScreen desktopScreen;
+ private void ProfileManager_Applied(Profile profile, UpdateSource source)
{
- if (true)
+ switch (source)
{
- switch (source)
- {
- // self update, unlock and exit
- case UpdateSource.QuickProfilesPage:
- case UpdateSource.Serializer:
- return;
- }
+ // self update, unlock and exit
+ case UpdateSource.QuickProfilesPage:
+ return;
+ }
- // if an update is pending, execute it and stop timer
- if (UpdateTimer.Enabled)
- {
- UpdateTimer.Stop();
- SubmitProfile();
- }
+ // if an update is pending, execute it and stop timer
+ if (UpdateTimer.Enabled)
+ {
+ UpdateTimer.Stop();
+ SubmitProfile();
+ }
- // update profile
- selectedProfile = profile;
+ // update profile
+ selectedProfile = profile;
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
+ {
+ using (new ScopedLock(updateLock))
{
- using (new ScopedLock(updateLock))
- {
- // update profile name
- CurrentProfileName.Text = selectedProfile.Name;
- Toggle_ControllerLayout.IsEnabled = selectedProfile.Default ? false : true;
- Toggle_ControllerLayout.IsOn = selectedProfile.LayoutEnabled;
+ // update profile name
+ CurrentProfileName.Text = selectedProfile.Name;
+ Toggle_ControllerLayout.IsOn = selectedProfile.LayoutEnabled;
+ Toggle_ControllerLayout.IsEnabled = !selectedProfile.Default;
- // power profile
- PowerProfile powerProfile = PowerProfileManager.GetProfile(profile.PowerProfile);
- powerProfile.Check(this);
+ // sub profiles
+ cb_SubProfiles.Items.Clear();
+ int selectedIndex = 0;
- // gyro layout
- if (!selectedProfile.Layout.GyroLayout.TryGetValue(AxisLayoutFlags.Gyroscope, out IActions currentAction))
+ if (profile.Default)
+ {
+ cb_SubProfiles.Items.Add(profile);
+ cb_SubProfiles.IsEnabled = false;
+ }
+ else
+ {
+ Profile mainProfile = ProfileManager.GetProfileForSubProfile(selectedProfile);
+ Profile[] subProfiles = ProfileManager.GetSubProfilesFromPath(selectedProfile.Path, false);
+
+ cb_SubProfiles.Items.Add(mainProfile);
+ foreach (Profile subProfile in subProfiles)
{
- // no gyro layout available, mark as disabled
- cB_Output.SelectedIndex = (int)MotionOuput.Disabled;
+ cb_SubProfiles.Items.Add(subProfile);
+ if (subProfile.Guid == selectedProfile.Guid)
+ selectedIndex = cb_SubProfiles.Items.IndexOf(subProfile);
}
- else
- {
- // IActions
- GridAntiDeadzone.Visibility = currentAction is AxisActions ? Visibility.Visible : Visibility.Collapsed;
- GridGyroWeight.Visibility = currentAction is AxisActions ? Visibility.Visible : Visibility.Collapsed;
+ cb_SubProfiles.IsEnabled = true;
+ }
- if (currentAction is AxisActions)
- {
- cB_Output.SelectedIndex = (int)((AxisActions)currentAction).Axis;
- SliderUMCAntiDeadzone.Value = ((AxisActions)currentAction).AxisAntiDeadZone;
- Slider_GyroWeight.Value = ((AxisActions)currentAction).gyroWeight;
- }
- else if (currentAction is MouseActions)
- {
- cB_Output.SelectedIndex = (int)((MouseActions)currentAction).MouseType - 1;
- }
+ cb_SubProfiles.SelectedIndex = selectedIndex;
- // GyroActions
- cB_Input.SelectedIndex = (int)((GyroActions)currentAction).MotionInput;
- cB_UMC_MotionDefaultOffOn.SelectedIndex = (int)((GyroActions)currentAction).MotionMode;
+ // power profile
+ PowerProfile powerProfile = PowerProfileManager.GetProfile(profile.PowerProfile);
+ powerProfile.Check(this);
- // todo: move me to layout ?
- SliderSensitivityX.Value = selectedProfile.MotionSensivityX;
- SliderSensitivityY.Value = selectedProfile.MotionSensivityY;
+ // gyro layout
+ if (!selectedProfile.Layout.GyroLayout.TryGetValue(AxisLayoutFlags.Gyroscope, out IActions currentAction))
+ {
+ // no gyro layout available, mark as disabled
+ cB_Output.SelectedIndex = (int)MotionOuput.Disabled;
+ }
+ else
+ {
+ // IActions
+ GridAntiDeadzone.Visibility = currentAction is AxisActions ? Visibility.Visible : Visibility.Collapsed;
+ GridGyroWeight.Visibility = currentAction is AxisActions ? Visibility.Visible : Visibility.Collapsed;
- // todo: improve me ?
- GyroHotkey.inputsChord.State = ((GyroActions)currentAction).MotionTrigger.Clone() as ButtonState;
- GyroHotkey.DrawInput();
+ if (currentAction is AxisActions)
+ {
+ cB_Output.SelectedIndex = (int)((AxisActions)currentAction).Axis;
+ SliderUMCAntiDeadzone.Value = ((AxisActions)currentAction).AxisAntiDeadZone;
+ Slider_GyroWeight.Value = ((AxisActions)currentAction).gyroWeight;
+ }
+ else if (currentAction is MouseActions)
+ {
+ cB_Output.SelectedIndex = (int)((MouseActions)currentAction).MouseType - 1;
}
- // Framerate
- FramerateToggle.IsOn = selectedProfile.FramerateEnabled;
- FramerateSlider.Value = selectedProfile.FramerateValue;
+ // GyroActions
+ cB_Input.SelectedIndex = (int)((GyroActions)currentAction).MotionInput;
+ cB_UMC_MotionDefaultOffOn.SelectedIndex = (int)((GyroActions)currentAction).MotionMode;
+
+ // todo: move me to layout ?
+ SliderSensitivityX.Value = selectedProfile.MotionSensivityX;
+ SliderSensitivityY.Value = selectedProfile.MotionSensivityY;
- // RSR
- RSRToggle.IsOn = selectedProfile.RSREnabled;
- RSRSlider.Value = selectedProfile.RSRSharpness;
+ // todo: improve me ?
+ GyroHotkey.inputsChord.State = ((GyroActions)currentAction).MotionTrigger.Clone() as ButtonState;
+ GyroHotkey.DrawInput();
}
- });
- }
+
+ // Framerate limit
+ desktopScreen = SystemManager.GetDesktopScreen();
+ if (desktopScreen is not null)
+ cB_Framerate.SelectedItem = desktopScreen.GetClosest(selectedProfile.FramerateValue);
+
+ // GPU Scaling
+ GPUScalingToggle.IsOn = selectedProfile.GPUScaling;
+ GPUScalingComboBox.SelectedIndex = selectedProfile.ScalingMode;
+
+ // RSR
+ RSRToggle.IsOn = selectedProfile.RSREnabled;
+ RSRSlider.Value = selectedProfile.RSRSharpness;
+
+ // Integer Scaling
+ IntegerScalingToggle.IsOn = selectedProfile.IntegerScalingEnabled;
+
+ if (desktopScreen is not null)
+ IntegerScalingComboBox.SelectedItem = desktopScreen.screenDividers.FirstOrDefault(d => d.divider == selectedProfile.IntegerScalingDivider);
+
+ // RIS
+ RISToggle.IsOn = selectedProfile.RISEnabled;
+ RISSlider.Value = selectedProfile.RISSharpness;
+ }
+ });
}
private void ProcessManager_ForegroundChanged(ProcessEx processEx, ProcessEx backgroundEx)
@@ -455,11 +533,12 @@ private void ProcessManager_ForegroundChanged(ProcessEx processEx, ProcessEx bac
if (processEx.MainWindowHandle != IntPtr.Zero)
{
- var MainWindowTitle = ProcessUtils.GetWindowTitle(processEx.MainWindowHandle);
+ // string MainWindowTitle = ProcessUtils.GetWindowTitle(processEx.MainWindowHandle);
ProfileToggle.IsEnabled = true;
ProcessName.Text = currentProcess.Executable;
ProcessPath.Text = currentProcess.Path;
+ SubProfilesBorder.Visibility = Visibility.Visible;
}
else
{
@@ -468,6 +547,7 @@ private void ProcessManager_ForegroundChanged(ProcessEx processEx, ProcessEx bac
ProfileToggle.IsEnabled = false;
ProcessName.Text = Properties.Resources.QuickProfilesPage_Waiting;
ProcessPath.Text = string.Empty;
+ SubProfilesBorder.Visibility = Visibility.Collapsed;
}
}
});
@@ -496,7 +576,7 @@ private void ProfileToggle_Toggled(object sender, RoutedEventArgs e)
else
{
realProfile.Enabled = ProfileToggle.IsOn;
- ProfileManager.UpdateOrCreateProfile(realProfile, UpdateSource.Creation);
+ ProfileManager.UpdateOrCreateProfile(realProfile, UpdateSource.QuickProfilesCreation);
}
}
@@ -514,7 +594,7 @@ private void CreateProfile()
if (UpdateTimer.Enabled)
UpdateTimer.Stop();
- SubmitProfile(UpdateSource.Creation);
+ SubmitProfile(UpdateSource.QuickProfilesCreation);
}
private void cB_Input_SelectionChanged(object sender, SelectionChangedEventArgs e)
@@ -709,67 +789,36 @@ private void cB_UMC_MotionDefaultOffOn_SelectionChanged(object sender, RoutedEve
UpdateProfile();
}
- private void FramerateToggle_Toggled(object sender, RoutedEventArgs e)
+ private void RSRToggle_Toggled(object sender, RoutedEventArgs e)
{
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- if (FramerateToggle.IsOn)
- {
- FramerateSlider_ValueChanged(null, null);
- }
- else
- {
- foreach (Control control in FramerateModeGrid.Children)
- {
- if (control is not Label)
- continue;
-
- control.SetResourceReference(Control.ForegroundProperty, "SystemControlForegroundBaseMediumBrush");
- }
- }
- });
-
if (selectedProfile is null)
return;
+ // wait until lock is released
if (updateLock)
return;
- selectedProfile.FramerateEnabled = FramerateToggle.IsOn;
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.RadeonSuperResolution, RSRToggle.IsOn);
UpdateProfile();
}
- private void FramerateSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ private void RSRSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
- // UI thread (async)
- Application.Current.Dispatcher.BeginInvoke(() =>
- {
- var value = (int)FramerateSlider.Value;
-
- foreach (Control control in FramerateModeGrid.Children)
- {
- if (control is not Label)
- continue;
-
- control.SetResourceReference(Control.ForegroundProperty, "SystemControlForegroundBaseMediumBrush");
- }
-
- Label label = (Label)FramerateModeGrid.Children[value];
- label.SetResourceReference(Control.ForegroundProperty, "AccentButtonBackground");
- });
-
if (selectedProfile is null)
return;
+ if (!RSRSlider.IsInitialized)
+ return;
+
+ // wait until lock is released
if (updateLock)
return;
- selectedProfile.FramerateValue = (int)FramerateSlider.Value;
+ selectedProfile.RSRSharpness = (int)RSRSlider.Value;
UpdateProfile();
}
- private void RSRToggle_Toggled(object sender, RoutedEventArgs e)
+ private void RISToggle_Toggled(object sender, RoutedEventArgs e)
{
if (selectedProfile is null)
return;
@@ -778,23 +827,23 @@ private void RSRToggle_Toggled(object sender, RoutedEventArgs e)
if (updateLock)
return;
- selectedProfile.RSREnabled = RSRToggle.IsOn;
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.RadeonImageSharpening, RISToggle.IsOn);
UpdateProfile();
}
- private void RSRSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ private void RISSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
{
if (selectedProfile is null)
return;
- if (!RSRSlider.IsInitialized)
+ if (!RISSlider.IsInitialized)
return;
// wait until lock is released
if (updateLock)
return;
- selectedProfile.RSRSharpness = (int)RSRSlider.Value;
+ selectedProfile.RISSharpness = (int)RISSlider.Value;
UpdateProfile();
}
@@ -820,4 +869,187 @@ private void Button_PowerSettings_Create_Click(object sender, RoutedEventArgs e)
PowerProfileManager.UpdateOrCreateProfile(powerProfile, UpdateSource.Creation);
}
+
+ private void IntegerScalingToggle_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.IntegerScaling, IntegerScalingToggle.IsOn);
+ UpdateProfile();
+ }
+
+ private void GPUScalingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (GPUScalingComboBox.SelectedIndex == -1 || selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ int selectedIndex = GPUScalingComboBox.SelectedIndex;
+ // RSR does not work with ScalingMode.Center
+ if (selectedProfile.RSREnabled && selectedIndex == 2)
+ {
+ selectedProfile.ScalingMode = 1;
+ GPUScalingComboBox.SelectedIndex = 1;
+ }
+ else
+ {
+ selectedProfile.ScalingMode = GPUScalingComboBox.SelectedIndex;
+ }
+ UpdateProfile();
+ }
+
+ private void GPUScaling_Toggled(object sender, RoutedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ UpdateGraphicsSettings(UpdateGraphicsSettingsSource.GPUScaling, GPUScalingToggle.IsOn);
+ UpdateProfile();
+ }
+
+ private void cb_SubProfiles_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ // return if combobox selected item is null
+ if (cb_SubProfiles.SelectedIndex == -1)
+ return;
+
+ LogManager.LogInformation($"Subprofile changed in Quick Settings - ind: {cb_SubProfiles.SelectedIndex} - subprofile: {cb_SubProfiles.SelectedItem}");
+ selectedProfile = (Profile)cb_SubProfiles.SelectedItem;
+ UpdateProfile();
+ }
+
+ private void cB_Framerate_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ // return if combobox selected item is null
+ if (cB_Framerate.SelectedIndex == -1)
+ return;
+
+ if (cB_Framerate.SelectedItem is ScreenFramelimit screenFramelimit)
+ {
+ selectedProfile.FramerateValue = screenFramelimit.limit;
+ UpdateProfile();
+ }
+ }
+
+ private void IntegerScalingComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+ {
+ if (IntegerScalingComboBox.SelectedIndex == -1 || selectedProfile is null)
+ return;
+
+ // wait until lock is released
+ if (updateLock)
+ return;
+
+ var divider = 1;
+ if (IntegerScalingComboBox.SelectedItem is ScreenDivider screenDivider)
+ {
+ divider = screenDivider.divider;
+ }
+
+ selectedProfile.IntegerScalingDivider = divider;
+ UpdateProfile();
+ }
+
+ private enum UpdateGraphicsSettingsSource
+ {
+ GPUScaling,
+ RadeonSuperResolution,
+ RadeonImageSharpening,
+ IntegerScaling
+ }
+
+ private void UpdateGraphicsSettings(UpdateGraphicsSettingsSource source, bool isEnabled)
+ {
+ using (new ScopedLock(updateLock))
+ {
+ switch (source)
+ {
+ case UpdateGraphicsSettingsSource.GPUScaling:
+ {
+ selectedProfile.GPUScaling = isEnabled;
+ if (!isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+ selectedProfile.IntegerScalingEnabled = false;
+
+ RSRToggle.IsOn = false;
+ IntegerScalingToggle.IsOn = false;
+ }
+ }
+ break;
+ // RSR is incompatible with RIS and IS
+ case UpdateGraphicsSettingsSource.RadeonSuperResolution:
+ {
+ selectedProfile.RSREnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RISEnabled = false;
+ selectedProfile.IntegerScalingEnabled = false;
+
+ RISToggle.IsOn = false;
+ IntegerScalingToggle.IsOn = false;
+
+ // RSR does not support ScalingMode.Center
+ if (selectedProfile.ScalingMode == 2)
+ {
+ selectedProfile.ScalingMode = 1;
+ GPUScalingComboBox.SelectedIndex = 1;
+ }
+ }
+ }
+ break;
+ // Image Sharpening is incompatible with RSR
+ case UpdateGraphicsSettingsSource.RadeonImageSharpening:
+ {
+ selectedProfile.RISEnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+
+ RSRToggle.IsOn = false;
+ }
+ }
+ break;
+
+ // Integer Scaling is incompatible with RSR
+ case UpdateGraphicsSettingsSource.IntegerScaling:
+ {
+ selectedProfile.IntegerScalingEnabled = isEnabled;
+ if (isEnabled)
+ {
+ selectedProfile.RSREnabled = false;
+
+ RSRToggle.IsOn = false;
+ }
+ }
+ break;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml b/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml
deleted file mode 100644
index 6e952c89d..000000000
--- a/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml
+++ /dev/null
@@ -1,193 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml.cs b/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml.cs
deleted file mode 100644
index 83fa53afa..000000000
--- a/HandheldCompanion/Views/QuickPages/QuickSettingsPage.xaml.cs
+++ /dev/null
@@ -1,154 +0,0 @@
-using HandheldCompanion.Managers;
-using HandheldCompanion.Managers.Desktop;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Timers;
-using System.Windows;
-using System.Windows.Controls;
-using Windows.Devices.Bluetooth;
-using Windows.Devices.Radios;
-
-namespace HandheldCompanion.Views.QuickPages;
-
-///
-/// Interaction logic for QuickSettingsPage.xaml
-///
-public partial class QuickSettingsPage : Page
-{
- private IReadOnlyList radios;
- private Timer radioTimer;
-
- public QuickSettingsPage(string Tag) : this()
- {
- this.Tag = Tag;
-
- HotkeysManager.HotkeyCreated += HotkeysManager_HotkeyCreated;
- HotkeysManager.HotkeyUpdated += HotkeysManager_HotkeyUpdated;
-
- SystemManager.PrimaryScreenChanged += DesktopManager_PrimaryScreenChanged;
- SystemManager.DisplaySettingsChanged += DesktopManager_DisplaySettingsChanged;
-
- radioTimer = new(1000);
- radioTimer.Elapsed += RadioTimer_Elapsed;
- radioTimer.Start();
- }
-
- private void RadioTimer_Elapsed(object? sender, ElapsedEventArgs e)
- {
- new Task(async () =>
- {
- // Get the Bluetooth adapter
- BluetoothAdapter adapter = await BluetoothAdapter.GetDefaultAsync();
-
- // Get the Bluetooth radio
- radios = await Radio.GetRadiosAsync();
-
- // UI thread (async)
- _ = Application.Current.Dispatcher.BeginInvoke(() =>
- {
- // WIFI
- WifiToggle.IsEnabled = radios.Where(radio => radio.Kind == RadioKind.WiFi).Any();
- WifiToggle.IsOn = radios.Where(radio => radio.Kind == RadioKind.WiFi && radio.State == RadioState.On).Any();
-
- // Bluetooth
- BluetoothToggle.IsEnabled = radios.Where(radio => radio.Kind == RadioKind.Bluetooth).Any();
- BluetoothToggle.IsOn = radios.Where(radio => radio.Kind == RadioKind.Bluetooth && radio.State == RadioState.On).Any();
- });
- }).Start();
- }
-
- public QuickSettingsPage()
- {
- InitializeComponent();
- }
-
- private void HotkeysManager_HotkeyUpdated(Hotkey hotkey)
- {
- UpdatePins();
- }
-
- private void HotkeysManager_HotkeyCreated(Hotkey hotkey)
- {
- UpdatePins();
- }
-
- private void UpdatePins()
- {
- // todo, implement quick hotkey order
- QuickHotkeys.Children.Clear();
-
- foreach (var hotkey in HotkeysManager.Hotkeys.Values.Where(item => item.IsPinned))
- QuickHotkeys.Children.Add(hotkey.GetPin());
- }
-
- private void DesktopManager_PrimaryScreenChanged(DesktopScreen screen)
- {
- ComboBoxResolution.Items.Clear();
- foreach (var resolution in screen.resolutions)
- ComboBoxResolution.Items.Add(resolution);
- }
-
- private void DesktopManager_DisplaySettingsChanged(ScreenResolution resolution)
- {
- ComboBoxResolution.SelectedItem = resolution;
- ComboBoxFrequency.SelectedItem = SystemManager.GetDesktopScreen().GetFrequency();
- }
-
- private void ComboBoxResolution_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (ComboBoxResolution.SelectedItem is null)
- return;
-
- var resolution = (ScreenResolution)ComboBoxResolution.SelectedItem;
-
- ComboBoxFrequency.Items.Clear();
- foreach (var frequency in resolution.Frequencies.Values)
- ComboBoxFrequency.Items.Add(frequency);
-
- ComboBoxFrequency.SelectedItem = SystemManager.GetDesktopScreen().GetFrequency();
-
- SetResolution();
- }
-
- private void ComboBoxFrequency_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (ComboBoxFrequency.SelectedItem is null)
- return;
-
- SetResolution();
- }
-
- private void SetResolution()
- {
- if (ComboBoxResolution.SelectedItem is null)
- return;
-
- if (ComboBoxFrequency.SelectedItem is null)
- return;
-
- var resolution = (ScreenResolution)ComboBoxResolution.SelectedItem;
- var frequency = (ScreenFrequency)ComboBoxFrequency.SelectedItem;
-
- // update current screen resolution
- SystemManager.SetResolution(resolution.Width, resolution.Height, (int)frequency.GetValue(Frequency.Full), resolution.BitsPerPel);
- }
-
- private void WIFIToggle_Toggled(object sender, RoutedEventArgs e)
- {
- foreach(Radio radio in radios.Where(r => r.Kind == RadioKind.WiFi))
- _ = radio.SetStateAsync(WifiToggle.IsOn ? RadioState.On : RadioState.Off);
- }
-
- private void BluetoothToggle_Toggled(object sender, RoutedEventArgs e)
- {
- foreach (Radio radio in radios.Where(r => r.Kind == RadioKind.Bluetooth))
- _ = radio.SetStateAsync(BluetoothToggle.IsOn ? RadioState.On : RadioState.Off);
- }
-
- internal void Close()
- {
- radioTimer.Stop();
- }
-}
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Windows/MainWindow.xaml b/HandheldCompanion/Views/Windows/MainWindow.xaml
index 0cfbea380..a89bd9b10 100644
--- a/HandheldCompanion/Views/Windows/MainWindow.xaml
+++ b/HandheldCompanion/Views/Windows/MainWindow.xaml
@@ -1,240 +1,243 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
index c2311f30e..f122323f7 100644
--- a/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
+++ b/HandheldCompanion/Views/Windows/MainWindow.xaml.cs
@@ -6,7 +6,7 @@
using HandheldCompanion.Views.Classes;
using HandheldCompanion.Views.Pages;
using HandheldCompanion.Views.Windows;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using Nefarius.Utilities.DeviceManagement.PnP;
using System;
using System.Collections.Generic;
@@ -59,12 +59,6 @@ public partial class MainWindow : GamepadWindow
public static OverlayTrackpad overlayTrackpad;
public static OverlayQuickTools overlayquickTools;
- // manager(s) vars
- private static readonly List _managers = new();
- public static TaskManager taskManager;
- public static PerformanceManager performanceManager;
- public static UpdateManager updateManager;
-
public static string CurrentExe, CurrentPath;
private static MainWindow CurrentWindow;
@@ -197,61 +191,45 @@ public MainWindow(FileVersionInfo _fileVersionInfo, Assembly CurrentAssembly)
SettingsManager.SetProperty("FirstStart", false);
}
- // load manager(s)
- // todo: make me static
- loadManagers();
-
// load window(s)
loadWindows();
// load page(s)
loadPages();
- // start static managers in sequence
- // managers that has to be stopped/started when session status changes shouldn't be put here
+ // manage events
+ InputsManager.TriggerRaised += InputsManager_TriggerRaised;
+ PowerManager.SystemStatusChanged += OnSystemStatusChanged;
+ DeviceManager.UsbDeviceArrived += GenericDeviceUpdated;
+ DeviceManager.UsbDeviceRemoved += GenericDeviceUpdated;
+ ControllerManager.ControllerSelected += ControllerManager_ControllerSelected;
+ VirtualManager.ControllerSelected += VirtualManager_ControllerSelected;
ToastManager.Start();
ToastManager.IsEnabled = SettingsManager.GetBoolean("ToastEnable");
+ // start static managers in sequence
PowerProfileManager.Start();
ProfileManager.Start();
-
- ControllerManager.ControllerSelected += ControllerManager_ControllerSelected;
ControllerManager.Start();
HotkeysManager.Start();
-
- DeviceManager.UsbDeviceArrived += GenericDeviceUpdated;
- DeviceManager.UsbDeviceRemoved += GenericDeviceUpdated;
DeviceManager.Start();
-
OSDManager.Start();
LayoutManager.Start();
-
- // todo: improve overall threading logic
- new Thread(() =>
- {
- PlatformManager.Start();
- ProcessManager.Start();
- }).Start();
-
- PowerManager.SystemStatusChanged += OnSystemStatusChanged;
PowerManager.Start();
-
DynamicLightingManager.Start();
-
SystemManager.Start();
VirtualManager.Start();
-
- InputsManager.TriggerRaised += InputsManager_TriggerRaised;
InputsManager.Start();
SensorsManager.Start();
TimerManager.Start();
- VirtualManager.ControllerSelected += VirtualManager_ControllerSelected;
-
- // start managers asynchroneously
- foreach (var manager in _managers)
- new Thread(manager.Start).Start();
+ // todo: improve overall threading logic
+ new Thread(() => { PlatformManager.Start(); }).Start();
+ new Thread(() => { ProcessManager.Start(); }).Start();
+ new Thread(() => { TaskManager.Start(CurrentExe); }).Start();
+ new Thread(() => { PerformanceManager.Start(); }).Start();
+ new Thread(() => { UpdateManager.Start(); }).Start();
// start setting last
SettingsManager.SettingValueChanged += SettingsManager_SettingValueChanged;
@@ -445,19 +423,6 @@ private void loadWindows()
overlayquickTools = new OverlayQuickTools();
}
- private void loadManagers()
- {
- // initialize managers
- taskManager = new TaskManager("HandheldCompanion", CurrentExe);
- performanceManager = new PerformanceManager();
- updateManager = new UpdateManager();
-
- // store managers
- _managers.Add(taskManager);
- _managers.Add(performanceManager);
- _managers.Add(updateManager);
- }
-
private void GenericDeviceUpdated(PnPDevice device, DeviceEventArgs obj)
{
// todo: improve me
@@ -689,15 +654,10 @@ private void Window_Closed(object sender, EventArgs e)
overlayTrackpad.Close();
overlayquickTools.Close(true);
- // TODO: Make static
- taskManager.Stop();
- performanceManager.Stop();
-
VirtualManager.Stop();
SystemManager.Stop();
MotionManager.Stop();
SensorsManager.Stop();
-
ControllerManager.Stop();
InputsManager.Stop();
DeviceManager.Stop();
@@ -709,6 +669,9 @@ private void Window_Closed(object sender, EventArgs e)
PowerManager.Stop();
ProcessManager.Stop();
ToastManager.Stop();
+ TaskManager.Stop();
+ PerformanceManager.Stop();
+ UpdateManager.Stop();
// closing page(s)
controllerPage.Page_Closed();
diff --git a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml
index 6696782a8..c9fe51ffe 100644
--- a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml
+++ b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml
@@ -28,55 +28,53 @@
WindowStyle="ToolWindow"
mc:Ignorable="d">
-
-
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
\ No newline at end of file
diff --git a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
index ebcfd52f5..0f9267f3d 100644
--- a/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
+++ b/HandheldCompanion/Views/Windows/OverlayQuickTools.xaml.cs
@@ -3,7 +3,7 @@
using HandheldCompanion.Utils;
using HandheldCompanion.Views.Classes;
using HandheldCompanion.Views.QuickPages;
-using Inkore.UI.WPF.Modern.Controls;
+using iNKORE.UI.WPF.Modern.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -14,18 +14,21 @@
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Interop;
+using System.Windows.Media;
using System.Windows.Navigation;
using System.Windows.Threading;
using Windows.System.Power;
using WpfScreenHelper;
using WpfScreenHelper.Enum;
using Application = System.Windows.Application;
+using ComboBox = System.Windows.Controls.ComboBox;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using Page = System.Windows.Controls.Page;
using PowerLineStatus = System.Windows.Forms.PowerLineStatus;
using PowerManager = HandheldCompanion.Managers.PowerManager;
using Screen = WpfScreenHelper.Screen;
using SystemPowerManager = Windows.System.Power.PowerManager;
+using Timer = System.Timers.Timer;
namespace HandheldCompanion.Views.Windows;
@@ -41,6 +44,9 @@ public partial class OverlayQuickTools : GamepadWindow
const UInt32 SWP_NOMOVE = 0x0002;
const UInt32 SWP_NOACTIVATE = 0x0010;
const UInt32 SWP_NOZORDER = 0x0004;
+
+ // Define the Win32 API constants and functions
+ const int WM_PAINT = 0x000F;
const int WM_ACTIVATEAPP = 0x001C;
const int WM_ACTIVATE = 0x0006;
const int WM_SETFOCUS = 0x0007;
@@ -56,6 +62,9 @@ public partial class OverlayQuickTools : GamepadWindow
private HwndSource hwndSource;
+ private Dictionary cacheModes = new();
+ private Timer WM_PAINT_TIMER;
+
// page vars
private readonly Dictionary _pages = new();
@@ -64,10 +73,10 @@ public partial class OverlayQuickTools : GamepadWindow
private readonly DispatcherTimer clockUpdateTimer;
public QuickHomePage homePage;
- public QuickSettingsPage settingsPage;
public QuickDevicePage devicePage;
public QuickPerformancePage performancePage;
public QuickProfilesPage profilesPage;
+ public QuickOverlayPage overlayPage;
public QuickSuspenderPage suspenderPage;
private string preNavItemTag;
@@ -85,6 +94,9 @@ public OverlayQuickTools()
clockUpdateTimer.Interval = TimeSpan.FromMilliseconds(500);
clockUpdateTimer.Tick += UpdateTime;
+ WM_PAINT_TIMER = new(250) { AutoReset = false };
+ WM_PAINT_TIMER.Elapsed += WM_PAINT_TIMER_Tick;
+
// create manager(s)
PowerManager.PowerStatusChanged += PowerManager_PowerStatusChanged;
@@ -93,22 +105,18 @@ public OverlayQuickTools()
// create pages
homePage = new("quickhome");
- settingsPage = new("quicksettings");
devicePage = new("quickdevice");
performancePage = new("quickperformance");
profilesPage = new("quickprofiles");
+ overlayPage = new("quickoverlay");
suspenderPage = new("quicksuspender");
_pages.Add("QuickHomePage", homePage);
- _pages.Add("QuickSettingsPage", settingsPage);
_pages.Add("QuickDevicePage", devicePage);
_pages.Add("QuickPerformancePage", performancePage);
_pages.Add("QuickProfilesPage", profilesPage);
+ _pages.Add("QuickOverlayPage", overlayPage);
_pages.Add("QuickSuspenderPage", suspenderPage);
-
- // update Position and Size
- Height = (int)Math.Max(MinHeight, SettingsManager.GetDouble("QuickToolsHeight"));
- navView.IsPaneOpen = SettingsManager.GetBoolean("QuickToolsIsPaneOpen");
}
private void SettingsManager_SettingValueChanged(string name, object value)
@@ -135,56 +143,38 @@ private void SettingsManager_SettingValueChanged(string name, object value)
private void SystemManager_DisplaySettingsChanged(ScreenResolution resolution)
{
- var QuickToolsLocation = SettingsManager.GetInt("QuickToolsLocation");
+ int QuickToolsLocation = SettingsManager.GetInt("QuickToolsLocation");
UpdateLocation(QuickToolsLocation);
}
private void UpdateLocation(int QuickToolsLocation)
{
- switch (QuickToolsLocation)
+ // UI thread (async)
+ Application.Current.Dispatcher.BeginInvoke(() =>
{
- // top, left
- case 0:
- {
- this.SetWindowPosition(WindowPositions.TopLeft, Screen.PrimaryScreen);
- Top += Margin.Top;
- Left += Margin.Left;
- }
- break;
-
- // top, right
- case 1:
- {
- this.SetWindowPosition(WindowPositions.TopRight, Screen.PrimaryScreen);
- Top += Margin.Top;
- Left -= Margin.Left;
- }
- break;
-
- // bottom, left
- case 2:
- {
- this.SetWindowPosition(WindowPositions.BottomLeft, Screen.PrimaryScreen);
- Top -= Margin.Top;
+ switch (QuickToolsLocation)
+ {
+ // top, left
+ // bottom, left
+ case 0:
+ case 2:
+ this.SetWindowPosition(WindowPositions.Left, Screen.PrimaryScreen);
Left += Margin.Left;
- }
- break;
+ break;
- // bottom, right
- default:
- case 3:
- {
- this.SetWindowPosition(WindowPositions.BottomRight, Screen.PrimaryScreen);
- Top -= Margin.Top;
- Left -= Margin.Left;
- }
- break;
- }
+ // top, right
+ // bottom, right
+ default:
+ case 1:
+ case 3:
+ this.SetWindowPosition(WindowPositions.Right, Screen.PrimaryScreen);
+ Left -= Margin.Right;
+ break;
+ }
- // prevent window's from being too tall, add margin for top and bottom
- var maxHeight = (int)(Screen.PrimaryScreen.WpfBounds.Height - 2 * Margin.Top);
- if (Height > maxHeight)
- Height = maxHeight;
+ Height = MinHeight = MaxHeight = (int)(Screen.PrimaryScreen.WpfBounds.Height - (2.0d * Margin.Top));
+ Top = Margin.Top;
+ });
}
private void PowerManager_PowerStatusChanged(PowerStatus status)
@@ -253,11 +243,9 @@ private void Window_Loaded(object sender, RoutedEventArgs e)
hwndSource = PresentationSource.FromVisual(this) as HwndSource;
hwndSource.AddHook(WndProc);
- // workaround: fix the stalled UI rendering, at the cost of forcing the window to render over CPU at 30fps
if (hwndSource != null)
{
- hwndSource.CompositionTarget.RenderMode = RenderMode.Default;
- // hwndSource.CompositionTarget.RenderMode = RenderMode.SoftwareOnly;
+ hwndSource.CompositionTarget.RenderMode = RenderMode.SoftwareOnly;
WinAPI.SetWindowPos(hwndSource.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
}
}
@@ -326,14 +314,41 @@ private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref b
}
break;
- default:
- // Debug.WriteLine($"{msg}\t\t{wParam}\t\t\t{lParam}");
+ case WM_PAINT:
+ {
+ // Loop through all visual elements in the window
+ foreach (var element in WPFUtils.FindVisualChildren(this))
+ {
+ if (element.CacheMode is not null)
+ {
+ // Store the previous CacheMode value
+ cacheModes[element] = element.CacheMode.Clone();
+
+ // Set the CacheMode to null
+ element.CacheMode = null;
+ }
+ }
+
+ WM_PAINT_TIMER.Stop();
+ WM_PAINT_TIMER.Start();
+ }
break;
}
return IntPtr.Zero;
}
+ private void WM_PAINT_TIMER_Tick(object? sender, EventArgs e)
+ {
+ // UI thread
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ // Set the CacheMode back to the previous value
+ foreach (UIElement element in cacheModes.Keys)
+ element.CacheMode = cacheModes[element];
+ });
+ }
+
private void HandleEsc(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
@@ -372,24 +387,14 @@ public void ToggleVisibility()
private void Window_Closing(object sender, CancelEventArgs e)
{
- // position and size settings
- switch (WindowState)
- {
- case WindowState.Normal:
- case WindowState.Maximized:
- SettingsManager.SetProperty("QuickToolsHeight", Height);
- break;
- }
-
- SettingsManager.SetProperty("QuickToolsIsPaneOpen", navView.IsPaneOpen);
-
e.Cancel = !isClosing;
if (!isClosing)
ToggleVisibility();
else
{
- settingsPage.Close();
+ // close pages
+ devicePage.Close();
}
}
diff --git a/HandheldCompanion/XInputPlus/XInputPlus.cs b/HandheldCompanion/XInputPlus/XInputPlus.cs
index 1cc5a52ac..fe4b3a5a0 100644
--- a/HandheldCompanion/XInputPlus/XInputPlus.cs
+++ b/HandheldCompanion/XInputPlus/XInputPlus.cs
@@ -352,51 +352,59 @@ public static bool UnregisterApplication(Profile profile)
return true;
}
+ private static object writeLock = new();
public static bool WriteXInputPlusINI(string directoryPath, bool x64bit)
{
- var IniPath = Path.Combine(directoryPath, "XInputPlus.ini");
+ lock (writeLock)
+ {
+ string IniPath = Path.Combine(directoryPath, "XInputPlus.ini");
- if (!FileUtils.IsFileWritable(IniPath))
- return false;
+ if (!FileUtils.IsFileWritable(IniPath))
+ return false;
- // prepare index array
- List userIndex = new() { 1, 2, 3, 4 };
+ // prepare index array
+ List userIndex = new() { 1, 2, 3, 4 };
- // prepare IniFile
- File.WriteAllText(IniPath, IniContent);
- IniFile IniFile = new IniFile(IniPath);
- IniFile.Write("FileVersion", x64bit ? "X64" : "X86", "Misc");
+ // prepare IniFile
+ try
+ {
+ File.WriteAllText(IniPath, IniContent);
+ IniFile IniFile = new IniFile(IniPath);
+ IniFile.Write("FileVersion", x64bit ? "X64" : "X86", "Misc");
- // reset controller index values
- for (int i = 0; i < userIndex.Count; i++)
- IniFile.Write($"Controller{i + 1}", "0", "ControllerNumber");
+ // reset controller index values
+ for (int i = 0; i < userIndex.Count; i++)
+ IniFile.Write($"Controller{i + 1}", "0", "ControllerNumber");
- // we need to define Controller index overwrite
- XInputController vController = ControllerManager.GetVirtualControllers().OfType().FirstOrDefault();
- if (vController is null)
- return false;
+ // we need to define Controller index overwrite
+ XInputController vController = ControllerManager.GetVirtualControllers().OfType().FirstOrDefault();
+ if (vController is null)
+ return false;
- // get virtual controller index and update IniFile
- int idx = vController.GetUserIndex() + 1;
- IniFile.Write("Controller1", Convert.ToString(idx), "ControllerNumber");
+ // get virtual controller index and update IniFile
+ int idx = vController.GetUserIndex() + 1;
+ IniFile.Write("Controller1", Convert.ToString(idx), "ControllerNumber");
- // remove virtual controller index from it
- userIndex.Remove(idx);
+ // remove virtual controller index from it
+ userIndex.Remove(idx);
- // remove all hidden physical controllers from the list
- foreach(XInputController pController in ControllerManager.GetPhysicalControllers().OfType().Where(c => c.IsHidden()))
- userIndex.Remove(pController.GetUserIndex() + 1);
+ // remove all hidden physical controllers from the list
+ foreach (XInputController pController in ControllerManager.GetPhysicalControllers().OfType().Where(c => c.IsHidden()))
+ userIndex.Remove(pController.GetUserIndex() + 1);
- for (int i = 0; i < userIndex.Count; i++)
- {
- int cIdx = userIndex[i];
- IniFile.Write($"Controller{i + 2}", Convert.ToString(cIdx), "ControllerNumber");
- }
+ for (int i = 0; i < userIndex.Count; i++)
+ {
+ int cIdx = userIndex[i];
+ IniFile.Write($"Controller{i + 2}", Convert.ToString(cIdx), "ControllerNumber");
+ }
- LogManager.LogDebug("XInputPlus INI wrote in {0}. Controller1 set to UserIndex: {1}",
- directoryPath, idx);
+ LogManager.LogDebug("XInputPlus INI wrote in {0}. Controller1 set to UserIndex: {1}",
+ directoryPath, idx);
- return true;
+ return true;
+ }
+ catch { return false; }
+ }
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684139%28v=vs.85%29.aspx
diff --git a/README.md b/README.md
index 910637c77..c5cc0f639 100644
--- a/README.md
+++ b/README.md
@@ -36,14 +36,15 @@ The software is built for Windows 10/Windows 11 (x86 and amd64).
- AYA Neo Next and its different versions
- AYA Neo Air and it's different versions
- AYA Neo 2, Geek, 2S Geek 1S
-- Ayn Loki (all models)
+- AYA Neo KUN
- ONEXPLAYER MINI and its different versions (Intel, AMD, Gundam)
-- GPD WIN Max 2 (Intel and AMD)
+- GPD WIN Max 2 (INTEL, AMD)
- GPD Win 2
- GPD Win 3
- GPD Win 4
-- Steam Deck (LCD and OLED)
-- Lenovo Legion Go (WIP)
+- Steam Deck (LCD, OLED)
+- Ayn Loki (all models)
+- Lenovo Legion Go
## Supported Sensors
- Bosch BMI160 (and similar)
diff --git a/redist/hwi_766.exe b/redist/hwi_766.exe
deleted file mode 100644
index d71ef3df8..000000000
Binary files a/redist/hwi_766.exe and /dev/null differ