Compare commits

...

123 Commits
v0.16 ... v0.32

Author SHA1 Message Date
seerge
04b3a15d8f Merge branch 'main' of https://github.com/seerge/g-helper 2023-03-19 10:27:35 +01:00
seerge
aae0570340 - 2023-03-19 10:27:32 +01:00
Serge
b142d566da Update README.md 2023-03-18 20:56:37 +01:00
seerge
a9115d0dff Screenshot 2023-03-18 18:46:35 +01:00
Serge
e3a3e81245 Merge pull request #96 from seerge/new_ui
New UI
2023-03-18 18:38:35 +01:00
seerge
c50c1807ca UI fixes, tooltips for fan control 2023-03-18 17:57:09 +01:00
seerge
5767320437 Fixes for scaling, and layout 2023-03-18 15:13:34 +01:00
seerge
74846097db Optimized icons 2023-03-17 22:39:53 +01:00
seerge
5b89556ed3 New UI 2023-03-17 22:28:33 +01:00
Serge
845b182b55 Update README.md 2023-03-17 15:28:41 +01:00
Serge
b7cfd04560 Rename stop-asus-sv.bat to debloat.bat 2023-03-17 15:28:23 +01:00
Serge
6ffd464ec4 Update README.md 2023-03-17 15:14:04 +01:00
seerge
e7dd3ce203 - 2023-03-17 15:13:49 +01:00
Serge
d06dae9015 Update README.md 2023-03-17 15:11:44 +01:00
Serge
1b208e1a74 Update README.md 2023-03-17 15:11:00 +01:00
seerge
6befab190b Folders 2023-03-17 15:10:39 +01:00
seerge
5d3eaa0055 Merge branch 'main' of https://github.com/seerge/g-helper 2023-03-17 15:08:03 +01:00
seerge
667f1a997c Folder cleanup 2023-03-17 15:08:01 +01:00
Serge
4542221a58 Update README.md 2023-03-17 15:03:58 +01:00
seerge
5fd7b74519 Folder reorganisation 2023-03-17 15:03:09 +01:00
Serge
014ee635d6 Update README.md 2023-03-17 01:31:24 +01:00
Serge
1dff60d574 Create default.html 2023-03-17 01:18:00 +01:00
Serge
7395f0be69 Update README.md 2023-03-16 23:07:38 +01:00
seerge
e3019a313a UI fixes 2023-03-16 22:59:50 +01:00
seerge
9653b81cd3 Revert "Update _config.yml"
This reverts commit 9713cb6fa4.
2023-03-16 22:59:34 +01:00
Serge
9713cb6fa4 Update _config.yml 2023-03-16 22:51:51 +01:00
Serge
10053eda10 Update _config.yml 2023-03-16 22:42:42 +01:00
Serge
ef1bbc1fce Update _config.yml 2023-03-16 22:36:31 +01:00
seerge
3fde8c1fa9 Screenshot 2023-03-16 18:56:09 +01:00
seerge
efd6707e61 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-16 15:39:27 +01:00
seerge
8032ea3fc7 UI tweaks 2023-03-16 15:39:25 +01:00
Serge
d0a232d888 Update README.md 2023-03-15 22:55:42 +01:00
Serge
a6bd18f019 Update README.md 2023-03-15 22:53:16 +01:00
seerge
a09c252c2e Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-15 21:25:51 +01:00
seerge
99d3c61897 Kill app on Eco switch 2023-03-15 21:25:49 +01:00
Serge
4a6decb0be Update README.md 2023-03-15 21:25:10 +01:00
Serge
80b9fdb8ac Update README.md 2023-03-15 19:14:49 +01:00
Serge
e3c293942c Update README.md 2023-03-15 17:47:38 +01:00
Serge
42e910e635 Create _config.yml 2023-03-15 17:44:18 +01:00
Serge
18b6ae07b2 Update README.md 2023-03-15 17:30:17 +01:00
Serge
fa2875fbee Update README.md 2023-03-15 17:29:17 +01:00
Serge
f2bfb24fb4 Update README.md 2023-03-15 17:27:22 +01:00
Serge
adc81721ac Update README.md 2023-03-15 17:21:50 +01:00
Serge
9da061d621 Update README.md 2023-03-15 17:12:07 +01:00
Serge
274c04bf61 Update README.md 2023-03-15 14:15:29 +01:00
Serge
2d286ca04f Update README.md 2023-03-15 14:14:47 +01:00
Serge
2c1fa01863 Create SECURITY.md 2023-03-15 14:11:46 +01:00
Serge
0370ef7bc0 Update issue templates 2023-03-15 14:10:33 +01:00
Serge
2f2ef23ee4 Create CONTRIBUTING.md 2023-03-15 14:09:57 +01:00
Serge
756ed44741 Create CODE_OF_CONDUCT.md 2023-03-15 14:08:49 +01:00
Serge
efb6a087b4 Merge pull request #86 from seerge/add-license-1
Create LICENSE
2023-03-15 14:07:13 +01:00
Serge
4e6f55c24d Create LICENSE 2023-03-15 14:05:01 +01:00
Serge
c029df357a Update README.md 2023-03-15 12:45:49 +01:00
Serge
8d19b5f89c Update README.md 2023-03-15 12:24:54 +01:00
seerge
7683e68df3 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-14 23:07:52 +01:00
seerge
e45bcdf8a5 Adjusted PPTs for 2021 model, added windows PowerModes 2023-03-14 23:07:49 +01:00
Serge
ab8d42c216 Update README.md 2023-03-14 17:55:25 +01:00
seerge
d248fcf384 Screenshot 2023-03-14 17:53:15 +01:00
seerge
9bb5e41a5d Fixed auto resolution switching in some exotic cases 2023-03-14 15:39:56 +01:00
seerge
bc965c003d Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-14 14:21:23 +01:00
seerge
a6cfc91de2 Added log cleanup 2023-03-14 14:21:20 +01:00
Serge
9ca6ec657f Update README.md 2023-03-14 12:55:22 +01:00
seerge
89d7930323 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-13 23:30:02 +01:00
seerge
e26d26b498 - 2023-03-13 23:28:58 +01:00
seerge
a6d0dde4b0 - 2023-03-13 23:28:58 +01:00
seerge
f68d53aaf4 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-13 23:28:58 +01:00
seerge
a2ea3d18fd UI Tweaks 2023-03-13 23:28:58 +01:00
seerge
f77fcc940f Merge pull request #82 from ZimM-LostPolygon/gpu-temperature
fix: improved GPU temperature reliability
2023-03-13 23:28:58 +01:00
seerge
dd4d85f254 Turbo boost dropdown 2023-03-13 23:28:57 +01:00
seerge
2afbde814f fix: improved GPU temperature reliability 2023-03-13 23:28:57 +01:00
seerge
b6b06a3802 UI tweaks 2023-03-13 23:28:57 +01:00
seerge
4d58945688 Minor fixes 2023-03-13 23:28:57 +01:00
seerge
9aaf0159e5 Merged GPU temp reader 2023-03-13 23:28:57 +01:00
seerge
3cbaf1eb52 Merge pull request #74 from ZimM-LostPolygon/gpu-temperature
feat: added GPU temperature indication.
2023-03-13 23:28:57 +01:00
seerge
c76fbeab37 New sleep/wake up detection 2023-03-13 23:28:56 +01:00
seerge
15d580bbe3 fix: fixed crash when launched in Eco mode 2023-03-13 23:28:56 +01:00
seerge
2ec64bf8b5 feat: added GPU temperature indication. Supports both NVIDIA and AMD discrete GPUs
feat: immediately update sensors when opening GHelper window
2023-03-13 23:28:56 +01:00
seerge
254be71e88 - 2023-03-13 23:21:06 +01:00
seerge
e9ec8f0e8f - 2023-03-13 23:14:28 +01:00
seerge
0ef44a0495 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-13 23:07:31 +01:00
seerge
e725760b24 UI Tweaks 2023-03-13 23:07:28 +01:00
seerge
a83ab4884e Merge pull request #82 from ZimM-LostPolygon/gpu-temperature
fix: improved GPU temperature reliability
2023-03-13 23:07:12 +01:00
Serhii Yolkin
7bfd10c65d fix: improved GPU temperature reliability 2023-03-13 22:45:12 +01:00
seerge
67b541b145 Turbo boost dropdown 2023-03-13 21:46:11 +01:00
seerge
f1ae14652f UI tweaks 2023-03-13 21:20:46 +01:00
seerge
223ead2f4e Minor fixes 2023-03-13 20:25:35 +01:00
seerge
a211dd412f Merged GPU temp reader 2023-03-13 20:02:59 +01:00
seerge
550e9fc036 Merge pull request #74 from ZimM-LostPolygon/gpu-temperature
feat: added GPU temperature indication.
2023-03-13 19:52:33 +01:00
seerge
8fe01e8790 New sleep/wake up detection 2023-03-13 19:38:39 +01:00
seerge
f0abe22b5d Logger and minor changes 2023-03-13 18:33:27 +01:00
Serhii Yolkin
ef0993e442 fix: fixed crash when launched in Eco mode 2023-03-13 17:47:11 +01:00
Serhii Yolkin
62ac478761 feat: added GPU temperature indication. Supports both NVIDIA and AMD discrete GPUs
feat: immediately update sensors when opening GHelper window
2023-03-13 17:35:35 +01:00
seerge
a7e8ba3241 Scheduler warning 2023-03-13 12:10:29 +01:00
seerge
b46f0fb887 Removed scheduler call on each run 2023-03-13 11:38:54 +01:00
seerge
a39c084bdf Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-12 16:16:35 +01:00
seerge
f0c291bea4 Minor tweaks 2023-03-12 16:16:32 +01:00
seerge
d04a20367b Update README.md 2023-03-12 13:36:09 +01:00
seerge
888e49fe40 Update README.md 2023-03-12 13:35:40 +01:00
seerge
4875a22f38 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-12 13:27:55 +01:00
seerge
ea2e8a7c24 UI Tweaks 2023-03-12 13:27:44 +01:00
seerge
6ec94e4ac3 Update README.md 2023-03-11 14:28:17 +01:00
seerge
5334d1e4ed Screenshot 2023-03-11 12:47:17 +01:00
seerge
9f339806d4 UI Fixes 2023-03-11 12:41:34 +01:00
seerge
54a4668e2a Under the hood changes 2023-03-10 23:32:12 +01:00
seerge
71d2a6ce05 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-10 21:50:22 +01:00
seerge
92d1b97b95 Fix for UI lag on GPU switch 2023-03-10 21:50:20 +01:00
seerge
4b9a53cef8 Update README.md 2023-03-10 15:51:20 +01:00
seerge
068694d7d1 Update README.md 2023-03-10 13:45:49 +01:00
seerge
43c6def162 Update checker 2023-03-09 20:54:32 +01:00
seerge
306697f026 Added possible fix for bios unsetting ppts after wake up 2023-03-09 16:03:39 +01:00
seerge
c5a32cc9d5 Moved turbo boost checkbox to Fans and Power window 2023-03-09 14:10:13 +01:00
seerge
51acd9a612 Fix for startup checkbox 2023-03-09 11:28:02 +01:00
seerge
457a37049c - 2023-03-08 22:51:33 +01:00
seerge
6d2cece4f2 Merge branch 'main' of https://github.com/seerge/g14-helper 2023-03-08 22:44:16 +01:00
seerge
265611009c Improved internal display detection 2023-03-08 22:44:14 +01:00
seerge
2714b6dca7 Update README.md 2023-03-08 20:04:38 +01:00
seerge
f6de5eba64 Screenshot 2023-03-08 20:03:24 +01:00
seerge
13f7c81689 Fix animatrix 2021 size 2023-03-08 19:43:52 +01:00
seerge
8c0d84b65b Fix for possible animatrix custom picture support on older (2021) models 2023-03-08 19:15:21 +01:00
seerge
4e6fa6d9b0 Auto Apply power limits 2023-03-08 17:25:11 +01:00
seerge
be133cd238 Minor fixes 2023-03-07 21:19:04 +01:00
seerge
30f678d08f Hide unsupported power sliders 2023-03-07 16:10:56 +01:00
seerge
cf201632d5 New built in monitor detection system 2023-03-07 15:23:06 +01:00
92 changed files with 3916 additions and 2050 deletions

128
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

1
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1 @@
Please, feel free to contribute. Especially if you own model differnt from G14 2022 and can offer extra features or support.

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

10
.github/ISSUE_TEMPLATE/custom.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

16
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,16 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 0.25+ | :white_check_mark: |
| < 0.24 | :x: |
## Reporting a Vulnerability
Use this section to tell people how to report a vulnerability.
Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.

301
Fans.Designer.cs generated
View File

@@ -1,301 +0,0 @@
namespace GHelper
{
partial class Fans
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
chartCPU = new System.Windows.Forms.DataVisualization.Charting.Chart();
buttonApply = new Button();
buttonReset = new Button();
chartGPU = new System.Windows.Forms.DataVisualization.Charting.Chart();
groupBox1 = new GroupBox();
labelApplied = new Label();
pictureFine = new PictureBox();
labelInfo = new Label();
labelCPU = new Label();
labelTotal = new Label();
label2 = new Label();
label1 = new Label();
trackCPU = new TrackBar();
trackTotal = new TrackBar();
buttonApplyPower = new Button();
checkAuto = new CheckBox();
((System.ComponentModel.ISupportInitialize)chartCPU).BeginInit();
((System.ComponentModel.ISupportInitialize)chartGPU).BeginInit();
groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)pictureFine).BeginInit();
((System.ComponentModel.ISupportInitialize)trackCPU).BeginInit();
((System.ComponentModel.ISupportInitialize)trackTotal).BeginInit();
SuspendLayout();
//
// chartCPU
//
chartArea1.Name = "ChartArea1";
chartCPU.ChartAreas.Add(chartArea1);
chartCPU.Location = new Point(390, 28);
chartCPU.Margin = new Padding(4, 2, 4, 2);
chartCPU.Name = "chartCPU";
chartCPU.Size = new Size(832, 436);
chartCPU.TabIndex = 0;
chartCPU.Text = "chartCPU";
//
// buttonApply
//
buttonApply.Location = new Point(946, 952);
buttonApply.Margin = new Padding(4, 2, 4, 2);
buttonApply.Name = "buttonApply";
buttonApply.Size = new Size(274, 44);
buttonApply.TabIndex = 1;
buttonApply.Text = "Apply Fan Curve";
buttonApply.UseVisualStyleBackColor = true;
//
// buttonReset
//
buttonReset.Location = new Point(390, 952);
buttonReset.Margin = new Padding(4, 2, 4, 2);
buttonReset.Name = "buttonReset";
buttonReset.Size = new Size(274, 44);
buttonReset.TabIndex = 2;
buttonReset.Text = "Factory Defaults";
buttonReset.UseVisualStyleBackColor = true;
//
// chartGPU
//
chartArea2.Name = "ChartArea1";
chartGPU.ChartAreas.Add(chartArea2);
chartGPU.Location = new Point(390, 480);
chartGPU.Margin = new Padding(4, 2, 4, 2);
chartGPU.Name = "chartGPU";
chartGPU.Size = new Size(832, 450);
chartGPU.TabIndex = 3;
chartGPU.Text = "chart1";
//
// groupBox1
//
groupBox1.Controls.Add(labelApplied);
groupBox1.Controls.Add(pictureFine);
groupBox1.Controls.Add(labelInfo);
groupBox1.Controls.Add(labelCPU);
groupBox1.Controls.Add(labelTotal);
groupBox1.Controls.Add(label2);
groupBox1.Controls.Add(label1);
groupBox1.Controls.Add(trackCPU);
groupBox1.Controls.Add(trackTotal);
groupBox1.Location = new Point(12, 12);
groupBox1.Margin = new Padding(4, 2, 4, 2);
groupBox1.Name = "groupBox1";
groupBox1.Padding = new Padding(6, 4, 6, 4);
groupBox1.Size = new Size(356, 918);
groupBox1.TabIndex = 4;
groupBox1.TabStop = false;
groupBox1.Text = "Power Limits (PPT)";
//
// labelApplied
//
labelApplied.AutoSize = true;
labelApplied.ForeColor = Color.Tomato;
labelApplied.Location = new Point(16, 36);
labelApplied.Margin = new Padding(4, 0, 4, 0);
labelApplied.Name = "labelApplied";
labelApplied.Size = new Size(143, 32);
labelApplied.TabIndex = 13;
labelApplied.Text = "Not Applied";
//
// pictureFine
//
pictureFine.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
pictureFine.BackgroundImageLayout = ImageLayout.Zoom;
pictureFine.Image = Properties.Resources.everything_is_fine_itsfine;
pictureFine.Location = new Point(10, 682);
pictureFine.Margin = new Padding(4, 2, 4, 2);
pictureFine.Name = "pictureFine";
pictureFine.Size = new Size(336, 226);
pictureFine.SizeMode = PictureBoxSizeMode.Zoom;
pictureFine.TabIndex = 12;
pictureFine.TabStop = false;
pictureFine.Visible = false;
//
// labelInfo
//
labelInfo.AutoSize = true;
labelInfo.Dock = DockStyle.Bottom;
labelInfo.Location = new Point(6, 882);
labelInfo.Margin = new Padding(4, 0, 4, 0);
labelInfo.Name = "labelInfo";
labelInfo.Size = new Size(65, 32);
labelInfo.TabIndex = 11;
labelInfo.Text = "label";
//
// labelCPU
//
labelCPU.AutoSize = true;
labelCPU.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelCPU.Location = new Point(212, 118);
labelCPU.Margin = new Padding(4, 0, 4, 0);
labelCPU.Name = "labelCPU";
labelCPU.Size = new Size(61, 32);
labelCPU.TabIndex = 10;
labelCPU.Text = "CPU";
labelCPU.TextAlign = ContentAlignment.MiddleCenter;
//
// labelTotal
//
labelTotal.AutoSize = true;
labelTotal.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelTotal.Location = new Point(42, 118);
labelTotal.Margin = new Padding(4, 0, 4, 0);
labelTotal.Name = "labelTotal";
labelTotal.Size = new Size(70, 32);
labelTotal.TabIndex = 9;
labelTotal.Text = "Total";
labelTotal.TextAlign = ContentAlignment.MiddleCenter;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(216, 86);
label2.Margin = new Padding(4, 0, 4, 0);
label2.Name = "label2";
label2.Size = new Size(58, 32);
label2.TabIndex = 8;
label2.Text = "CPU";
label2.TextAlign = ContentAlignment.MiddleCenter;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(44, 86);
label1.Margin = new Padding(4, 0, 4, 0);
label1.Name = "label1";
label1.Size = new Size(65, 32);
label1.TabIndex = 7;
label1.Text = "Total";
label1.TextAlign = ContentAlignment.MiddleCenter;
//
// trackCPU
//
trackCPU.Location = new Point(218, 166);
trackCPU.Margin = new Padding(4, 2, 4, 2);
trackCPU.Maximum = 85;
trackCPU.Minimum = 15;
trackCPU.Name = "trackCPU";
trackCPU.Orientation = Orientation.Vertical;
trackCPU.Size = new Size(90, 416);
trackCPU.TabIndex = 6;
trackCPU.TickFrequency = 5;
trackCPU.Value = 80;
//
// trackTotal
//
trackTotal.Location = new Point(46, 166);
trackTotal.Margin = new Padding(4, 2, 4, 2);
trackTotal.Maximum = 150;
trackTotal.Minimum = 15;
trackTotal.Name = "trackTotal";
trackTotal.Orientation = Orientation.Vertical;
trackTotal.Size = new Size(90, 416);
trackTotal.TabIndex = 5;
trackTotal.TickFrequency = 5;
trackTotal.TickStyle = TickStyle.TopLeft;
trackTotal.Value = 125;
//
// buttonApplyPower
//
buttonApplyPower.Location = new Point(16, 952);
buttonApplyPower.Margin = new Padding(4, 2, 4, 2);
buttonApplyPower.Name = "buttonApplyPower";
buttonApplyPower.Size = new Size(352, 44);
buttonApplyPower.TabIndex = 11;
buttonApplyPower.Text = "Apply Power Limits";
buttonApplyPower.UseVisualStyleBackColor = true;
//
// checkAuto
//
checkAuto.AutoSize = true;
checkAuto.Location = new Point(762, 958);
checkAuto.Margin = new Padding(4, 2, 4, 2);
checkAuto.Name = "checkAuto";
checkAuto.Size = new Size(165, 36);
checkAuto.TabIndex = 12;
checkAuto.Text = "Auto Apply";
checkAuto.UseVisualStyleBackColor = true;
//
// Fans
//
AutoScaleDimensions = new SizeF(192F, 192F);
AutoScaleMode = AutoScaleMode.Dpi;
AutoSize = true;
ClientSize = new Size(1242, 1020);
Controls.Add(checkAuto);
Controls.Add(buttonApplyPower);
Controls.Add(groupBox1);
Controls.Add(chartGPU);
Controls.Add(buttonReset);
Controls.Add(buttonApply);
Controls.Add(chartCPU);
Margin = new Padding(4, 2, 4, 2);
MaximizeBox = false;
MdiChildrenMinimizedAnchorBottom = false;
MinimizeBox = false;
Name = "Fans";
ShowIcon = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Fans and Power";
((System.ComponentModel.ISupportInitialize)chartCPU).EndInit();
((System.ComponentModel.ISupportInitialize)chartGPU).EndInit();
groupBox1.ResumeLayout(false);
groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)pictureFine).EndInit();
((System.ComponentModel.ISupportInitialize)trackCPU).EndInit();
((System.ComponentModel.ISupportInitialize)trackTotal).EndInit();
ResumeLayout(false);
PerformLayout();
}
#endregion
private System.Windows.Forms.DataVisualization.Charting.Chart chartCPU;
private Button buttonApply;
private Button buttonReset;
private System.Windows.Forms.DataVisualization.Charting.Chart chartGPU;
private GroupBox groupBox1;
private Label labelCPU;
private Label labelTotal;
private Label label2;
private Label label1;
private TrackBar trackCPU;
private TrackBar trackTotal;
private Button buttonApplyPower;
private Label labelInfo;
private PictureBox pictureFine;
private Label labelApplied;
private CheckBox checkAuto;
}
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Serge
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,277 +0,0 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
public class NativeMethods
{
public const int KEYEVENTF_EXTENDEDKEY = 1;
public const int KEYEVENTF_KEYUP = 2;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
public const int VK_VOLUME_MUTE = 0xAD;
public const int VK_SNAPSHOT = 0x2C;
[DllImport("user32.dll", SetLastError = true)]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public static void KeyPress(int key = VK_MEDIA_PLAY_PAUSE)
{
keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero);
}
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
public const int SW_RESTORE = 9;
public static bool SwitchToCurrent()
{
IntPtr hWnd = IntPtr.Zero;
Process process = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(process.ProcessName);
foreach (Process _process in processes)
{
if (_process.Id != process.Id)
{
if (_process.MainWindowHandle != IntPtr.Zero)
{
Debug.WriteLine(_process.Id);
Debug.WriteLine(process.Id);
hWnd = _process.MainWindowHandle;
ShowWindowAsync(hWnd, SW_RESTORE);
}
return true;
break;
}
}
return false;
}
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerWriteDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerWriteACValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerReadACValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
out IntPtr AcValueIndex
);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerReadDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
out IntPtr AcValueIndex
);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerSetActiveScheme(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerGetActiveScheme(IntPtr UserPowerKey, out IntPtr ActivePolicyGuid);
static readonly Guid GUID_CPU = new Guid("54533251-82be-4824-96c1-47b60b740d00");
static readonly Guid GUID_BOOST = new Guid("be337238-0d82-4146-a960-4f3749d470c7");
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
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 int dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short 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;
};
[Flags()]
public enum DisplaySettingsFlags : int
{
CDS_UPDATEREGISTRY = 1,
CDS_TEST = 2,
CDS_FULLSCREEN = 4,
CDS_GLOBAL = 8,
CDS_SET_PRIMARY = 0x10,
CDS_RESET = 0x40000000,
CDS_NORESET = 0x10000000
}
// PInvoke declaration for EnumDisplaySettings Win32 API
[DllImport("user32.dll")]
public static extern int EnumDisplaySettingsEx(
string lpszDeviceName,
int iModeNum,
ref DEVMODE lpDevMode);
// PInvoke declaration for ChangeDisplaySettings Win32 API
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(
string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd,
DisplaySettingsFlags dwflags, IntPtr lParam);
public const int ENUM_CURRENT_SETTINGS = -1;
public const string laptopScreenName = "\\\\.\\DISPLAY1";
public static DEVMODE CreateDevmode()
{
DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
public static Screen FindLaptopScreen()
{
var screens = Screen.AllScreens;
Screen laptopScreen = null;
foreach (var screen in screens)
{
if (screen.DeviceName == laptopScreenName)
{
laptopScreen = screen;
}
}
if (laptopScreen is null) return null;
else return laptopScreen;
}
public static int GetRefreshRate()
{
DEVMODE dm = CreateDevmode();
Screen laptopScreen = FindLaptopScreen();
int frequency = -1;
if (laptopScreen is null)
return -1;
if (0 != NativeMethods.EnumDisplaySettingsEx(laptopScreen.DeviceName, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
frequency = dm.dmDisplayFrequency;
}
return frequency;
}
public static int SetRefreshRate(int frequency = 120)
{
DEVMODE dm = CreateDevmode();
Screen laptopScreen = FindLaptopScreen();
if (laptopScreen is null)
return -1;
if (0 != NativeMethods.EnumDisplaySettingsEx(laptopScreen.DeviceName, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
dm.dmDisplayFrequency = frequency;
int iRet = NativeMethods.ChangeDisplaySettingsEx(laptopScreen.DeviceName, ref dm, IntPtr.Zero, DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);
return iRet;
}
return 0;
}
static Guid GetActiveScheme()
{
IntPtr pActiveSchemeGuid;
var hr = PowerGetActiveScheme(IntPtr.Zero, out pActiveSchemeGuid);
Guid activeSchemeGuid = (Guid)Marshal.PtrToStructure(pActiveSchemeGuid, typeof(Guid));
return activeSchemeGuid;
}
public static int GetCPUBoost()
{
IntPtr AcValueIndex;
Guid activeSchemeGuid = GetActiveScheme();
UInt32 value = PowerReadACValueIndex(IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST, out AcValueIndex);
return AcValueIndex.ToInt32();
}
public static void SetCPUBoost(int boost = 0)
{
Guid activeSchemeGuid = GetActiveScheme();
var hrAC = PowerWriteACValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST,
boost);
PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
var hrDC = PowerWriteDCValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST,
boost);
PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
}
}

View File

@@ -1,8 +0,0 @@
{
"profiles": {
"GHelper": {
"commandName": "Project",
"workingDirectory": "C:\\Users\\serge\\source\\GHelper"
}
}
}

View File

@@ -1,68 +0,0 @@
# G-Helper (For Asus ROG Zephyrus G14, G15, Flow X13, Flow X16, and others)
A small utility that allows you do almost everyting you could do with Armory Crate but without extra bloat and unnecessary services.
## NEW (and experimental) features
1. Set Power limits (PPT) for Total (APU + dGPU) and CPU.
2. Anime matrix control thanks to https://github.com/vddCore/Starlight
## Main features
1. Switch between built-in system **Performance modes** Silent / Balanced / Turbo and apply default fan curves
2. Switch between Eco / Standard or Ultimate **GPU modes**
3. Change laptop screen refresh rate - 60hz or your maximum (120hz, 144hz, etc depending on the model) with display overdrive (OD)
4. View default fan profiles for every mode and **auto apply** custom ones
5. Control keyboard backlit animation and colors
6. Set battery charge limit to preserve battery health
7. Monitor CPU temperature, fan speeds and battery discharge rate
8. **Automatically switch to Eco(iGPU)/60hz on battery** and back to Standard(GPU)/120hz modes when plugged
9. Support for FN+F5 to cycle through performance modes (with OSD notification) and FN+F4 to cycle through keeyboard animation modes
10. Basic keybindings for M3 and M4 keys
11. Turn cpu turbo boost on/off with one checkbox to keep temps cooler
Designed and developed for Asus Zephyrus G14 2022 (with AMD Radeon iGPU and dGPU). But could and should potentially work for G14 of 2021 and 2020, G15, X FLOW, and other ROG models for relevant and supported features.
To keep autoswitching and hotkeys work app needs to stay in running in tray. It doesn't consume any resources.
I recommend to keep "Asus Optimization Service" running, as it keeps basic laptop hotkeys such as screen or keyboard brightness adjustment working. If you have (or had) MyASUS app installed, that service is most probably still up an running even after MyASUS uninstall. It's part of [Asus System Controll Interface](https://www.asus.com/support/FAQ/1047338/). You can install it, and later disable / remove unnecesarily services by running [this bat file](https://raw.githubusercontent.com/seerge/g-helper/main/stop-asus-sv.bat ) as admin.
### [Download latest release](https://github.com/seerge/g-helper/releases)
![Screenshot](https://github.com/seerge/g-helper/blob/main/screenshot.png)
## Performance Profile switching
Profiles are **same** as in Armory Crate (as they are stored in bios), including default fan curves
1. Silent (minimal or no fans, 70W PPT total, up to 45W PPT to CPU)
2. Balanced (balanced fans, 100W PPT total, up to 45W PPT to CPU)
3. Turbo (intense fans, 125W PPT total, up to 80W PPT to CPU)
PPTs are shown for G14 2022, for other models PPTs will be different as they are set in bios.
## GPU Modes
1. Eco mode : only low power integrated GPU enabled, iGPU drives built in display
2. Standard mode (Windows Hybrid) : iGPU and dGPU enabled, iGPU drives built in display
3. Ultimate mode: iGPU and dGPU enabled, but dGPU drives built in display (supported only on G14 2022 model)
## How to install
1. Download latest release from https://github.com/seerge/g-helper/releases
2. Unzip to a folder of your choice
3. Run **GHelper.exe**
Note: Uses low level ASUS ACPI commands and doens't require Armory Crate to be installed at all! Doesn't need administrator privileges to run!
I don`t have Microsoft certificate to sign app yet, so if you get a warning from Windows Defender on launch (Windows Protected your PC), click More Info -> Run anyway. Alternatively you can compile and run project by yourself using Visual Studio :)
Settings file is stored at %AppData%\GHelper
P.S.: It's not recommended to use app in combination with Armory Crate, cause they adjust same settings.
------------------
Debloating helps to save your battery and keep laptop a bit cooler
![Helps to save your battery](https://raw.githubusercontent.com/seerge/g-helper/main/screenshots/screen-5w.png)

View File

@@ -1,8 +1,6 @@
using System.Diagnostics;
using System.Management;
using System.Management;
using System.Runtime.InteropServices;
public class ASUSWmi
{
@@ -26,12 +24,16 @@ public class ASUSWmi
public const uint DevsCPUFanCurve = 0x00110024;
public const uint DevsGPUFanCurve = 0x00110025;
public const int PPT_TotalA0 = 0x001200A0;
public const int PPT_TotalA1 = 0x001200A1;
public const int PPT_TotalA0 = 0x001200A0; // Total PPT on 2022 and CPU PPT on 2021
public const int PPT_EDCA1 = 0x001200A1; // CPU EDC
public const int PPT_TDCA2 = 0x001200A2; // CPU TDC
public const int PPT_APUA3 = 0x001200A3; // APU PPT ON 2021, doesn't work on 2022
public const int PPT_CPUB0 = 0x001200B0;
public const int PPT_CPUB1 = 0x001200B1;
public const int PPT_CPUA2 = 0x001200A2;
public const int PPT_CPUB0 = 0x001200B0; // CPU PPT on 2022
public const int PPT_CPUB1 = 0x001200B1; // APU PPT on 2022
public const int PPT_APUC1 = 0x001200C1;
public const int PPT_APUC2 = 0x001200C2;
public const int PerformanceBalanced = 0;
public const int PerformanceTurbo = 1;
@@ -42,6 +44,15 @@ public class ASUSWmi
public const int GPUModeUltimate = 2;
public const int MaxTotal = 150;
public const int MinTotal = 5;
public const int DefaultTotal = 125;
public const int MaxCPU = 90;
public const int MinCPU = 5;
public const int DefaultCPU = 80;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern IntPtr CreateFile(
string lpFileName,
@@ -173,7 +184,7 @@ public class ASUSWmi
if (curve.Length != 16) return;
if (curve.All(singleByte => singleByte == 0)) return;
Debug.WriteLine(BitConverter.ToString(curve));
Logger.WriteLine("Fans" + ((device == 1) ? "GPU" : "CPU") + " " + BitConverter.ToString(curve));
if (device == 1)
DeviceSet(DevsGPUFanCurve, curve);
@@ -200,7 +211,6 @@ public class ASUSWmi
}
public void SubscribeToEvents(Action<object, EventArrivedEventArgs> EventHandler)
{
ManagementEventWatcher watcher = new ManagementEventWatcher();

View File

@@ -3,6 +3,7 @@
using Starlight.Communication;
using System.Diagnostics;
using System.Text;
using System.Management;
namespace Starlight.AnimeMatrix
{
@@ -70,16 +71,45 @@ namespace Starlight.AnimeMatrix
private const int UpdatePageLength = 0x0278;
public int LedCount => 1450;
public int Rows => 61;
private byte[] _displayBuffer = new byte[UpdatePageLength * 3];
private List<byte[]> frames = new List<byte[]>();
private int pages = 3;
public int MaxColumns = 34;
public int MaxRows = 61;
public int FullRows = 11;
private int frameIndex = 0;
public AnimeMatrixDevice()
: base(0x0B05, 0x193B, 640)
{
string model = GetModel();
Debug.WriteLine(model);
if (model is not null && model.Contains("401"))
{
pages = 2;
FullRows = 6;
MaxColumns = 33;
MaxRows = 55;
}
}
public string GetModel()
{
using (var searcher = new ManagementObjectSearcher(@"Select * from Win32_ComputerSystem"))
{
foreach (var process in searcher.Get())
return process["Model"].ToString();
}
return null;
}
public byte[] GetBuffer()
@@ -115,12 +145,12 @@ namespace Starlight.AnimeMatrix
public int EmptyColumns(int row)
{
return (int)Math.Ceiling(Math.Max(0, row - 11) / 2.0);
return (int)Math.Ceiling(Math.Max(0, row - FullRows) / 2.0);
}
public int Columns(int row)
{
EnsureRowInRange(row);
return 34 - EmptyColumns(row);
return MaxColumns - EmptyColumns(row);
}
public int RowToLinearAddress(int row)
@@ -183,6 +213,7 @@ namespace Starlight.AnimeMatrix
public void Present()
{
Set(Packet<AnimeMatrixPacket>(0xC0, 0x02)
.AppendData(BitConverter.GetBytes((ushort)(UpdatePageLength * 0 + 1)))
.AppendData(BitConverter.GetBytes((ushort)UpdatePageLength))
@@ -195,12 +226,13 @@ namespace Starlight.AnimeMatrix
.AppendData(_displayBuffer[(UpdatePageLength * 1)..(UpdatePageLength * 2)])
);
Set(Packet<AnimeMatrixPacket>(0xC0, 0x02)
.AppendData(BitConverter.GetBytes((ushort)(UpdatePageLength * 2 + 1)))
.AppendData(BitConverter.GetBytes((ushort)(LedCount - UpdatePageLength * 2)))
.AppendData(
_displayBuffer[(UpdatePageLength * 2)..(UpdatePageLength * 2 + (LedCount - UpdatePageLength * 2))])
);
if (pages > 2)
Set(Packet<AnimeMatrixPacket>(0xC0, 0x02)
.AppendData(BitConverter.GetBytes((ushort)(UpdatePageLength * 2 + 1)))
.AppendData(BitConverter.GetBytes((ushort)(LedCount - UpdatePageLength * 2)))
.AppendData(
_displayBuffer[(UpdatePageLength * 2)..(UpdatePageLength * 2 + (LedCount - UpdatePageLength * 2))])
);
Set(Packet<AnimeMatrixPacket>(0xC0, 0x03));
}
@@ -241,8 +273,8 @@ namespace Starlight.AnimeMatrix
public void GenerateFrame(Image image)
{
int width = 34 * 3;
int height = 61;
int width = MaxColumns * 3;
int height = MaxRows;
float scale;
Bitmap canvas = new Bitmap(width, height);
@@ -259,7 +291,7 @@ namespace Starlight.AnimeMatrix
graph.DrawImage(image, ((int)width - scaleWidth), ((int)height - scaleHeight) / 2, scaleWidth, scaleHeight);
Bitmap bmp = new Bitmap(canvas, 34, 61);
Bitmap bmp = new Bitmap(canvas, MaxColumns, MaxRows);
for (int y = 0; y < bmp.Height; y++)
{
@@ -275,9 +307,9 @@ namespace Starlight.AnimeMatrix
private void EnsureRowInRange(int row)
{
if (row < 0 || row >= Rows)
if (row < 0 || row >= MaxRows)
{
throw new IndexOutOfRangeException($"Y-coordinate should fall in range of [0, {Rows - 1}].");
throw new IndexOutOfRangeException($"Y-coordinate should fall in range of [0, {MaxRows - 1}].");
}
}

View File

@@ -3,4 +3,8 @@
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
<appSettings>
<add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
</appSettings>
</configuration>

View File

@@ -44,8 +44,9 @@ public class AppConfig
File.WriteAllText(configFile, jsonString);
}
public int getConfig(string name)
public int getConfig(string name, bool performance = false)
{
if (config.ContainsKey(name))
return int.Parse(config[name].ToString());
else return -1;
@@ -141,4 +142,17 @@ public class AppConfig
return curve;
}
public int getConfigPerf(string name)
{
int mode = getConfig("performance_mode");
return getConfig(name + "_" + mode);
}
public void setConfigPerf(string name, int value)
{
int mode = getConfig("performance_mode");
setConfig(name + "_" + mode, value);
}
}

View File

@@ -43,7 +43,7 @@ public class Aura
{
HidDevice[] HidDeviceList;
int[] deviceIds = { 0x1854, 0x1869, 0x1866, 0x19b6 };
int[] deviceIds = { 0x1854, 0x1869, 0x1866, 0x19b6, 0x1822, 0x1837, 0x1854, 0x184a, 0x183d, 0x8502, 0x1807, 0x17e0 };
HidDeviceList = HidDevices.Enumerate(0x0b05, deviceIds).ToArray();
@@ -63,18 +63,14 @@ public class Aura
foreach (HidDevice device in HidDeviceList)
{
if (device.IsConnected)
if (device.IsConnected && device.Description.Contains("HID"))
{
if (device.Description.IndexOf("HID") >= 0)
{
device.OpenDevice();
byte[] msg = AuraMessage(Mode, Color1, Color2, Speed);
device.Write(msg);
device.Write(MESSAGE_SET);
device.Write(MESSAGE_APPLY);
device.CloseDevice();
}
device.OpenDevice();
byte[] msg = AuraMessage(Mode, Color1, Color2, Speed);
device.Write(msg);
device.Write(MESSAGE_SET);
device.Write(MESSAGE_APPLY);
device.CloseDevice();
}
}

View File

@@ -1,6 +1,7 @@
// Source thanks to https://github.com/vddCore/Starlight :)
using Starlight.Communication.Platform;
using System.Configuration;
namespace Starlight.Communication
{
@@ -8,9 +9,21 @@ namespace Starlight.Communication
{
private static UsbProvider _usbProvider;
private static ushort _vendorId;
private static ushort _productId;
private static int _maxFeatureReportLength;
protected Device(ushort vendorId, ushort productId, int maxFeatureReportLength)
{
_usbProvider = new WindowsUsbProvider(vendorId, productId, maxFeatureReportLength);
_vendorId = vendorId;
_productId = productId;
_maxFeatureReportLength = maxFeatureReportLength;
SetProvider();
}
public void SetProvider()
{
_usbProvider = new WindowsUsbProvider(_vendorId, _productId, _maxFeatureReportLength);
}
protected T Packet<T>(params byte[] command) where T : Packet

486
app/Fans.Designer.cs generated Normal file
View File

@@ -0,0 +1,486 @@
namespace GHelper
{
partial class Fans
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea2 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
panelFans = new Panel();
labelTip = new Label();
labelBoost = new Label();
comboBoost = new ComboBox();
picturePerf = new PictureBox();
tableFanCharts = new TableLayoutPanel();
chartGPU = new System.Windows.Forms.DataVisualization.Charting.Chart();
chartCPU = new System.Windows.Forms.DataVisualization.Charting.Chart();
labelFans = new Label();
checkAuto = new CheckBox();
buttonReset = new Button();
buttonApply = new Button();
panelPower = new Panel();
pictureBox1 = new PictureBox();
labelPowerLimits = new Label();
checkApplyPower = new CheckBox();
buttonApplyPower = new Button();
panelCPU = new Panel();
labelCPU = new Label();
label2 = new Label();
trackCPU = new TrackBar();
panelTotal = new Panel();
labelTotal = new Label();
label1 = new Label();
trackTotal = new TrackBar();
labelApplied = new Label();
pictureFine = new PictureBox();
labelInfo = new Label();
panelFans.SuspendLayout();
((System.ComponentModel.ISupportInitialize)picturePerf).BeginInit();
tableFanCharts.SuspendLayout();
((System.ComponentModel.ISupportInitialize)chartGPU).BeginInit();
((System.ComponentModel.ISupportInitialize)chartCPU).BeginInit();
panelPower.SuspendLayout();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
panelCPU.SuspendLayout();
((System.ComponentModel.ISupportInitialize)trackCPU).BeginInit();
panelTotal.SuspendLayout();
((System.ComponentModel.ISupportInitialize)trackTotal).BeginInit();
((System.ComponentModel.ISupportInitialize)pictureFine).BeginInit();
SuspendLayout();
//
// panelFans
//
panelFans.Controls.Add(labelTip);
panelFans.Controls.Add(labelBoost);
panelFans.Controls.Add(comboBoost);
panelFans.Controls.Add(picturePerf);
panelFans.Controls.Add(tableFanCharts);
panelFans.Controls.Add(labelFans);
panelFans.Controls.Add(checkAuto);
panelFans.Controls.Add(buttonReset);
panelFans.Controls.Add(buttonApply);
panelFans.Dock = DockStyle.Left;
panelFans.Location = new Point(364, 0);
panelFans.Margin = new Padding(0);
panelFans.Name = "panelFans";
panelFans.Padding = new Padding(20);
panelFans.Size = new Size(824, 1159);
panelFans.TabIndex = 12;
//
// labelTip
//
labelTip.AutoSize = true;
labelTip.BackColor = SystemColors.ControlLightLight;
labelTip.Location = new Point(245, 13);
labelTip.Name = "labelTip";
labelTip.Padding = new Padding(5);
labelTip.Size = new Size(107, 42);
labelTip.TabIndex = 40;
labelTip.Text = "500,300";
//
// labelBoost
//
labelBoost.AutoSize = true;
labelBoost.Location = new Point(397, 19);
labelBoost.Name = "labelBoost";
labelBoost.Size = new Size(125, 32);
labelBoost.TabIndex = 39;
labelBoost.Text = "CPU Boost";
//
// comboBoost
//
comboBoost.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
comboBoost.DropDownStyle = ComboBoxStyle.DropDownList;
comboBoost.FormattingEnabled = true;
comboBoost.Items.AddRange(new object[] { "Disabled", "Enabled", "Aggressive", "Efficient Enabled", "Efficient Aggressive" });
comboBoost.Location = new Point(526, 15);
comboBoost.Name = "comboBoost";
comboBoost.Size = new Size(266, 40);
comboBoost.TabIndex = 38;
//
// picturePerf
//
picturePerf.BackgroundImage = Properties.Resources.icons8_fan_head_96;
picturePerf.BackgroundImageLayout = ImageLayout.Zoom;
picturePerf.InitialImage = null;
picturePerf.Location = new Point(30, 18);
picturePerf.Margin = new Padding(4, 2, 4, 2);
picturePerf.Name = "picturePerf";
picturePerf.Size = new Size(36, 38);
picturePerf.TabIndex = 37;
picturePerf.TabStop = false;
//
// tableFanCharts
//
tableFanCharts.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
tableFanCharts.ColumnCount = 1;
tableFanCharts.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
tableFanCharts.Controls.Add(chartGPU, 0, 1);
tableFanCharts.Controls.Add(chartCPU, 0, 0);
tableFanCharts.Location = new Point(28, 64);
tableFanCharts.Margin = new Padding(6);
tableFanCharts.Name = "tableFanCharts";
tableFanCharts.RowCount = 2;
tableFanCharts.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableFanCharts.RowStyles.Add(new RowStyle(SizeType.Percent, 50F));
tableFanCharts.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
tableFanCharts.RowStyles.Add(new RowStyle(SizeType.Absolute, 40F));
tableFanCharts.Size = new Size(764, 992);
tableFanCharts.TabIndex = 36;
//
// chartGPU
//
chartArea1.Name = "ChartArea1";
chartGPU.ChartAreas.Add(chartArea1);
chartGPU.Dock = DockStyle.Fill;
chartGPU.Location = new Point(2, 506);
chartGPU.Margin = new Padding(2, 10, 2, 10);
chartGPU.Name = "chartGPU";
chartGPU.Size = new Size(760, 476);
chartGPU.TabIndex = 17;
chartGPU.Text = "chart1";
//
// chartCPU
//
chartArea2.Name = "ChartArea1";
chartCPU.ChartAreas.Add(chartArea2);
chartCPU.Dock = DockStyle.Fill;
chartCPU.Location = new Point(2, 10);
chartCPU.Margin = new Padding(2, 10, 2, 10);
chartCPU.Name = "chartCPU";
chartCPU.Size = new Size(760, 476);
chartCPU.TabIndex = 14;
chartCPU.Text = "chartCPU";
//
// labelFans
//
labelFans.AutoSize = true;
labelFans.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelFans.Location = new Point(66, 20);
labelFans.Margin = new Padding(4, 0, 4, 0);
labelFans.Name = "labelFans";
labelFans.Size = new Size(138, 32);
labelFans.TabIndex = 28;
labelFans.Text = "Fan Curves";
//
// checkAuto
//
checkAuto.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
checkAuto.AutoSize = true;
checkAuto.Location = new Point(377, 1086);
checkAuto.Margin = new Padding(4, 2, 4, 2);
checkAuto.Name = "checkAuto";
checkAuto.Size = new Size(165, 36);
checkAuto.TabIndex = 17;
checkAuto.Text = "Auto Apply";
checkAuto.UseVisualStyleBackColor = true;
//
// buttonReset
//
buttonReset.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
buttonReset.Location = new Point(30, 1081);
buttonReset.Margin = new Padding(4, 2, 4, 2);
buttonReset.Name = "buttonReset";
buttonReset.Size = new Size(232, 44);
buttonReset.TabIndex = 15;
buttonReset.Text = "Factory Defaults";
buttonReset.UseVisualStyleBackColor = true;
//
// buttonApply
//
buttonApply.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
buttonApply.Location = new Point(542, 1081);
buttonApply.Margin = new Padding(4, 2, 4, 2);
buttonApply.Name = "buttonApply";
buttonApply.Size = new Size(248, 44);
buttonApply.TabIndex = 14;
buttonApply.Text = "Apply Fan Curve";
buttonApply.UseVisualStyleBackColor = true;
//
// panelPower
//
panelPower.Controls.Add(pictureBox1);
panelPower.Controls.Add(labelPowerLimits);
panelPower.Controls.Add(checkApplyPower);
panelPower.Controls.Add(buttonApplyPower);
panelPower.Controls.Add(panelCPU);
panelPower.Controls.Add(panelTotal);
panelPower.Controls.Add(labelApplied);
panelPower.Controls.Add(pictureFine);
panelPower.Controls.Add(labelInfo);
panelPower.Dock = DockStyle.Left;
panelPower.Location = new Point(0, 0);
panelPower.Margin = new Padding(10);
panelPower.Name = "panelPower";
panelPower.Padding = new Padding(10);
panelPower.Size = new Size(364, 1159);
panelPower.TabIndex = 13;
//
// pictureBox1
//
pictureBox1.BackgroundImage = Properties.Resources.icons8_processor_96;
pictureBox1.BackgroundImageLayout = ImageLayout.Zoom;
pictureBox1.InitialImage = null;
pictureBox1.Location = new Point(20, 18);
pictureBox1.Margin = new Padding(4, 2, 4, 2);
pictureBox1.Name = "pictureBox1";
pictureBox1.Size = new Size(36, 38);
pictureBox1.TabIndex = 38;
pictureBox1.TabStop = false;
//
// labelPowerLimits
//
labelPowerLimits.AutoSize = true;
labelPowerLimits.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelPowerLimits.Location = new Point(54, 20);
labelPowerLimits.Margin = new Padding(4, 0, 4, 0);
labelPowerLimits.Name = "labelPowerLimits";
labelPowerLimits.Size = new Size(229, 32);
labelPowerLimits.TabIndex = 26;
labelPowerLimits.Text = "Power Limits (PPT)";
//
// checkApplyPower
//
checkApplyPower.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
checkApplyPower.AutoSize = true;
checkApplyPower.Location = new Point(27, 1039);
checkApplyPower.Margin = new Padding(4, 2, 4, 2);
checkApplyPower.Name = "checkApplyPower";
checkApplyPower.Size = new Size(165, 36);
checkApplyPower.TabIndex = 25;
checkApplyPower.Text = "Auto Apply";
checkApplyPower.UseVisualStyleBackColor = true;
//
// buttonApplyPower
//
buttonApplyPower.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
buttonApplyPower.Location = new Point(20, 1081);
buttonApplyPower.Margin = new Padding(4, 2, 4, 2);
buttonApplyPower.Name = "buttonApplyPower";
buttonApplyPower.Size = new Size(324, 44);
buttonApplyPower.TabIndex = 24;
buttonApplyPower.Text = "Apply Power Limits";
buttonApplyPower.UseVisualStyleBackColor = true;
//
// panelCPU
//
panelCPU.Controls.Add(labelCPU);
panelCPU.Controls.Add(label2);
panelCPU.Controls.Add(trackCPU);
panelCPU.Location = new Point(184, 93);
panelCPU.Margin = new Padding(4);
panelCPU.Name = "panelCPU";
panelCPU.Size = new Size(160, 510);
panelCPU.TabIndex = 23;
//
// labelCPU
//
labelCPU.AutoSize = true;
labelCPU.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelCPU.Location = new Point(44, 40);
labelCPU.Margin = new Padding(4, 0, 4, 0);
labelCPU.Name = "labelCPU";
labelCPU.Size = new Size(61, 32);
labelCPU.TabIndex = 13;
labelCPU.Text = "CPU";
labelCPU.TextAlign = ContentAlignment.MiddleCenter;
//
// label2
//
label2.AutoSize = true;
label2.Location = new Point(44, 8);
label2.Margin = new Padding(4, 0, 4, 0);
label2.Name = "label2";
label2.Size = new Size(58, 32);
label2.TabIndex = 12;
label2.Text = "CPU";
label2.TextAlign = ContentAlignment.MiddleCenter;
//
// trackCPU
//
trackCPU.Location = new Point(48, 88);
trackCPU.Margin = new Padding(4, 2, 4, 2);
trackCPU.Maximum = 85;
trackCPU.Minimum = 15;
trackCPU.Name = "trackCPU";
trackCPU.Orientation = Orientation.Vertical;
trackCPU.Size = new Size(90, 416);
trackCPU.TabIndex = 11;
trackCPU.TickFrequency = 5;
trackCPU.Value = 80;
//
// panelTotal
//
panelTotal.Controls.Add(labelTotal);
panelTotal.Controls.Add(label1);
panelTotal.Controls.Add(trackTotal);
panelTotal.Location = new Point(16, 93);
panelTotal.Margin = new Padding(4);
panelTotal.Name = "panelTotal";
panelTotal.Size = new Size(160, 512);
panelTotal.TabIndex = 22;
//
// labelTotal
//
labelTotal.AutoSize = true;
labelTotal.Font = new Font("Segoe UI", 9F, FontStyle.Bold, GraphicsUnit.Point);
labelTotal.Location = new Point(46, 40);
labelTotal.Margin = new Padding(4, 0, 4, 0);
labelTotal.Name = "labelTotal";
labelTotal.Size = new Size(70, 32);
labelTotal.TabIndex = 12;
labelTotal.Text = "Total";
labelTotal.TextAlign = ContentAlignment.MiddleCenter;
//
// label1
//
label1.AutoSize = true;
label1.Location = new Point(48, 8);
label1.Margin = new Padding(4, 0, 4, 0);
label1.Name = "label1";
label1.Size = new Size(65, 32);
label1.TabIndex = 11;
label1.Text = "Total";
label1.TextAlign = ContentAlignment.MiddleCenter;
//
// trackTotal
//
trackTotal.Location = new Point(44, 88);
trackTotal.Margin = new Padding(4, 2, 4, 2);
trackTotal.Maximum = 150;
trackTotal.Minimum = 15;
trackTotal.Name = "trackTotal";
trackTotal.Orientation = Orientation.Vertical;
trackTotal.Size = new Size(90, 416);
trackTotal.TabIndex = 10;
trackTotal.TickFrequency = 5;
trackTotal.TickStyle = TickStyle.TopLeft;
trackTotal.Value = 125;
//
// labelApplied
//
labelApplied.AutoSize = true;
labelApplied.ForeColor = Color.Tomato;
labelApplied.Location = new Point(56, 54);
labelApplied.Margin = new Padding(4, 0, 4, 0);
labelApplied.Name = "labelApplied";
labelApplied.Size = new Size(143, 32);
labelApplied.TabIndex = 21;
labelApplied.Text = "Not Applied";
//
// pictureFine
//
pictureFine.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
pictureFine.BackgroundImageLayout = ImageLayout.Zoom;
pictureFine.Image = Properties.Resources.everything_is_fine_itsfine;
pictureFine.Location = new Point(20, 682);
pictureFine.Margin = new Padding(4, 2, 4, 2);
pictureFine.Name = "pictureFine";
pictureFine.Size = new Size(324, 268);
pictureFine.SizeMode = PictureBoxSizeMode.Zoom;
pictureFine.TabIndex = 20;
pictureFine.TabStop = false;
pictureFine.Visible = false;
//
// labelInfo
//
labelInfo.Location = new Point(24, 618);
labelInfo.Margin = new Padding(4, 0, 4, 0);
labelInfo.Name = "labelInfo";
labelInfo.Size = new Size(320, 330);
labelInfo.TabIndex = 19;
labelInfo.Text = "label";
//
// Fans
//
AutoScaleDimensions = new SizeF(192F, 192F);
AutoScaleMode = AutoScaleMode.Dpi;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
ClientSize = new Size(1178, 1159);
Controls.Add(panelFans);
Controls.Add(panelPower);
Margin = new Padding(4, 2, 4, 2);
MaximizeBox = false;
MdiChildrenMinimizedAnchorBottom = false;
MinimizeBox = false;
MinimumSize = new Size(26, 1230);
Name = "Fans";
ShowIcon = false;
ShowInTaskbar = false;
StartPosition = FormStartPosition.CenterScreen;
Text = "Fans and Power";
panelFans.ResumeLayout(false);
panelFans.PerformLayout();
((System.ComponentModel.ISupportInitialize)picturePerf).EndInit();
tableFanCharts.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)chartGPU).EndInit();
((System.ComponentModel.ISupportInitialize)chartCPU).EndInit();
panelPower.ResumeLayout(false);
panelPower.PerformLayout();
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
panelCPU.ResumeLayout(false);
panelCPU.PerformLayout();
((System.ComponentModel.ISupportInitialize)trackCPU).EndInit();
panelTotal.ResumeLayout(false);
panelTotal.PerformLayout();
((System.ComponentModel.ISupportInitialize)trackTotal).EndInit();
((System.ComponentModel.ISupportInitialize)pictureFine).EndInit();
ResumeLayout(false);
}
#endregion
private Panel panelFans;
private CheckBox checkAuto;
private Button buttonReset;
private Button buttonApply;
private Panel panelPower;
private CheckBox checkApplyPower;
private Button buttonApplyPower;
private Panel panelCPU;
private Label labelCPU;
private Label label2;
private TrackBar trackCPU;
private Panel panelTotal;
private Label labelTotal;
private Label label1;
private TrackBar trackTotal;
private Label labelApplied;
private PictureBox pictureFine;
private Label labelInfo;
private Label labelPowerLimits;
private TableLayoutPanel tableFanCharts;
private System.Windows.Forms.DataVisualization.Charting.Chart chartGPU;
private System.Windows.Forms.DataVisualization.Charting.Chart chartCPU;
private Label labelFans;
private PictureBox picturePerf;
private PictureBox pictureBox1;
private ComboBox comboBoost;
private Label labelBoost;
private Label labelTip;
}
}

View File

@@ -1,5 +1,9 @@
using System;
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Drawing.Imaging;
using System.Drawing.Text;
using System.IO;
using System.Windows.Forms.DataVisualization.Charting;
namespace GHelper
@@ -11,13 +15,11 @@ namespace GHelper
Series seriesCPU;
Series seriesGPU;
const int MaxTotal = 150;
const int MinTotal = 15;
const int DefaultTotal = 125;
const int MaxCPU = 90;
const int MinCPU = 15;
const int DefaultCPU = 80;
static string ChartPercToRPM(int percentage, string unit = "")
{
if (percentage == 0) return "OFF";
return (1800 + 200 * Math.Floor(percentage * 0.2)).ToString() + unit;
}
void SetChart(Chart chart, int device)
{
@@ -30,7 +32,7 @@ namespace GHelper
title = "CPU Fan Profile";
if (Program.settingsForm.perfName.Length > 0)
title += ": " + Program.settingsForm.perfName;
labelFans.Text = "Fan Profiles: " + Program.settingsForm.perfName;
if (chart.Titles.Count > 0)
chart.Titles[0].Text = title;
@@ -49,10 +51,8 @@ namespace GHelper
chart.ChartAreas[0].AxisY.LabelStyle.Font = new Font("Arial", 7F);
chart.ChartAreas[0].AxisY.CustomLabels.Add(-2, 2, "OFF");
for (int i = 1; i <= 9; i++)
chart.ChartAreas[0].AxisY.CustomLabels.Add(i * 10 - 2, i * 10 + 2, (1800 + 400 * i).ToString());
for (int i = 0; i <= 90; i += 10)
chart.ChartAreas[0].AxisY.CustomLabels.Add(i - 2, i + 2, ChartPercToRPM(i));
chart.ChartAreas[0].AxisY.CustomLabels.Add(98, 102, "RPM");
@@ -65,7 +65,18 @@ namespace GHelper
private void Fans_Shown(object? sender, EventArgs e)
{
Top = Program.settingsForm.Top;
if (Height > Program.settingsForm.Height)
{
Top = Program.settingsForm.Top + Program.settingsForm.Height - Height;
}
else
{
MinimumSize = new Size(0, Program.settingsForm.Height);
Height = Program.settingsForm.Height;
Top = Program.settingsForm.Top;
}
Left = Program.settingsForm.Left - Width - 5;
}
@@ -74,6 +85,9 @@ namespace GHelper
InitializeComponent();
labelTip.Visible = false;
labelTip.BackColor = Color.Transparent;
FormClosing += Fans_FormClosing;
seriesCPU = chartCPU.Series.Add("CPU");
@@ -91,11 +105,11 @@ namespace GHelper
buttonReset.Click += ButtonReset_Click;
buttonApply.Click += ButtonApply_Click;
trackTotal.Maximum = MaxTotal;
trackTotal.Minimum = MinTotal;
trackTotal.Maximum = ASUSWmi.MaxTotal;
trackTotal.Minimum = ASUSWmi.MinTotal;
trackCPU.Maximum = MaxCPU;
trackCPU.Minimum = MinCPU;
trackCPU.Maximum = ASUSWmi.MaxCPU;
trackCPU.Minimum = ASUSWmi.MinCPU;
trackCPU.Scroll += TrackCPU_Scroll;
trackTotal.Scroll += TrackTotal_Scroll;
@@ -103,25 +117,48 @@ namespace GHelper
buttonApplyPower.Click += ButtonApplyPower_Click;
checkAuto.Click += CheckAuto_Click;
checkApplyPower.Click += CheckApplyPower_Click;
//labelInfo.MaximumSize = new Size(280, 0);
labelInfo.Text = "Power Limits (PPT) is\nexperimental feature.\n\nValues will be applied\nonly after you click 'Apply'\nand reset after performance\nmode changes.\n\nUse carefully and\non your own risk!";
labelInfo.Text = "Power Limits (PPT) is\nexperimental feature.\n\nUse carefully and\non your own risk!";
LoadFans();
VisualisePower(true);
InitFans();
InitPower();
InitBoost();
comboBoost.SelectedIndexChanged += ComboBoost_Changed;
Shown += Fans_Shown;
}
public void InitBoost()
{
int boost = NativeMethods.GetCPUBoost();
if (boost >= 0)
comboBoost.SelectedIndex = Math.Min(boost, comboBoost.Items.Count - 1);
}
private void ComboBoost_Changed(object? sender, EventArgs e)
{
if (sender is null) return;
ComboBox cmb = (ComboBox)sender;
NativeMethods.SetCPUBoost(cmb.SelectedIndex);
}
private void CheckApplyPower_Click(object? sender, EventArgs e)
{
if (sender is null) return;
CheckBox chk = (CheckBox)sender;
Program.config.setConfigPerf("auto_apply_power", chk.Checked ? 1 : 0);
}
private void CheckAuto_Click(object? sender, EventArgs e)
{
if (sender is null)
return;
if (sender is null) return;
CheckBox chk = (CheckBox)sender;
Program.config.setConfig("auto_apply_" + Program.config.getConfig("performance_mode"), chk.Checked ? 1 : 0);
Program.config.setConfigPerf("auto_apply", chk.Checked ? 1 : 0);
}
private void Fans_FormClosing(object? sender, FormClosingEventArgs e)
@@ -135,76 +172,91 @@ namespace GHelper
private void ButtonApplyPower_Click(object? sender, EventArgs e)
{
int limit_total = trackTotal.Value;
int limit_cpu = trackCPU.Value;
Program.config.setConfig("limit_total", limit_total);
Program.config.setConfig("limit_cpu", limit_cpu);
Program.wmi.DeviceSet(ASUSWmi.PPT_TotalA0, limit_total);
Program.wmi.DeviceSet(ASUSWmi.PPT_TotalA1, limit_total);
Program.wmi.DeviceSet(ASUSWmi.PPT_CPUB0, limit_cpu);
Program.wmi.DeviceSet(ASUSWmi.PPT_CPUA2, limit_cpu);
labelApplied.ForeColor = Color.Blue;
labelApplied.Text = "Applied";
Program.settingsForm.SetPower();
ApplyLabel(true);
}
public void VisualisePower(bool init = false)
public void InitPower(bool changed = false)
{
bool cpuBmode = (Program.wmi.DeviceGet(ASUSWmi.PPT_CPUB0) >= 0); // 2022 model +
bool cpuAmode = (Program.wmi.DeviceGet(ASUSWmi.PPT_TotalA0) >= 0); // 2021 model +
panelPower.Visible = cpuAmode;
panelCPU.Visible = cpuBmode;
// Yes, that's stupid, but Total slider on 2021 model actually adjusts CPU PPT
if (!cpuBmode)
{
label1.Text = "CPU SPPT";
}
int limit_total;
int limit_cpu;
bool apply = Program.config.getConfigPerf("auto_apply_power") == 1;
if (init)
{
limit_total = Program.config.getConfig("limit_total");
limit_cpu = Program.config.getConfig("limit_cpu");
}
else
if (changed)
{
limit_total = trackTotal.Value;
limit_cpu = trackCPU.Value;
ApplyLabel(false);
}
else
{
limit_total = Program.config.getConfigPerf("limit_total");
limit_cpu = Program.config.getConfigPerf("limit_cpu");
ApplyLabel(apply);
}
if (limit_total < 0) limit_total = DefaultTotal;
if (limit_total > MaxTotal) limit_total = MaxTotal;
if (limit_total < MinTotal) limit_total = MinTotal;
if (limit_cpu < 0) limit_cpu = DefaultCPU;
if (limit_cpu > MaxCPU) limit_cpu = MaxCPU;
if (limit_cpu < MinCPU) limit_cpu = MinCPU;
if (limit_total < 0) limit_total = ASUSWmi.DefaultTotal;
if (limit_total > ASUSWmi.MaxTotal) limit_total = ASUSWmi.MaxTotal;
if (limit_total < ASUSWmi.MinTotal) limit_total = ASUSWmi.MinTotal;
if (limit_cpu < 0) limit_cpu = ASUSWmi.DefaultCPU;
if (limit_cpu > ASUSWmi.MaxCPU) limit_cpu = ASUSWmi.MaxCPU;
if (limit_cpu < ASUSWmi.MinCPU) limit_cpu = ASUSWmi.MinCPU;
if (limit_cpu > limit_total) limit_cpu = limit_total;
trackTotal.Value = limit_total;
trackCPU.Value = limit_cpu;
checkApplyPower.Checked = apply;
labelTotal.Text = trackTotal.Value.ToString() + "W";
labelCPU.Text = trackCPU.Value.ToString() + "W";
pictureFine.Visible = (limit_cpu > 85 || limit_total > 145);
Program.config.setConfigPerf("limit_total", limit_total);
Program.config.setConfigPerf("limit_cpu", limit_cpu);
}
private void TrackTotal_Scroll(object? sender, EventArgs e)
{
VisualisePower();
InitPower(true);
}
private void TrackCPU_Scroll(object? sender, EventArgs e)
{
VisualisePower();
InitPower(true);
}
public void ResetApplyLabel()
public void ApplyLabel(bool applied = false)
{
labelApplied.ForeColor = Color.Red;
labelApplied.Text = "Not Applied";
if (applied)
{
labelApplied.ForeColor = Color.Blue;
labelApplied.Text = "Applied";
}
else
{
labelApplied.ForeColor = Color.Red;
labelApplied.Text = "Not Applied";
}
}
public void LoadFans()
public void InitFans()
{
SetChart(chartCPU, 0);
@@ -213,7 +265,7 @@ namespace GHelper
LoadProfile(seriesCPU, 0);
LoadProfile(seriesGPU, 1);
int auto_apply = Program.config.getConfig("auto_apply_" + Program.config.getConfig("performance_mode"));
int auto_apply = Program.config.getConfigPerf("auto_apply");
checkAuto.Checked = (auto_apply == 1);
@@ -275,20 +327,25 @@ namespace GHelper
private void ButtonReset_Click(object? sender, EventArgs e)
{
LoadProfile(seriesCPU, 0, 1);
LoadProfile(seriesGPU, 1, 1);
checkAuto.Checked = false;
Program.config.setConfig("auto_apply_" + Program.config.getConfig("performance_mode"), 0);
checkApplyPower.Checked = false;
Program.config.setConfigPerf("auto_apply", 0);
Program.config.setConfigPerf("auto_apply_power", 0);
Program.wmi.DeviceSet(ASUSWmi.PerformanceMode, Program.config.getConfig("performance_mode"));
ResetApplyLabel();
ApplyLabel(false);
}
private void ChartCPU_MouseUp(object? sender, MouseEventArgs e)
{
curPoint = null;
labelTip.Visible = false;
}
private void ChartCPU_MouseMove(object? sender, MouseEventArgs e)
@@ -326,13 +383,18 @@ namespace GHelper
if (dy < 0) dy = 0;
if (dy > 100) dy = 100;
dymin = (dx - 60) * 1.2;
dymin = (dx - 65) * 1.2;
if (dy < dymin) dy = dymin;
curPoint.XValue = dx;
curPoint.YValues[0] = dy;
labelTip.Visible = true;
labelTip.Text = Math.Round(dx) + "C, " + ChartPercToRPM((int)dy, " RPM");
labelTip.Top = e.Y + ((Control)sender).Top;
labelTip.Left = e.X;
}
catch
{

View File

@@ -15,10 +15,16 @@
<AssemblyName>GHelper</AssemblyName>
<PlatformTarget>x64</PlatformTarget>
<ProduceReferenceAssembly>False</ProduceReferenceAssembly>
<AssemblyVersion>0.16</AssemblyVersion>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<AssemblyVersion>0.31</AssemblyVersion>
</PropertyGroup>
<ItemGroup>
<Compile Remove="screenshots\**" />
<EmbeddedResource Remove="screenshots\**" />
<None Remove="screenshots\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Resources\eco.ico" />
<None Remove="Resources\icons8-charging-battery-48.png" />
@@ -32,13 +38,14 @@
<ItemGroup>
<Content Include="favicon.ico">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="hidlibrary" Version="3.3.40" />
<PackageReference Include="HidSharpCore" Version="1.2.1.1" />
<PackageReference Include="NvAPIWrapper.Net" Version="0.8.1.101" />
<PackageReference Include="System.Management" Version="7.0.0" />
<PackageReference Include="TaskScheduler" Version="2.10.1" />
<PackageReference Include="WinForms.DataVisualization" Version="1.7.0" />
@@ -101,8 +108,4 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="screenshots\" />
</ItemGroup>
</Project>

485
app/Gpu/AmdAdl2.cs Normal file
View File

@@ -0,0 +1,485 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace AmdAdl2;
#region Export Struct
[StructLayout(LayoutKind.Sequential)]
public struct ADLSingleSensorData {
public int Supported;
public int Value;
}
[StructLayout(LayoutKind.Sequential)]
public struct ADLPMLogDataOutput {
int Size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Adl2.ADL_PMLOG_MAX_SENSORS)]
public ADLSingleSensorData[] Sensors;
}
[StructLayout(LayoutKind.Sequential)]
public struct ADLGcnInfo
{
public int CuCount; //Number of compute units on the ASIC.
public int TexCount; //Number of texture mapping units.
public int RopCount; //Number of Render backend Units.
public int ASICFamilyId; //Such SI, VI. See /inc/asic_reg/atiid.h for family ids
public int ASICRevisionId; //Such as Ellesmere, Fiji. For example - VI family revision ids are stored in /inc/asic_reg/vi_id.h
}
[Flags]
public enum ADLAsicFamilyType {
Undefined = 0,
Discrete = 1 << 0,
Integrated = 1 << 1,
Workstation = 1 << 2,
FireMV = 1 << 3,
Xgp = 1 << 4,
Fusion = 1 << 5,
Firestream = 1 << 6,
Embedded = 1 << 7,
}
public enum ADLSensorType {
SENSOR_MAXTYPES = 0,
PMLOG_CLK_GFXCLK = 1, // Current graphic clock value in MHz
PMLOG_CLK_MEMCLK = 2, // Current memory clock value in MHz
PMLOG_CLK_SOCCLK = 3,
PMLOG_CLK_UVDCLK1 = 4,
PMLOG_CLK_UVDCLK2 = 5,
PMLOG_CLK_VCECLK = 6,
PMLOG_CLK_VCNCLK = 7,
PMLOG_TEMPERATURE_EDGE = 8, // Current edge of the die temperature value in C
PMLOG_TEMPERATURE_MEM = 9,
PMLOG_TEMPERATURE_VRVDDC = 10,
PMLOG_TEMPERATURE_VRMVDD = 11,
PMLOG_TEMPERATURE_LIQUID = 12,
PMLOG_TEMPERATURE_PLX = 13,
PMLOG_FAN_RPM = 14, // Current fan RPM value
PMLOG_FAN_PERCENTAGE = 15, // Current ratio of fan RPM and max RPM
PMLOG_SOC_VOLTAGE = 16,
PMLOG_SOC_POWER = 17,
PMLOG_SOC_CURRENT = 18,
PMLOG_INFO_ACTIVITY_GFX = 19, // Current graphic activity level in percentage
PMLOG_INFO_ACTIVITY_MEM = 20, // Current memory activity level in percentage
PMLOG_GFX_VOLTAGE = 21, // Current graphic voltage in mV
PMLOG_MEM_VOLTAGE = 22,
PMLOG_ASIC_POWER = 23, // Current ASIC power draw in Watt
PMLOG_TEMPERATURE_VRSOC = 24,
PMLOG_TEMPERATURE_VRMVDD0 = 25,
PMLOG_TEMPERATURE_VRMVDD1 = 26,
PMLOG_TEMPERATURE_HOTSPOT = 27, // Current center of the die temperature value in C
PMLOG_TEMPERATURE_GFX = 28,
PMLOG_TEMPERATURE_SOC = 29,
PMLOG_GFX_POWER = 30,
PMLOG_GFX_CURRENT = 31,
PMLOG_TEMPERATURE_CPU = 32,
PMLOG_CPU_POWER = 33,
PMLOG_CLK_CPUCLK = 34,
PMLOG_THROTTLER_STATUS = 35, // A bit map of GPU throttle information. If a bit is set, the bit represented type of thorttling occurred in the last metrics sampling period
PMLOG_CLK_VCN1CLK1 = 36,
PMLOG_CLK_VCN1CLK2 = 37,
PMLOG_SMART_POWERSHIFT_CPU = 38,
PMLOG_SMART_POWERSHIFT_DGPU = 39,
PMLOG_BUS_SPEED = 40, // Current PCIE bus speed running
PMLOG_BUS_LANES = 41, // Current PCIE bus lanes using
PMLOG_TEMPERATURE_LIQUID0 = 42,
PMLOG_TEMPERATURE_LIQUID1 = 43,
PMLOG_CLK_FCLK = 44,
PMLOG_THROTTLER_STATUS_CPU = 45,
PMLOG_SSPAIRED_ASICPOWER = 46, // apuPower
PMLOG_SSTOTAL_POWERLIMIT = 47, // Total Power limit
PMLOG_SSAPU_POWERLIMIT = 48, // APU Power limit
PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
PMLOG_BOARD_POWER = 73,
PMLOG_MAX_SENSORS_REAL
};
//Throttle Status
[Flags]
public enum ADL_THROTTLE_NOTIFICATION {
ADL_PMLOG_THROTTLE_POWER = 1 << 0,
ADL_PMLOG_THROTTLE_THERMAL = 1 << 1,
ADL_PMLOG_THROTTLE_CURRENT = 1 << 2,
};
public enum ADL_PMLOG_SENSORS {
ADL_SENSOR_MAXTYPES = 0,
ADL_PMLOG_CLK_GFXCLK = 1,
ADL_PMLOG_CLK_MEMCLK = 2,
ADL_PMLOG_CLK_SOCCLK = 3,
ADL_PMLOG_CLK_UVDCLK1 = 4,
ADL_PMLOG_CLK_UVDCLK2 = 5,
ADL_PMLOG_CLK_VCECLK = 6,
ADL_PMLOG_CLK_VCNCLK = 7,
ADL_PMLOG_TEMPERATURE_EDGE = 8,
ADL_PMLOG_TEMPERATURE_MEM = 9,
ADL_PMLOG_TEMPERATURE_VRVDDC = 10,
ADL_PMLOG_TEMPERATURE_VRMVDD = 11,
ADL_PMLOG_TEMPERATURE_LIQUID = 12,
ADL_PMLOG_TEMPERATURE_PLX = 13,
ADL_PMLOG_FAN_RPM = 14,
ADL_PMLOG_FAN_PERCENTAGE = 15,
ADL_PMLOG_SOC_VOLTAGE = 16,
ADL_PMLOG_SOC_POWER = 17,
ADL_PMLOG_SOC_CURRENT = 18,
ADL_PMLOG_INFO_ACTIVITY_GFX = 19,
ADL_PMLOG_INFO_ACTIVITY_MEM = 20,
ADL_PMLOG_GFX_VOLTAGE = 21,
ADL_PMLOG_MEM_VOLTAGE = 22,
ADL_PMLOG_ASIC_POWER = 23,
ADL_PMLOG_TEMPERATURE_VRSOC = 24,
ADL_PMLOG_TEMPERATURE_VRMVDD0 = 25,
ADL_PMLOG_TEMPERATURE_VRMVDD1 = 26,
ADL_PMLOG_TEMPERATURE_HOTSPOT = 27,
ADL_PMLOG_TEMPERATURE_GFX = 28,
ADL_PMLOG_TEMPERATURE_SOC = 29,
ADL_PMLOG_GFX_POWER = 30,
ADL_PMLOG_GFX_CURRENT = 31,
ADL_PMLOG_TEMPERATURE_CPU = 32,
ADL_PMLOG_CPU_POWER = 33,
ADL_PMLOG_CLK_CPUCLK = 34,
ADL_PMLOG_THROTTLER_STATUS = 35, // GFX
ADL_PMLOG_CLK_VCN1CLK1 = 36,
ADL_PMLOG_CLK_VCN1CLK2 = 37,
ADL_PMLOG_SMART_POWERSHIFT_CPU = 38,
ADL_PMLOG_SMART_POWERSHIFT_DGPU = 39,
ADL_PMLOG_BUS_SPEED = 40,
ADL_PMLOG_BUS_LANES = 41,
ADL_PMLOG_TEMPERATURE_LIQUID0 = 42,
ADL_PMLOG_TEMPERATURE_LIQUID1 = 43,
ADL_PMLOG_CLK_FCLK = 44,
ADL_PMLOG_THROTTLER_STATUS_CPU = 45,
ADL_PMLOG_SSPAIRED_ASICPOWER = 46, // apuPower
ADL_PMLOG_SSTOTAL_POWERLIMIT = 47, // Total Power limit
ADL_PMLOG_SSAPU_POWERLIMIT = 48, // APU Power limit
ADL_PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit
ADL_PMLOG_TEMPERATURE_HOTSPOT_GCD = 50,
ADL_PMLOG_TEMPERATURE_HOTSPOT_MCD = 51,
ADL_PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54,
ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55,
ADL_PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56,
ADL_PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57,
ADL_PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58,
ADL_PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59,
ADL_PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60,
ADL_PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61,
ADL_PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62,
ADL_PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63,
ADL_PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64,
ADL_PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65,
ADL_PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66,
ADL_PMLOG_THROTTLER_PPT0_PERCENTAGE = 67,
ADL_PMLOG_THROTTLER_PPT1_PERCENTAGE = 68,
ADL_PMLOG_THROTTLER_PPT2_PERCENTAGE = 69,
ADL_PMLOG_THROTTLER_PPT3_PERCENTAGE = 70,
ADL_PMLOG_THROTTLER_FIT_PERCENTAGE = 71,
ADL_PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72,
ADL_PMLOG_BOARD_POWER = 73,
ADL_PMLOG_MAX_SENSORS_REAL
}
#region ADLAdapterInfo
/// <summary> ADLAdapterInfo Structure</summary>
[StructLayout(LayoutKind.Sequential)]
public struct ADLAdapterInfo {
/// <summary>The size of the structure</summary>
int Size;
/// <summary> Adapter Index</summary>
public int AdapterIndex;
/// <summary> Adapter UDID</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string UDID;
/// <summary> Adapter Bus Number</summary>
public int BusNumber;
/// <summary> Adapter Driver Number</summary>
public int DriverNumber;
/// <summary> Adapter Function Number</summary>
public int FunctionNumber;
/// <summary> Adapter Vendor ID</summary>
public int VendorID;
/// <summary> Adapter Adapter name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string AdapterName;
/// <summary> Adapter Display name</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string DisplayName;
/// <summary> Adapter Present status</summary>
public int Present;
/// <summary> Adapter Exist status</summary>
public int Exist;
/// <summary> Adapter Driver Path</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string DriverPath;
/// <summary> Adapter Driver Ext Path</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string DriverPathExt;
/// <summary> Adapter PNP String</summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string PNPString;
/// <summary> OS Display Index</summary>
public int OSDisplayIndex;
}
/// <summary> ADLAdapterInfo Array</summary>
[StructLayout(LayoutKind.Sequential)]
public struct ADLAdapterInfoArray {
/// <summary> ADLAdapterInfo Array </summary>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Adl2.ADL_MAX_ADAPTERS)]
public ADLAdapterInfo[] ADLAdapterInfo;
}
#endregion ADLAdapterInfo
#region ADLDisplayInfo
/// <summary> ADLDisplayID Structure</summary>
[StructLayout(LayoutKind.Sequential)]
public struct ADLDisplayID {
/// <summary> Display Logical Index </summary>
public int DisplayLogicalIndex;
/// <summary> Display Physical Index </summary>
public int DisplayPhysicalIndex;
/// <summary> Adapter Logical Index </summary>
public int DisplayLogicalAdapterIndex;
/// <summary> Adapter Physical Index </summary>
public int DisplayPhysicalAdapterIndex;
}
/// <summary> ADLDisplayInfo Structure</summary>
[StructLayout(LayoutKind.Sequential)]
public struct ADLDisplayInfo {
/// <summary> Display Index </summary>
public ADLDisplayID DisplayID;
/// <summary> Display Controller Index </summary>
public int DisplayControllerIndex;
/// <summary> Display Name </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string DisplayName;
/// <summary> Display Manufacturer Name </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Adl2.ADL_MAX_PATH)]
public string DisplayManufacturerName;
/// <summary> Display Type : < The Display type. CRT, TV,CV,DFP are some of display types,</summary>
public int DisplayType;
/// <summary> Display output type </summary>
public int DisplayOutputType;
/// <summary> Connector type</summary>
public int DisplayConnector;
///<summary> Indicating the display info bits' mask.<summary>
public int DisplayInfoMask;
///<summary> Indicating the display info value.<summary>
public int DisplayInfoValue;
}
#endregion ADLDisplayInfo
#endregion Export Struct
public class Adl2 {
public const string Atiadlxx_FileName = "atiadlxx.dll";
#region Internal Constant
/// <summary> Define the maximum path</summary>
public const int ADL_MAX_PATH = 256;
/// <summary> Define the maximum adapters</summary>
public const int ADL_MAX_ADAPTERS = 40 /* 150 */;
/// <summary> Define the maximum displays</summary>
public const int ADL_MAX_DISPLAYS = 40 /* 150 */;
/// <summary> Define the maximum device name length</summary>
public const int ADL_MAX_DEVICENAME = 32;
/// <summary> Define the successful</summary>
public const int ADL_SUCCESS = 0;
/// <summary> Define the failure</summary>
public const int ADL_FAIL = -1;
/// <summary> Define the driver ok</summary>
public const int ADL_DRIVER_OK = 0;
/// <summary> Maximum number of GL-Sync ports on the GL-Sync module </summary>
public const int ADL_MAX_GLSYNC_PORTS = 8;
/// <summary> Maximum number of GL-Sync ports on the GL-Sync module </summary>
public const int ADL_MAX_GLSYNC_PORT_LEDS = 8;
/// <summary> Maximum number of ADLMOdes for the adapter </summary>
public const int ADL_MAX_NUM_DISPLAYMODES = 1024;
/// <summary> Performance Metrics Log max sensors number </summary>
public const int ADL_PMLOG_MAX_SENSORS = 256;
#endregion Internal Constant
// ///// <summary> ADL Create Function to create ADL Data</summary>
/// <param name="enumConnectedAdapters">If it is 1, then ADL will only return the physical exist adapters </param>
///// <returns> retrun ADL Error Code</returns>
public static int ADL2_Main_Control_Create(int enumConnectedAdapters, out IntPtr adlContextHandle) {
return NativeMethods.ADL2_Main_Control_Create(ADL_Main_Memory_Alloc_Impl_Reference, enumConnectedAdapters, out adlContextHandle);
}
public static void FreeMemory(IntPtr buffer) {
Memory_Free_Impl(buffer);
}
private static bool? isDllLoaded;
public static bool Load() {
if (isDllLoaded != null)
return isDllLoaded.Value;
try {
Marshal.PrelinkAll(typeof(Adl2));
isDllLoaded = true;
} catch (Exception e) when (e is DllNotFoundException or EntryPointNotFoundException) {
Debug.WriteLine(e);
isDllLoaded = false;
}
return isDllLoaded.Value;
}
private static NativeMethods.ADL_Main_Memory_Alloc ADL_Main_Memory_Alloc_Impl_Reference = Memory_Alloc_Impl;
/// <summary> Build in memory allocation function</summary>
/// <param name="size">input size</param>
/// <returns>return the memory buffer</returns>
private static IntPtr Memory_Alloc_Impl(int size) {
return Marshal.AllocCoTaskMem(size);
}
/// <summary> Build in memory free function</summary>
/// <param name="buffer">input buffer</param>
private static void Memory_Free_Impl(IntPtr buffer) {
if (IntPtr.Zero != buffer) {
Marshal.FreeCoTaskMem(buffer);
}
}
public static class NativeMethods {
/// <summary> ADL Memory allocation function allows ADL to callback for memory allocation</summary>
/// <param name="size">input size</param>
/// <returns> retrun ADL Error Code</returns>
public delegate IntPtr ADL_Main_Memory_Alloc(int size);
// ///// <summary> ADL Create Function to create ADL Data</summary>
/// <param name="callback">Call back functin pointer which is ised to allocate memeory </param>
/// <param name="enumConnectedAdapters">If it is 1, then ADL will only retuen the physical exist adapters </param>
///// <returns> retrun ADL Error Code</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Main_Control_Create(ADL_Main_Memory_Alloc callback, int enumConnectedAdapters, out IntPtr adlContextHandle);
/// <summary> ADL Destroy Function to free up ADL Data</summary>
/// <returns> retrun ADL Error Code</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Main_Control_Destroy(IntPtr adlContextHandle);
/// <summary> ADL Function to get the number of adapters</summary>
/// <param name="numAdapters">return number of adapters</param>
/// <returns> retrun ADL Error Code</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Adapter_NumberOfAdapters_Get(IntPtr adlContextHandle, out int numAdapters);
/// <summary> ADL Function to get the GPU adapter information</summary>
/// <param name="info">return GPU adapter information</param>
/// <param name="inputSize">the size of the GPU adapter struct</param>
/// <returns> retrun ADL Error Code</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Adapter_AdapterInfo_Get(IntPtr adlContextHandle, IntPtr info, int inputSize);
/// <summary> Function to determine if the adapter is active or not.</summary>
/// <remarks>The function is used to check if the adapter associated with iAdapterIndex is active</remarks>
/// <param name="adapterIndex"> Adapter Index.</param>
/// <param name="status"> Status of the adapter. True: Active; False: Dsiabled</param>
/// <returns>Non zero is successfull</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Adapter_Active_Get(IntPtr adlContextHandle, int adapterIndex, out int status);
/// <summary>Get display information based on adapter index</summary>
/// <param name="adapterIndex">Adapter Index</param>
/// <param name="numDisplays">return the total number of supported displays</param>
/// <param name="displayInfoArray">return ADLDisplayInfo Array for supported displays' information</param>
/// <param name="forceDetect">force detect or not</param>
/// <returns>return ADL Error Code</returns>
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Display_DisplayInfo_Get(
IntPtr adlContextHandle,
int adapterIndex,
out int numDisplays,
out IntPtr displayInfoArray,
int forceDetect
);
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Overdrive_Caps(
IntPtr adlContextHandle,
int adapterIndex,
out int supported,
out int enabled,
out int version
);
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_New_QueryPMLogData_Get(IntPtr adlContextHandle, int adapterIndex, out ADLPMLogDataOutput adlpmLogDataOutput);
[DllImport(Atiadlxx_FileName)]
public static extern int ADL2_Adapter_ASICFamilyType_Get(IntPtr adlContextHandle, int adapterIndex, out ADLAsicFamilyType asicFamilyType, out int asicFamilyTypeValids);
}
}

View File

@@ -0,0 +1,92 @@
using System.Runtime.InteropServices;
using AmdAdl2;
namespace GHelper.Gpu;
// Reference: https://github.com/GPUOpen-LibrariesAndSDKs/display-library/blob/master/Sample-Managed/Program.cs
public class AmdGpuTemperatureProvider : IGpuTemperatureProvider {
private bool _isReady;
private IntPtr _adlContextHandle;
private readonly ADLAdapterInfo _internalDiscreteAdapter;
public AmdGpuTemperatureProvider() {
if (!Adl2.Load())
return;
if (Adl2.ADL2_Main_Control_Create(1, out _adlContextHandle) != Adl2.ADL_SUCCESS)
return;
Adl2.NativeMethods.ADL2_Adapter_NumberOfAdapters_Get(_adlContextHandle, out int numberOfAdapters);
if (numberOfAdapters <= 0)
return;
ADLAdapterInfoArray osAdapterInfoData = new();
int osAdapterInfoDataSize = Marshal.SizeOf(osAdapterInfoData);
IntPtr AdapterBuffer = Marshal.AllocCoTaskMem(osAdapterInfoDataSize);
Marshal.StructureToPtr(osAdapterInfoData, AdapterBuffer, false);
if (Adl2.NativeMethods.ADL2_Adapter_AdapterInfo_Get(_adlContextHandle, AdapterBuffer, osAdapterInfoDataSize) != Adl2.ADL_SUCCESS)
return;
osAdapterInfoData = (ADLAdapterInfoArray) Marshal.PtrToStructure(AdapterBuffer, osAdapterInfoData.GetType())!;
const int amdVendorId = 1002;
// Determine which GPU is internal discrete AMD GPU
ADLAdapterInfo internalDiscreteAdapter =
osAdapterInfoData.ADLAdapterInfo
.FirstOrDefault(adapter => {
if (adapter.Exist == 0 || adapter.Present == 0)
return false;
if (adapter.VendorID != amdVendorId)
return false;
if (Adl2.NativeMethods.ADL2_Adapter_ASICFamilyType_Get(_adlContextHandle, adapter.AdapterIndex, out ADLAsicFamilyType asicFamilyType, out int asicFamilyTypeValids) != Adl2.ADL_SUCCESS)
return false;
asicFamilyType = (ADLAsicFamilyType) ((int) asicFamilyType & asicFamilyTypeValids);
// FIXME: is this correct for G14 2022?
return (asicFamilyType & ADLAsicFamilyType.Discrete) != 0;
});
if (internalDiscreteAdapter.Exist == 0)
return;
_internalDiscreteAdapter = internalDiscreteAdapter;
_isReady = true;
}
public bool IsValid => _isReady && _adlContextHandle != IntPtr.Zero;
public int? GetCurrentTemperature() {
if (!IsValid)
return null;
if (Adl2.NativeMethods.ADL2_New_QueryPMLogData_Get(_adlContextHandle, _internalDiscreteAdapter.AdapterIndex, out ADLPMLogDataOutput adlpmLogDataOutput) != Adl2.ADL_SUCCESS)
return null;
ADLSingleSensorData temperatureSensor = adlpmLogDataOutput.Sensors[(int) ADLSensorType.PMLOG_TEMPERATURE_EDGE];
if (temperatureSensor.Supported == 0)
return null;
return temperatureSensor.Value;
}
private void ReleaseUnmanagedResources() {
if (_adlContextHandle != IntPtr.Zero) {
Adl2.NativeMethods.ADL2_Main_Control_Destroy(_adlContextHandle);
_adlContextHandle = IntPtr.Zero;
_isReady = false;
}
}
public void Dispose() {
ReleaseUnmanagedResources();
GC.SuppressFinalize(this);
}
~AmdGpuTemperatureProvider() {
ReleaseUnmanagedResources();
}
}

View File

@@ -0,0 +1,6 @@
namespace GHelper.Gpu;
public interface IGpuTemperatureProvider : IDisposable {
bool IsValid { get; }
int? GetCurrentTemperature();
}

View File

@@ -0,0 +1,42 @@
using NvAPIWrapper.GPU;
using NvAPIWrapper.Native;
using NvAPIWrapper.Native.Exceptions;
using NvAPIWrapper.Native.GPU;
using NvAPIWrapper.Native.Interfaces.GPU;
namespace GHelper.Gpu;
public class NvidiaGpuTemperatureProvider : IGpuTemperatureProvider {
private readonly PhysicalGPU? _internalGpu;
public NvidiaGpuTemperatureProvider() {
_internalGpu = GetInternalDiscreteGpu();
}
public bool IsValid => _internalGpu != null;
public int? GetCurrentTemperature() {
if (!IsValid)
return null;
PhysicalGPU internalGpu = _internalGpu!;
IThermalSensor? gpuSensor =
GPUApi.GetThermalSettings(internalGpu.Handle).Sensors
.FirstOrDefault(s => s.Target == ThermalSettingsTarget.GPU);
return gpuSensor?.CurrentTemperature;
}
public void Dispose() {
}
private static PhysicalGPU? GetInternalDiscreteGpu() {
try {
return PhysicalGPU
.GetPhysicalGPUs()
.FirstOrDefault(gpu => gpu.SystemType == SystemType.Laptop);
} catch {
return null;
}
}
}

86
app/HardwareMonitor.cs Normal file
View File

@@ -0,0 +1,86 @@
using System.Diagnostics;
using GHelper.Gpu;
public static class HardwareMonitor
{
private static IGpuTemperatureProvider? GpuTemperatureProvider;
public static float? cpuTemp = -1;
public static float? batteryDischarge = -1;
public static int? gpuTemp = null;
public static void ReadSensors()
{
cpuTemp = -1;
batteryDischarge = -1;
try
{
var ct = new PerformanceCounter("Thermal Zone Information", "Temperature", @"\_TZ.THRM", true);
cpuTemp = ct.NextValue() - 273;
ct.Dispose();
} catch
{
Logger.WriteLine("Failed reading CPU temp");
}
try
{
var cb = new PerformanceCounter("Power Meter", "Power", "Power Meter (0)", true);
batteryDischarge = cb.NextValue() / 1000;
cb.Dispose();
} catch
{
Logger.WriteLine("Failed reading Battery discharge");
}
try
{
gpuTemp = GpuTemperatureProvider?.GetCurrentTemperature();
} catch (Exception ex) {
gpuTemp = null;
Logger.WriteLine("Failed reading GPU temp");
Logger.WriteLine(ex.ToString());
}
}
public static void RecreateGpuTemperatureProviderWithRetry() {
RecreateGpuTemperatureProvider();
// Re-enabling the discrete GPU takes a bit of time,
// so a simple workaround is to refresh again after that happens
Task.Run(async () => {
await Task.Delay(TimeSpan.FromSeconds(3));
RecreateGpuTemperatureProvider();
});
}
public static void RecreateGpuTemperatureProvider() {
try {
GpuTemperatureProvider?.Dispose();
// Detect valid GPU temperature provider.
// We start with NVIDIA because there's always at least an integrated AMD GPU
IGpuTemperatureProvider gpuTemperatureProvider = new NvidiaGpuTemperatureProvider();
if (gpuTemperatureProvider.IsValid) {
GpuTemperatureProvider = gpuTemperatureProvider;
return;
}
gpuTemperatureProvider.Dispose();
gpuTemperatureProvider = new AmdGpuTemperatureProvider();
if (gpuTemperatureProvider.IsValid) {
GpuTemperatureProvider = gpuTemperatureProvider;
return;
}
gpuTemperatureProvider.Dispose();
GpuTemperatureProvider = null;
} finally {
Logger.WriteLine($"GpuTemperatureProvider: {GpuTemperatureProvider?.GetType().Name}");
}
}
}

67
app/HighDpiHelper.cs Normal file
View File

@@ -0,0 +1,67 @@
using System.Drawing.Drawing2D;
public static class HighDpiHelper
{
public static void AdjustControlImagesDpiScale(Control container, float baseScale = 2)
{
var dpiScale = GetDpiScale(container).Value;
AdjustControlImagesDpiScale(container.Controls, dpiScale / baseScale);
}
public static void AdjustButtonDpiScale(ButtonBase button, float dpiScale)
{
var image = button.Image;
if (image == null)
return;
button.Image = ScaleImage(image, dpiScale);
}
private static void AdjustControlImagesDpiScale(Control.ControlCollection controls, float dpiScale)
{
foreach (Control control in controls)
{
var button = control as ButtonBase;
if (button != null)
AdjustButtonDpiScale(button, dpiScale);
AdjustControlImagesDpiScale(control.Controls, dpiScale);
}
}
public static Lazy<float> GetDpiScale(Control control)
{
return new Lazy<float>(() =>
{
using (var graphics = control.CreateGraphics())
return graphics.DpiX / 96.0f;
});
}
private static Image ScaleImage(Image image, float dpiScale)
{
var newSize = ScaleSize(image.Size, dpiScale);
var newBitmap = new Bitmap(newSize.Width, newSize.Height);
using (var g = Graphics.FromImage(newBitmap))
{
// According to this blog post http://blogs.msdn.com/b/visualstudio/archive/2014/03/19/improving-high-dpi-support-for-visual-studio-2013.aspx
// NearestNeighbor is more adapted for 200% and 200%+ DPI
var interpolationMode = InterpolationMode.HighQualityBicubic;
if (dpiScale >= 2.0f)
interpolationMode = InterpolationMode.NearestNeighbor;
g.InterpolationMode = interpolationMode;
g.DrawImage(image, new Rectangle(new Point(), newSize));
}
return newBitmap;
}
private static Size ScaleSize(Size size, float scale)
{
return new Size((int)(size.Width * scale), (int)(size.Height * scale));
}
}

39
app/Logger.cs Normal file
View File

@@ -0,0 +1,39 @@
using System.Diagnostics;
public static class Logger
{
static string appPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\GHelper";
static string logFile = appPath + "\\log.txt";
public static void WriteLine(string logMessage)
{
Debug.WriteLine(logMessage);
if (!Directory.Exists(appPath)) Directory.CreateDirectory(appPath);
try
{
using (StreamWriter w = File.AppendText(logFile))
{
w.WriteLine($"{DateTime.Now}: {logMessage}");
w.Close();
}
}
catch { }
if (new Random().Next(100) == 1) Cleanup();
}
public static void Cleanup()
{
try
{
var file = File.ReadAllLines(logFile);
int skip = Math.Max(0, file.Count() - 500);
File.WriteAllLines(logFile, file.Skip(skip).ToArray());
}
catch { }
}
}

691
app/NativeMethods.cs Normal file
View File

@@ -0,0 +1,691 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using static Tools.ScreenInterrogatory;
namespace Tools
{
public static class ScreenInterrogatory
{
public const int ERROR_SUCCESS = 0;
#region enums
public enum QUERY_DEVICE_CONFIG_FLAGS : uint
{
QDC_ALL_PATHS = 0x00000001,
QDC_ONLY_ACTIVE_PATHS = 0x00000002,
QDC_DATABASE_CURRENT = 0x00000004
}
public enum DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY : uint
{
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER = 0xFFFFFFFF,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15 = 0,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO = 1,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO = 2,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO = 3,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI = 4,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI = 5,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS = 6,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN = 8,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI = 9,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL = 10,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED = 11,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL = 12,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED = 13,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE = 14,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_MIRACAST = 15,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL = 0x80000000,
DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCANLINE_ORDERING : uint
{
DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED = 0,
DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE = 1,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED = 2,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST = 3,
DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_ROTATION : uint
{
DISPLAYCONFIG_ROTATION_IDENTITY = 1,
DISPLAYCONFIG_ROTATION_ROTATE90 = 2,
DISPLAYCONFIG_ROTATION_ROTATE180 = 3,
DISPLAYCONFIG_ROTATION_ROTATE270 = 4,
DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_SCALING : uint
{
DISPLAYCONFIG_SCALING_IDENTITY = 1,
DISPLAYCONFIG_SCALING_CENTERED = 2,
DISPLAYCONFIG_SCALING_STRETCHED = 3,
DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
DISPLAYCONFIG_SCALING_CUSTOM = 5,
DISPLAYCONFIG_SCALING_PREFERRED = 128,
DISPLAYCONFIG_SCALING_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_PIXELFORMAT : uint
{
DISPLAYCONFIG_PIXELFORMAT_8BPP = 1,
DISPLAYCONFIG_PIXELFORMAT_16BPP = 2,
DISPLAYCONFIG_PIXELFORMAT_24BPP = 3,
DISPLAYCONFIG_PIXELFORMAT_32BPP = 4,
DISPLAYCONFIG_PIXELFORMAT_NONGDI = 5,
DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32 = 0xffffffff
}
public enum DISPLAYCONFIG_MODE_INFO_TYPE : uint
{
DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
}
public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
{
DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME = 1,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME = 2,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE = 3,
DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME = 4,
DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE = 5,
DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_BASE_TYPE = 6,
DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32 = 0xFFFFFFFF
}
#endregion
#region structs
[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
public uint LowPart;
public int HighPart;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_SOURCE_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_TARGET_INFO
{
public LUID adapterId;
public uint id;
public uint modeInfoIdx;
private DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
private DISPLAYCONFIG_ROTATION rotation;
private DISPLAYCONFIG_SCALING scaling;
private DISPLAYCONFIG_RATIONAL refreshRate;
private DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
public bool targetAvailable;
public uint statusFlags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_RATIONAL
{
public uint Numerator;
public uint Denominator;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_INFO
{
public DISPLAYCONFIG_PATH_SOURCE_INFO sourceInfo;
public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
public uint flags;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_2DREGION
{
public uint cx;
public uint cy;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
{
public ulong pixelRate;
public DISPLAYCONFIG_RATIONAL hSyncFreq;
public DISPLAYCONFIG_RATIONAL vSyncFreq;
public DISPLAYCONFIG_2DREGION activeSize;
public DISPLAYCONFIG_2DREGION totalSize;
public uint videoStandard;
public DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_MODE
{
public DISPLAYCONFIG_VIDEO_SIGNAL_INFO targetVideoSignalInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTL
{
private int x;
private int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_SOURCE_MODE
{
public uint width;
public uint height;
public DISPLAYCONFIG_PIXELFORMAT pixelFormat;
public POINTL position;
}
[StructLayout(LayoutKind.Explicit)]
public struct DISPLAYCONFIG_MODE_INFO_UNION
{
[FieldOffset(0)]
public DISPLAYCONFIG_TARGET_MODE targetMode;
[FieldOffset(0)]
public DISPLAYCONFIG_SOURCE_MODE sourceMode;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_MODE_INFO
{
public DISPLAYCONFIG_MODE_INFO_TYPE infoType;
public uint id;
public LUID adapterId;
public DISPLAYCONFIG_MODE_INFO_UNION modeInfo;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS
{
public uint value;
}
[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
public uint size;
public LUID adapterId;
public uint id;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct DISPLAYCONFIG_TARGET_DEVICE_NAME
{
public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
public DISPLAYCONFIG_TARGET_DEVICE_NAME_FLAGS flags;
public DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY outputTechnology;
public ushort edidManufactureId;
public ushort edidProductCodeId;
public uint connectorInstance;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
public string monitorFriendlyDeviceName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string monitorDevicePath;
}
#endregion
#region DLL-Imports
[DllImport("user32.dll")]
public static extern int GetDisplayConfigBufferSizes(
QUERY_DEVICE_CONFIG_FLAGS flags, out uint numPathArrayElements, out uint numModeInfoArrayElements);
[DllImport("user32.dll")]
public static extern int QueryDisplayConfig(
QUERY_DEVICE_CONFIG_FLAGS flags,
ref uint numPathArrayElements, [Out] DISPLAYCONFIG_PATH_INFO[] PathInfoArray,
ref uint numModeInfoArrayElements, [Out] DISPLAYCONFIG_MODE_INFO[] ModeInfoArray,
IntPtr currentTopologyId
);
[DllImport("user32.dll")]
public static extern int DisplayConfigGetDeviceInfo(ref DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName);
#endregion
private static DISPLAYCONFIG_TARGET_DEVICE_NAME DeviceName(LUID adapterId, uint targetId)
{
var deviceName = new DISPLAYCONFIG_TARGET_DEVICE_NAME
{
header =
{
size = (uint)Marshal.SizeOf(typeof (DISPLAYCONFIG_TARGET_DEVICE_NAME)),
adapterId = adapterId,
id = targetId,
type = DISPLAYCONFIG_DEVICE_INFO_TYPE.DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME
}
};
var error = DisplayConfigGetDeviceInfo(ref deviceName);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
return deviceName;
}
public static IEnumerable<DISPLAYCONFIG_TARGET_DEVICE_NAME> GetAllDevices()
{
uint pathCount, modeCount;
var error = GetDisplayConfigBufferSizes(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS, out pathCount, out modeCount);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
var displayPaths = new DISPLAYCONFIG_PATH_INFO[pathCount];
var displayModes = new DISPLAYCONFIG_MODE_INFO[modeCount];
error = QueryDisplayConfig(QUERY_DEVICE_CONFIG_FLAGS.QDC_ONLY_ACTIVE_PATHS,
ref pathCount, displayPaths, ref modeCount, displayModes, IntPtr.Zero);
if (error != ERROR_SUCCESS)
throw new Win32Exception(error);
for (var i = 0; i < modeCount; i++)
if (displayModes[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE.DISPLAYCONFIG_MODE_INFO_TYPE_TARGET)
yield return DeviceName(displayModes[i].adapterId, displayModes[i].id);
}
}
}
public class NativeMethods
{
// Monitor Power detection
internal const uint DEVICE_NOTIFY_WINDOW_HANDLE = 0x0;
internal const uint DEVICE_NOTIFY_SERVICE_HANDLE = 0x1;
internal const int WM_POWERBROADCAST = 0x0218;
internal const int PBT_POWERSETTINGCHANGE = 0x8013;
[DllImport("User32.dll", SetLastError = true)]
internal static extern IntPtr RegisterPowerSettingNotification(IntPtr hWnd, [In] Guid PowerSettingGuid, uint Flags);
[DllImport("User32.dll", SetLastError = true)]
internal static extern bool UnregisterPowerSettingNotification(IntPtr hWnd);
[StructLayout(LayoutKind.Sequential, Pack = 4)]
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
public class PowerSettingGuid
{
// 0=Powered by AC, 1=Powered by Battery, 2=Powered by short-term source (UPC)
public Guid AcdcPowerSource { get; } = new Guid("5d3e9a59-e9D5-4b00-a6bd-ff34ff516548");
// POWERBROADCAST_SETTING.Data = 1-100
public Guid BatteryPercentageRemaining { get; } = new Guid("a7ad8041-b45a-4cae-87a3-eecbb468a9e1");
// Windows 8+: 0=Monitor Off, 1=Monitor On, 2=Monitor Dimmed
public Guid ConsoleDisplayState { get; } = new Guid("6fe69556-704a-47a0-8f24-c28d936fda47");
// Windows 8+, Session 0 enabled: 0=User providing Input, 2=User Idle
public Guid GlobalUserPresence { get; } = new Guid("786E8A1D-B427-4344-9207-09E70BDCBEA9");
// 0=Monitor Off, 1=Monitor On.
public Guid MonitorPowerGuid { get; } = new Guid("02731015-4510-4526-99e6-e5a17ebd1aea");
// 0=Battery Saver Off, 1=Battery Saver On.
public Guid PowerSavingStatus { get; } = new Guid("E00958C0-C213-4ACE-AC77-FECCED2EEEA5");
// Windows 8+: 0=Off, 1=On, 2=Dimmed
public Guid SessionDisplayStatus { get; } = new Guid("2B84C20E-AD23-4ddf-93DB-05FFBD7EFCA5");
// Windows 8+, no Session 0: 0=User providing Input, 2=User Idle
public Guid SessionUserPresence { get; } = new Guid("3C0F4548-C03F-4c4d-B9F2-237EDE686376");
// 0=Exiting away mode 1=Entering away mode
public Guid SystemAwaymode { get; } = new Guid("98a7f580-01f7-48aa-9c0f-44352c29e5C0");
/* Windows 8+ */
// POWERBROADCAST_SETTING.Data not used
public Guid IdleBackgroundTask { get; } = new Guid(0x515C31D8, 0xF734, 0x163D, 0xA0, 0xFD, 0x11, 0xA0, 0x8C, 0x91, 0xE8, 0xF1);
public Guid PowerSchemePersonality { get; } = new Guid(0x245D8541, 0x3943, 0x4422, 0xB0, 0x25, 0x13, 0xA7, 0x84, 0xF6, 0x79, 0xB7);
// The Following 3 Guids are the POWERBROADCAST_SETTING.Data result of PowerSchemePersonality
public Guid MinPowerSavings { get; } = new Guid("8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c");
public Guid MaxPowerSavings { get; } = new Guid("a1841308-3541-4fab-bc81-f71556f20b4a");
public Guid TypicalPowerSavings { get; } = new Guid("381b4222-f694-41f0-9685-ff5bb260df2e");
}
public const int KEYEVENTF_EXTENDEDKEY = 1;
public const int KEYEVENTF_KEYUP = 2;
public const int VK_MEDIA_NEXT_TRACK = 0xB0;
public const int VK_MEDIA_PLAY_PAUSE = 0xB3;
public const int VK_MEDIA_PREV_TRACK = 0xB1;
public const int VK_VOLUME_MUTE = 0xAD;
public const int VK_SNAPSHOT = 0x2C;
[DllImport("user32.dll", SetLastError = true)]
public static extern void keybd_event(byte virtualKey, byte scanCode, uint flags, IntPtr extraInfo);
public static void KeyPress(int key = VK_MEDIA_PLAY_PAUSE)
{
keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY, IntPtr.Zero);
}
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
public const int SW_RESTORE = 9;
public static bool SwitchToCurrent()
{
IntPtr hWnd = IntPtr.Zero;
Process process = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(process.ProcessName);
foreach (Process _process in processes)
{
if (_process.Id != process.Id)
{
if (_process.MainWindowHandle != IntPtr.Zero)
{
Debug.WriteLine(_process.Id);
Debug.WriteLine(process.Id);
hWnd = _process.MainWindowHandle;
ShowWindowAsync(hWnd, SW_RESTORE);
}
return true;
break;
}
}
return false;
}
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerWriteDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerWriteACValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
int AcValueIndex);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerReadACValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
out IntPtr AcValueIndex
);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerReadDCValueIndex(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid SubGroupOfPowerSettingsGuid,
[MarshalAs(UnmanagedType.LPStruct)] Guid PowerSettingGuid,
out IntPtr AcValueIndex
);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerSetActiveScheme(IntPtr RootPowerKey,
[MarshalAs(UnmanagedType.LPStruct)] Guid SchemeGuid);
[DllImport("PowrProf.dll", CharSet = CharSet.Unicode)]
static extern UInt32 PowerGetActiveScheme(IntPtr UserPowerKey, out IntPtr ActivePolicyGuid);
static readonly Guid GUID_CPU = new Guid("54533251-82be-4824-96c1-47b60b740d00");
static readonly Guid GUID_BOOST = new Guid("be337238-0d82-4146-a960-4f3749d470c7");
[DllImportAttribute("powrprof.dll", EntryPoint = "PowerGetActualOverlayScheme")]
public static extern uint PowerGetActualOverlayScheme(out Guid ActualOverlayGuid);
[DllImportAttribute("powrprof.dll", EntryPoint = "PowerGetEffectiveOverlayScheme")]
public static extern uint PowerGetEffectiveOverlayScheme(out Guid EffectiveOverlayGuid);
[DllImportAttribute("powrprof.dll", EntryPoint = "PowerSetActiveOverlayScheme")]
public static extern uint PowerSetActiveOverlayScheme(Guid OverlaySchemeGuid);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
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 int dmDisplayOrientation;
public int dmDisplayFixedOutput;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public short 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;
};
[Flags()]
public enum DisplaySettingsFlags : int
{
CDS_UPDATEREGISTRY = 1,
CDS_TEST = 2,
CDS_FULLSCREEN = 4,
CDS_GLOBAL = 8,
CDS_SET_PRIMARY = 0x10,
CDS_RESET = 0x40000000,
CDS_NORESET = 0x10000000
}
// PInvoke declaration for EnumDisplaySettings Win32 API
[DllImport("user32.dll")]
public static extern int EnumDisplaySettingsEx(
string lpszDeviceName,
int iModeNum,
ref DEVMODE lpDevMode);
// PInvoke declaration for ChangeDisplaySettings Win32 API
[DllImport("user32.dll")]
public static extern int ChangeDisplaySettingsEx(
string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd,
DisplaySettingsFlags dwflags, IntPtr lParam);
public static DEVMODE CreateDevmode()
{
DEVMODE dm = new DEVMODE();
dm.dmDeviceName = new String(new char[32]);
dm.dmFormName = new String(new char[32]);
dm.dmSize = (short)Marshal.SizeOf(dm);
return dm;
}
public const int ENUM_CURRENT_SETTINGS = -1;
public const string defaultDevice = "\\\\.\\DISPLAY1";
public static string FindLaptopScreen()
{
string laptopScreen = null;
try
{
var devices = GetAllDevices().ToArray();
int count = 0, displayNum = -1;
foreach (var device in devices)
{
if (device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL ||
device.outputTechnology == DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY.DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED)
{
displayNum = count;
}
count++;
//Logger.WriteLine(device.outputTechnology.ToString());
//Logger.WriteLine(device.monitorFriendlyDeviceName);
}
var screens = Screen.AllScreens;
if (screens.Length != count) return null;
count = 0;
foreach (var screen in screens)
{
if (count == displayNum)
{
laptopScreen = screen.DeviceName;
}
//Logger.WriteLine(screen.DeviceName);
count++;
}
}
catch (Exception ex)
{
Logger.WriteLine(ex.ToString());
Logger.WriteLine("Can't detect internal screen");
//laptopScreen = Screen.PrimaryScreen.DeviceName;
}
return laptopScreen;
}
public static int GetRefreshRate()
{
DEVMODE dm = CreateDevmode();
string laptopScreen = FindLaptopScreen();
int frequency = -1;
if (laptopScreen is null)
return -1;
if (0 != NativeMethods.EnumDisplaySettingsEx(laptopScreen, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
frequency = dm.dmDisplayFrequency;
}
return frequency;
}
public static int SetRefreshRate(int frequency = 120)
{
DEVMODE dm = CreateDevmode();
string laptopScreen = FindLaptopScreen();
if (laptopScreen is null)
return -1;
if (0 != NativeMethods.EnumDisplaySettingsEx(laptopScreen, NativeMethods.ENUM_CURRENT_SETTINGS, ref dm))
{
dm.dmDisplayFrequency = frequency;
int iRet = NativeMethods.ChangeDisplaySettingsEx(laptopScreen, ref dm, IntPtr.Zero, DisplaySettingsFlags.CDS_UPDATEREGISTRY, IntPtr.Zero);
return iRet;
}
return 0;
}
static Guid GetActiveScheme()
{
IntPtr pActiveSchemeGuid;
var hr = PowerGetActiveScheme(IntPtr.Zero, out pActiveSchemeGuid);
Guid activeSchemeGuid = (Guid)Marshal.PtrToStructure(pActiveSchemeGuid, typeof(Guid));
return activeSchemeGuid;
}
public static int GetCPUBoost()
{
IntPtr AcValueIndex;
Guid activeSchemeGuid = GetActiveScheme();
UInt32 value = PowerReadACValueIndex(IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST, out AcValueIndex);
return AcValueIndex.ToInt32();
}
public static void SetCPUBoost(int boost = 0)
{
Guid activeSchemeGuid = GetActiveScheme();
var hrAC = PowerWriteACValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST,
boost);
PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
/*
var hrDC = PowerWriteDCValueIndex(
IntPtr.Zero,
activeSchemeGuid,
GUID_CPU,
GUID_BOOST,
boost);
PowerSetActiveScheme(IntPtr.Zero, activeSchemeGuid);
*/
}
public static void SetPowerScheme(int mode)
{
switch (mode)
{
case 0: // balanced
PowerSetActiveOverlayScheme(new Guid("00000000-0000-0000-0000-000000000000"));
break;
case 1: // turbo
PowerSetActiveOverlayScheme(new Guid("ded574b5-45a0-4f42-8737-46345c09c238"));
break;
case 2: //silent
PowerSetActiveOverlayScheme(new Guid("961cc777-2547-4f9d-8174-7d86181b8a7a"));
break;
}
}
}

View File

@@ -1,41 +1,15 @@
using Microsoft.Win32;
using System.Diagnostics;
using System.Management;
public class HardwareMonitor
{
public static float? cpuTemp = -1;
public static float? batteryDischarge = -1;
public static void ReadSensors()
{
cpuTemp = -1;
batteryDischarge = -1;
try
{
var ct = new PerformanceCounter("Thermal Zone Information", "Temperature", @"\_TZ.THRM", true);
cpuTemp = ct.NextValue() - 273;
ct.Dispose();
var cb = new PerformanceCounter("Power Meter", "Power", "Power Meter (0)", true);
batteryDischarge = cb.NextValue() / 1000;
cb.Dispose();
}
catch
{
Debug.WriteLine("Failed reading sensors");
}
}
}
using System.Reflection;
using System.Text.Json;
namespace GHelper
{
static class Program
{
public static NotifyIcon trayIcon = new NotifyIcon
{
Text = "G-Helper",
@@ -49,6 +23,11 @@ namespace GHelper
public static SettingsForm settingsForm = new SettingsForm();
public static ToastForm toast = new ToastForm();
private static IntPtr unRegPowerNotify;
private static IntPtr ds;
private static long lastAuto;
// The main entry point for the application
public static void Main()
{
@@ -69,44 +48,93 @@ namespace GHelper
}
Application.EnableVisualStyles();
ds = settingsForm.Handle;
trayIcon.MouseClick += TrayIcon_MouseClick; ;
wmi.SubscribeToEvents(WatcherEventArrived);
settingsForm.InitGPUMode();
settingsForm.InitBoost();
settingsForm.InitAura();
settingsForm.InitMatrix();
settingsForm.VisualiseGPUAuto(config.getConfig("gpu_auto"));
settingsForm.VisualiseScreenAuto(config.getConfig("screen_auto"));
settingsForm.SetStartupCheck(Startup.IsScheduled());
SetAutoModes();
HardwareMonitor.RecreateGpuTemperatureProvider();
// Subscribing for monitor power on events
var settingGuid = new NativeMethods.PowerSettingGuid();
unRegPowerNotify = NativeMethods.RegisterPowerSettingNotification(ds, settingGuid.ConsoleDisplayState, NativeMethods.DEVICE_NOTIFY_WINDOW_HANDLE);
// Subscribing for system power change events
SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
IntPtr ds = settingsForm.Handle;
CheckForUpdates();
Application.Run();
}
private static void SetAutoModes()
static async void CheckForUpdates()
{
PowerLineStatus isPlugged = SystemInformation.PowerStatus.PowerLineStatus;
settingsForm.AutoGPUMode(isPlugged);
settingsForm.AutoScreen(isPlugged);
settingsForm.AutoPerformance(isPlugged);
settingsForm.SetMatrix(isPlugged);
var assembly = Assembly.GetExecutingAssembly().GetName().Version.ToString();
settingsForm.SetVersionLabel("Version: " + assembly);
try
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("User-Agent", "C# App");
var json = await httpClient.GetStringAsync("https://api.github.com/repos/seerge/g-helper/releases/latest");
var config = JsonSerializer.Deserialize<JsonElement>(json);
var tag = config.GetProperty("tag_name").ToString().Replace("v", "");
var url = config.GetProperty("assets")[0].GetProperty("browser_download_url").ToString();
var gitVersion = new Version(tag);
var appVersion = new Version(assembly);
var result = gitVersion.CompareTo(appVersion);
if (result > 0)
{
settingsForm.SetVersionLabel("Download Update: " + tag, url);
}
}
}
catch
{
Logger.WriteLine("Failed to get update");
}
}
public static void SetAutoModes()
{
if (Math.Abs(DateTimeOffset.Now.ToUnixTimeMilliseconds() - lastAuto) < 1000) return;
lastAuto = DateTimeOffset.Now.ToUnixTimeMilliseconds();
PowerLineStatus isPlugged = SystemInformation.PowerStatus.PowerLineStatus;
Logger.WriteLine("AutoSetting for " + isPlugged.ToString());
settingsForm.SetBatteryChargeLimit(config.getConfig("charge_limit"));
settingsForm.AutoPerformance(isPlugged);
bool switched = settingsForm.AutoGPUMode(isPlugged);
if (!switched) settingsForm.AutoScreen(isPlugged);
settingsForm.SetMatrix(isPlugged);
}
private static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
Logger.WriteLine("Windows - Power Mode Changed");
SetAutoModes();
}
@@ -123,7 +151,7 @@ namespace GHelper
}
catch
{
Debug.WriteLine("Failed to run " + fileName);
Logger.WriteLine("Failed to run " + fileName);
}
@@ -200,7 +228,7 @@ namespace GHelper
int EventID = int.Parse(e.NewEvent["EventID"].ToString());
Debug.WriteLine(EventID);
Logger.WriteLine("WMI event " + EventID);
switch (EventID)
{
@@ -248,6 +276,7 @@ namespace GHelper
static void OnExit(object sender, EventArgs e)
{
trayIcon.Visible = false;
NativeMethods.UnregisterPowerSettingNotification(unRegPowerNotify);
Application.Exit();
}
}

View File

@@ -80,6 +80,26 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_balance_symbol_96 {
get {
object obj = ResourceManager.GetObject("icons8-balance-symbol-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_bicycle_48__1_ {
get {
object obj = ResourceManager.GetObject("icons8-bicycle-48 (1)", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -90,6 +110,16 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_fan_48 {
get {
object obj = ResourceManager.GetObject("icons8-fan-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -100,6 +130,36 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_fan_speed_48 {
get {
object obj = ResourceManager.GetObject("icons8-fan-speed-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_fiat_500_48 {
get {
object obj = ResourceManager.GetObject("icons8-fiat-500-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_game_controller_48 {
get {
object obj = ResourceManager.GetObject("icons8-game-controller-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -120,6 +180,36 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_launch_96 {
get {
object obj = ResourceManager.GetObject("icons8-launch-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_leaf_48 {
get {
object obj = ResourceManager.GetObject("icons8-leaf-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_leaf_96 {
get {
object obj = ResourceManager.GetObject("icons8-leaf-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -130,6 +220,86 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_organic_food_96 {
get {
object obj = ResourceManager.GetObject("icons8-organic-food-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_organic_food_961 {
get {
object obj = ResourceManager.GetObject("icons8-organic-food-961", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_processor_96 {
get {
object obj = ResourceManager.GetObject("icons8-processor-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_project_management_48 {
get {
object obj = ResourceManager.GetObject("icons8-project-management-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_project_management_48__1_ {
get {
object obj = ResourceManager.GetObject("icons8-project-management-48 (1)", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_rocket_48 {
get {
object obj = ResourceManager.GetObject("icons8-rocket-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_spa_flower_48 {
get {
object obj = ResourceManager.GetObject("icons8-spa-flower-48", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_spa_flower_96 {
get {
object obj = ResourceManager.GetObject("icons8-spa-flower-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
@@ -160,6 +330,16 @@ namespace GHelper.Properties {
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap icons8_xbox_controller_96 {
get {
object obj = ResourceManager.GetObject("icons8-xbox-controller-96", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
/// </summary>

View File

@@ -118,40 +118,94 @@
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="eco" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\eco.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="icons8-leaf-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-leaf-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-launch-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-launch-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-charging-battery-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-charging-battery-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-organic-food-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-organic-food-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-fiat-500-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-fiat-500-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-video-card-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-video-card-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-project-management-48 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-project-management-48 (1).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-bicycle-48 (1)" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-bicycle-48 (1).png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-fan-head-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-fan-head-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-processor-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-processor-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-spa-flower-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-spa-flower-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-spa-flower-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-spa-flower-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="standard" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\standard.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-keyboard-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-keyboard-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-fan-speed-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-fan-speed-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-speed-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-speed-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="eco" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\eco.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-laptop-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-laptop-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-rocket-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-rocket-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-organic-food-961" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-organic-food-961.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-balance-symbol-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-balance-symbol-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-fan-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-fan-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-matrix-desktop-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-matrix-desktop-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-xbox-controller-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-xbox-controller-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-project-management-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-project-management-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-leaf-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-leaf-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="ultimate" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\ultimate.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="standard" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\standard.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-speed-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-speed-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="everything-is-fine-itsfine" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\everything-is-fine-itsfine.gif;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-speed-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-speed-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-video-card-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-video-card-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-fan-head-96" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-fan-head-96.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-charging-battery-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-charging-battery-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-laptop-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-laptop-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="icons8-matrix-desktop-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-matrix-desktop-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
<data name="icons8-game-controller-48" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\icons8-game-controller-48.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View File

@@ -0,0 +1,7 @@
{
"profiles": {
"GHelper": {
"commandName": "Project"
}
}
}

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

View File

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 B

View File

Before

Width:  |  Height:  |  Size: 515 B

After

Width:  |  Height:  |  Size: 515 B

View File

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

View File

Before

Width:  |  Height:  |  Size: 428 B

After

Width:  |  Height:  |  Size: 428 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 837 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 B

View File

Before

Width:  |  Height:  |  Size: 885 B

After

Width:  |  Height:  |  Size: 885 B

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 400 B

After

Width:  |  Height:  |  Size: 400 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 B

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

85
app/RoundedButton.cs Normal file
View File

@@ -0,0 +1,85 @@
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace CustomControls
{
public class RoundedButton : Button
{
//Fields
private int borderSize = 5;
private int borderRadius = 5;
private bool activated = false;
private Color borderColor = Color.Transparent;
public Color BorderColor
{
get { return borderColor; }
set
{
borderColor = value;
}
}
public bool Activated
{
get { return activated; }
set
{
if (activated != value)
this.Invalidate();
activated = value;
}
}
public RoundedButton()
{
this.FlatStyle = FlatStyle.Flat;
this.FlatAppearance.BorderSize = 0;
}
private GraphicsPath GetFigurePath(Rectangle rect, int radius)
{
GraphicsPath path = new GraphicsPath();
float curveSize = radius * 2F;
path.StartFigure();
path.AddArc(rect.X, rect.Y, curveSize, curveSize, 180, 90);
path.AddArc(rect.Right - curveSize, rect.Y, curveSize, curveSize, 270, 90);
path.AddArc(rect.Right - curveSize, rect.Bottom - curveSize, curveSize, curveSize, 0, 90);
path.AddArc(rect.X, rect.Bottom - curveSize, curveSize, curveSize, 90, 90);
path.CloseFigure();
return path;
}
protected override void OnPaint(PaintEventArgs pevent)
{
base.OnPaint(pevent);
float ratio = pevent.Graphics.DpiX / 192.0f;
int border = (int)(ratio * borderSize);
Rectangle rectSurface = this.ClientRectangle;
Rectangle rectBorder = Rectangle.Inflate(rectSurface, -border, -border);
Color borderDrawColor = activated ? borderColor : Color.Transparent;
using (GraphicsPath pathSurface = GetFigurePath(rectSurface, borderRadius+ border))
using (GraphicsPath pathBorder = GetFigurePath(rectBorder, borderRadius))
using (Pen penSurface = new Pen(this.Parent.BackColor, border))
using (Pen penBorder = new Pen(borderDrawColor, border))
{
penBorder.Alignment = PenAlignment.Outset;
pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
this.Region = new Region(pathSurface);
pevent.Graphics.DrawPath(penSurface, pathSurface);
pevent.Graphics.DrawPath(penBorder, pathBorder);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,6 @@
using Starlight.AnimeMatrix;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Reflection;
using System.Timers;
namespace GHelper
@@ -14,36 +13,40 @@ namespace GHelper
static Color colorStandard = Color.FromArgb(255, 58, 174, 239);
static Color colorTurbo = Color.FromArgb(255, 255, 32, 32);
static int buttonInactive = 0;
static int buttonActive = 5;
static System.Timers.Timer aTimer = default!;
static System.Timers.Timer matrixTimer = default!;
public string versionUrl = "http://github.com/seerge/g-helper/releases";
public string perfName = "Balanced";
Fans fans;
Keyboard keyb;
static AnimeMatrixDevice mat;
static bool matEnabled = false;
public SettingsForm()
{
InitializeComponent();
HighDpiHelper.AdjustControlImagesDpiScale(this, 2);
FormClosing += SettingsForm_FormClosing;
buttonSilent.FlatAppearance.BorderColor = colorEco;
buttonBalanced.FlatAppearance.BorderColor = colorStandard;
buttonTurbo.FlatAppearance.BorderColor = colorTurbo;
buttonSilent.BorderColor = colorEco;
buttonBalanced.BorderColor = colorStandard;
buttonTurbo.BorderColor = colorTurbo;
buttonEco.FlatAppearance.BorderColor = colorEco;
buttonStandard.FlatAppearance.BorderColor = colorStandard;
buttonUltimate.FlatAppearance.BorderColor = colorTurbo;
buttonEco.BorderColor = colorEco;
buttonStandard.BorderColor = colorStandard;
buttonUltimate.BorderColor = colorTurbo;
buttonOptimized.BorderColor = colorEco;
button60Hz.BorderColor = SystemColors.ActiveBorder;
button120Hz.BorderColor = SystemColors.ActiveBorder;
buttonScreenAuto.BorderColor = SystemColors.ActiveBorder;
buttonOptimized.Click += ButtonOptimized_Click;
buttonSilent.Click += ButtonSilent_Click;
buttonBalanced.Click += ButtonBalanced_Click;
buttonTurbo.Click += ButtonTurbo_Click;
@@ -58,13 +61,10 @@ namespace GHelper
button60Hz.Click += Button60Hz_Click;
button120Hz.Click += Button120Hz_Click;
buttonScreenAuto.Click += ButtonScreenAuto_Click;
buttonQuit.Click += ButtonQuit_Click;
checkBoost.Click += CheckBoost_Click;
checkScreen.CheckedChanged += checkScreen_CheckedChanged;
comboKeyboard.DropDownStyle = ComboBoxStyle.DropDownList;
comboKeyboard.SelectedIndex = 0;
comboKeyboard.SelectedValueChanged += ComboKeyboard_SelectedValueChanged;
@@ -77,9 +77,6 @@ namespace GHelper
pictureColor.Click += PictureColor_Click;
pictureColor2.Click += PictureColor2_Click;
labelVersion.Text = "Version " + Assembly.GetExecutingAssembly().GetName().Version.ToString();
labelVersion.Click += LabelVersion_Click;
labelCPUFan.Click += LabelCPUFan_Click;
labelGPUFan.Click += LabelCPUFan_Click;
@@ -93,10 +90,161 @@ namespace GHelper
buttonMatrix.Click += ButtonMatrix_Click;
checkStartup.CheckedChanged += CheckStartup_CheckedChanged;
labelVersion.Click += LabelVersion_Click;
buttonOptimized.MouseMove += ButtonOptimized_MouseHover;
buttonOptimized.MouseLeave += ButtonGPU_MouseLeave;
buttonEco.MouseMove += ButtonEco_MouseHover;
buttonEco.MouseLeave += ButtonGPU_MouseLeave;
buttonStandard.MouseMove += ButtonStandard_MouseHover;
buttonStandard.MouseLeave += ButtonGPU_MouseLeave;
buttonUltimate.MouseMove += ButtonUltimate_MouseHover;
buttonUltimate.MouseLeave += ButtonGPU_MouseLeave;
buttonScreenAuto.MouseMove += ButtonScreenAuto_MouseHover;
buttonScreenAuto.MouseLeave += ButtonScreen_MouseLeave;
button60Hz.MouseMove += Button60Hz_MouseHover;
button60Hz.MouseLeave += ButtonScreen_MouseLeave;
button120Hz.MouseMove += Button120Hz_MouseHover;
button120Hz.MouseLeave += ButtonScreen_MouseLeave;
//buttonStandard.Image = (Image)(new Bitmap(buttonStandard.Image, new Size(16, 16)));
SetTimer();
}
private void Button120Hz_MouseHover(object? sender, EventArgs e)
{
labelTipScreen.Text = "Max refresh rate + screen overdrive for lower latency";
}
private void Button60Hz_MouseHover(object? sender, EventArgs e)
{
labelTipScreen.Text = "60Hz refresh rate to save battery";
}
private void ButtonScreen_MouseLeave(object? sender, EventArgs e)
{
labelTipScreen.Text = "";
}
private void ButtonScreenAuto_MouseHover(object? sender, EventArgs e)
{
labelTipScreen.Text = "Sets 60Hz to save battery, and back when plugged";
}
private void ButtonUltimate_MouseHover(object? sender, EventArgs e)
{
labelTipGPU.Text = "Routes laptop screen to dGPU, maximizing FPS";
}
private void ButtonStandard_MouseHover(object? sender, EventArgs e)
{
labelTipGPU.Text = "Enables dGPU for standard use";
}
private void ButtonEco_MouseHover(object? sender, EventArgs e)
{
labelTipGPU.Text = "Disables dGPU for battery savings";
}
private void ButtonOptimized_MouseHover(object? sender, EventArgs e)
{
labelTipGPU.Text = "Switch to Eco on battery and to Standard when plugged";
}
private void ButtonGPU_MouseLeave(object? sender, EventArgs e)
{
labelTipGPU.Text = "";
}
private void ButtonOptimized_Click(object? sender, EventArgs e)
{
Program.config.setConfig("gpu_auto", (Program.config.getConfig("gpu_auto") == 1) ? 0 : 1);
VisualiseGPUMode();
AutoGPUMode(SystemInformation.PowerStatus.PowerLineStatus);
}
private void ButtonScreenAuto_Click(object? sender, EventArgs e)
{
Program.config.setConfig("screen_auto", 1);
InitScreen();
AutoScreen(SystemInformation.PowerStatus.PowerLineStatus);
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case NativeMethods.WM_POWERBROADCAST:
if (m.WParam == (IntPtr)NativeMethods.PBT_POWERSETTINGCHANGE)
{
var settings = (NativeMethods.POWERBROADCAST_SETTING)m.GetLParam(typeof(NativeMethods.POWERBROADCAST_SETTING));
switch (settings.Data)
{
case 0:
Logger.WriteLine("Monitor Power Off");
break;
case 1:
Logger.WriteLine("Monitor Power On");
Program.settingsForm.BeginInvoke(delegate
{
Program.SetAutoModes();
});
break;
case 2:
Logger.WriteLine("Monitor Dimmed");
break;
}
}
m.Result = (IntPtr)1;
break;
}
base.WndProc(ref m);
}
public void SetVersionLabel(string label, string url = null)
{
labelVersion.Text = label;
if (url is not null)
{
versionUrl = url;
labelVersion.ForeColor = Color.Red;
}
}
private void LabelVersion_Click(object? sender, EventArgs e)
{
Process.Start(new ProcessStartInfo(versionUrl) { UseShellExecute = true });
}
private void CheckStartup_CheckedChanged(object? sender, EventArgs e)
{
if (sender is null) return;
CheckBox chk = (CheckBox)sender;
if (chk.Checked)
{
Startup.Schedule();
}
else
{
Startup.UnSchedule();
}
}
private void CheckMatrix_CheckedChanged(object? sender, EventArgs e)
{
if (sender is null) return;
@@ -174,9 +322,9 @@ namespace GHelper
private void ButtonMatrix_Click(object? sender, EventArgs e)
{
string fileName = "";
string fileName = null;
Thread t = new Thread((ThreadStart)(() =>
Thread t = new Thread(() =>
{
OpenFileDialog of = new OpenFileDialog();
of.Filter = "Image Files (*.bmp;*.jpg;*.jpeg,*.png,*.gif)|*.BMP;*.JPG;*.JPEG;*.PNG;*.GIF";
@@ -185,18 +333,22 @@ namespace GHelper
fileName = of.FileName;
}
return;
}));
});
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
Program.config.setConfig("matrix_picture", fileName);
SetMatrixPicture(fileName);
BeginInvoke(delegate
if (fileName is not null)
{
comboMatrixRunning.SelectedIndex = 2;
});
Program.config.setConfig("matrix_picture", fileName);
SetMatrixPicture(fileName);
BeginInvoke(delegate
{
comboMatrixRunning.SelectedIndex = 2;
});
}
}
@@ -234,6 +386,8 @@ namespace GHelper
StopMatrixTimer();
mat.SetProvider();
if (brightness == 0 || (auto && Plugged != PowerLineStatus.Online))
{
mat.SetDisplayState(false);
@@ -252,6 +406,7 @@ namespace GHelper
{
mat.SetBuiltInAnimation(true, animation);
}
}
}
@@ -264,11 +419,6 @@ namespace GHelper
RefreshSensors();
}
private void LabelVersion_Click(object? sender, EventArgs e)
{
Process.Start(new ProcessStartInfo("http://github.com/seerge/g-helper/releases") { UseShellExecute = true });
}
private void PictureColor2_Click(object? sender, EventArgs e)
{
@@ -305,7 +455,7 @@ namespace GHelper
if (fans == null || fans.Text == "")
{
fans = new Fans();
Debug.WriteLine("Starting fans");
//Debug.WriteLine("Starting fans");
}
if (fans.Visible)
@@ -367,36 +517,26 @@ namespace GHelper
public void InitMatrix()
{
matrixTimer = new System.Timers.Timer();
matrixTimer.Enabled = false;
matrixTimer.Interval = 100;
try
{
matEnabled = true;
mat = new AnimeMatrixDevice();
matrixTimer = new System.Timers.Timer(100);
matrixTimer.Elapsed += MatrixTimer_Elapsed;
}
catch
{
matEnabled = false;
Debug.WriteLine("Anime Matrix not detected");
}
if (!matEnabled)
{
panelMatrix.Visible = false;
return;
}
else
{
int brightness = Program.config.getConfig("matrix_brightness");
int running = Program.config.getConfig("matrix_running");
comboMatrix.SelectedIndex = (brightness != -1) ? brightness : 0;
comboMatrixRunning.SelectedIndex = (running != -1) ? running : 0;
int brightness = Program.config.getConfig("matrix_brightness");
int running = Program.config.getConfig("matrix_running");
comboMatrix.SelectedIndex = (brightness != -1) ? brightness : 0;
comboMatrixRunning.SelectedIndex = (running != -1) ? running : 0;
checkMatrix.Checked = (Program.config.getConfig("matrix_auto") == 1);
checkMatrix.Checked = (Program.config.getConfig("matrix_auto") == 1);
}
}
@@ -462,26 +602,15 @@ namespace GHelper
SetAuraMode(cmb.SelectedIndex);
}
private void CheckBoost_Click(object? sender, EventArgs e)
{
if (sender is null)
return;
CheckBox chk = (CheckBox)sender;
if (chk.Checked)
NativeMethods.SetCPUBoost(2);
else
NativeMethods.SetCPUBoost(0);
}
private void Button120Hz_Click(object? sender, EventArgs e)
{
Program.config.setConfig("screen_auto", 0);
SetScreen(1000, 1);
}
private void Button60Hz_Click(object? sender, EventArgs e)
{
Program.config.setConfig("screen_auto", 0);
SetScreen(60, 0);
}
@@ -490,8 +619,12 @@ namespace GHelper
{
int currentFrequency = NativeMethods.GetRefreshRate();
if (currentFrequency < 0) // Laptop screen not detected or has unknown refresh rate
if (currentFrequency < 0) // Laptop screen not detected or has unknown refresh rate
{
InitScreen();
return;
}
if (frequency >= 1000)
{
@@ -500,28 +633,16 @@ namespace GHelper
frequency = 120;
}
if (frequency > 0)
NativeMethods.SetRefreshRate(frequency);
try
{
if (overdrive > 0)
Program.wmi.DeviceSet(ASUSWmi.ScreenOverdrive, overdrive);
}
catch
{
Debug.WriteLine("Screen Overdrive not supported");
}
if (frequency <= 0) return;
NativeMethods.SetRefreshRate(frequency);
if (overdrive >= 0)
Program.wmi.DeviceSet(ASUSWmi.ScreenOverdrive, overdrive);
InitScreen();
}
Logger.WriteLine("Screen " + frequency.ToString() + "Hz");
public void InitBoost()
{
int boost = NativeMethods.GetCPUBoost();
checkBoost.Checked = (boost > 0);
}
public void InitScreen()
@@ -530,22 +651,7 @@ namespace GHelper
int frequency = NativeMethods.GetRefreshRate();
int maxFrequency = Program.config.getConfig("max_frequency");
if (frequency < 0)
{
button60Hz.Enabled = false;
button120Hz.Enabled = false;
labelSreen.Text = "Laptop Screen: Turned off";
button60Hz.BackColor = SystemColors.ControlLight;
button120Hz.BackColor = SystemColors.ControlLight;
}
else
{
button60Hz.Enabled = true;
button120Hz.Enabled = true;
button60Hz.BackColor = SystemColors.ControlLightLight;
button120Hz.BackColor = SystemColors.ControlLightLight;
labelSreen.Text = "Laptop Screen";
}
bool screenAuto = (Program.config.getConfig("screen_auto") == 1);
int overdrive = 0;
try
@@ -554,15 +660,42 @@ namespace GHelper
}
catch
{
Debug.WriteLine("Screen Overdrive not supported");
Logger.WriteLine("Screen Overdrive not supported");
}
button60Hz.FlatAppearance.BorderSize = buttonInactive;
button120Hz.FlatAppearance.BorderSize = buttonInactive;
if (frequency == 60)
if (frequency < 0)
{
button60Hz.FlatAppearance.BorderSize = buttonActive;
button60Hz.Enabled = false;
button120Hz.Enabled = false;
buttonScreenAuto.Enabled = false;
labelSreen.Text = "Laptop Screen: Turned off";
button60Hz.BackColor = SystemColors.ControlLight;
button120Hz.BackColor = SystemColors.ControlLight;
buttonScreenAuto.BackColor = SystemColors.ControlLight;
}
else
{
button60Hz.Enabled = true;
button120Hz.Enabled = true;
buttonScreenAuto.Enabled = true;
button60Hz.BackColor = SystemColors.ControlLightLight;
button120Hz.BackColor = SystemColors.ControlLightLight;
buttonScreenAuto.BackColor = SystemColors.ControlLightLight;
labelSreen.Text = "Laptop Screen: " + frequency + "Hz" + ((overdrive == 1) ? " + Overdrive" : "");
}
button60Hz.Activated = false;
button120Hz.Activated = false;
buttonScreenAuto.Activated = false;
if (screenAuto)
{
buttonScreenAuto.Activated = true;
}
else if (frequency == 60)
{
button60Hz.Activated = true;
}
else
{
@@ -570,7 +703,7 @@ namespace GHelper
maxFrequency = frequency;
Program.config.setConfig("max_frequency", maxFrequency);
button120Hz.FlatAppearance.BorderSize = buttonActive;
button120Hz.Activated = true;
}
if (maxFrequency > 60)
@@ -648,6 +781,11 @@ namespace GHelper
if (HardwareMonitor.batteryDischarge > 0)
battery = "Discharging: " + Math.Round((decimal)HardwareMonitor.batteryDischarge, 1).ToString() + "W";
if (HardwareMonitor.gpuTemp != null)
{
gpuTemp = $": {HardwareMonitor.gpuTemp}°C - ";
}
Program.settingsForm.BeginInvoke(delegate
{
Program.settingsForm.labelCPUFan.Text = "CPU" + cpuTemp + cpuFan;
@@ -675,6 +813,7 @@ namespace GHelper
aTimer.Interval = 300;
aTimer.Enabled = true;
//RefreshSensors();
}
else
{
@@ -682,25 +821,72 @@ namespace GHelper
}
}
public void SetPower()
{
int limit_total = Program.config.getConfigPerf("limit_total");
int limit_cpu = Program.config.getConfigPerf("limit_cpu");
if (limit_total > ASUSWmi.MaxTotal) return;
if (limit_total < ASUSWmi.MinTotal) return;
if (limit_cpu > ASUSWmi.MaxCPU) return;
if (limit_cpu < ASUSWmi.MinCPU) return;
if (Program.wmi.DeviceGet(ASUSWmi.PPT_TotalA0) >= 0)
Program.wmi.DeviceSet(ASUSWmi.PPT_TotalA0, limit_total);
if (Program.wmi.DeviceGet(ASUSWmi.PPT_CPUB0) >= 0)
Program.wmi.DeviceSet(ASUSWmi.PPT_CPUB0, limit_cpu);
Logger.WriteLine("PowerLimits " + limit_total.ToString() + ", " + limit_cpu.ToString());
}
public void AutoFansAndPower()
{
if (Program.config.getConfigPerf("auto_apply") == 1)
{
Program.wmi.SetFanCurve(0, Program.config.getFanConfig(0));
Program.wmi.SetFanCurve(1, Program.config.getFanConfig(1));
}
if (Program.config.getConfigPerf("auto_apply_power") == 1)
{
var timer = new System.Timers.Timer(1000);
timer.Elapsed += delegate
{
timer.Stop();
timer.Dispose();
SetPower();
};
timer.Start();
}
}
public void SetPerformanceMode(int PerformanceMode = ASUSWmi.PerformanceBalanced, bool notify = false)
{
buttonSilent.FlatAppearance.BorderSize = buttonInactive;
buttonBalanced.FlatAppearance.BorderSize = buttonInactive;
buttonTurbo.FlatAppearance.BorderSize = buttonInactive;
buttonSilent.Activated = false;
buttonBalanced.Activated = false;
buttonTurbo.Activated = false;
switch (PerformanceMode)
{
case ASUSWmi.PerformanceSilent:
buttonSilent.FlatAppearance.BorderSize = buttonActive;
buttonSilent.Activated = true;
perfName = "Silent";
break;
case ASUSWmi.PerformanceTurbo:
buttonTurbo.FlatAppearance.BorderSize = buttonActive;
buttonTurbo.Activated = true;
perfName = "Turbo";
break;
default:
buttonBalanced.FlatAppearance.BorderSize = buttonActive;
buttonBalanced.Activated = true;
PerformanceMode = ASUSWmi.PerformanceBalanced;
perfName = "Balanced";
break;
@@ -711,18 +897,7 @@ namespace GHelper
Program.config.setConfig("performance_mode", PerformanceMode);
Program.wmi.DeviceSet(ASUSWmi.PerformanceMode, PerformanceMode);
if (Program.config.getConfig("auto_apply_" + PerformanceMode) == 1)
{
Program.wmi.SetFanCurve(0, Program.config.getFanConfig(0));
Program.wmi.SetFanCurve(1, Program.config.getFanConfig(1));
}
if (fans != null && fans.Text != "")
{
fans.LoadFans();
fans.ResetApplyLabel();
}
Logger.WriteLine("PerfMode " + perfName + " " + PerformanceMode);
if (notify && (oldMode != PerformanceMode))
{
@@ -736,6 +911,23 @@ namespace GHelper
}
}
AutoFansAndPower();
NativeMethods.SetPowerScheme(PerformanceMode);
if (NativeMethods.PowerGetEffectiveOverlayScheme(out Guid activeScheme) == 0)
{
Debug.WriteLine("Effective :" + activeScheme);
}
if (fans != null && fans.Text != "")
{
fans.InitFans();
fans.InitPower();
}
}
@@ -756,44 +948,66 @@ namespace GHelper
public void AutoScreen(PowerLineStatus Plugged = PowerLineStatus.Online)
{
int ScreenAuto = Program.config.getConfig("screen_auto");
if (ScreenAuto != 1) return;
if (Program.config.getConfig("screen_auto") != 1) return;
if (Plugged == PowerLineStatus.Online)
SetScreen(1000, 1);
else
SetScreen(60, 0);
InitScreen();
}
public void AutoGPUMode(PowerLineStatus Plugged = PowerLineStatus.Online)
public bool AutoGPUMode(PowerLineStatus Plugged = PowerLineStatus.Online)
{
int GpuAuto = Program.config.getConfig("gpu_auto");
if (GpuAuto != 1) return;
bool GpuAuto = Program.config.getConfig("gpu_auto") == 1;
if (!GpuAuto) return false;
int eco = Program.wmi.DeviceGet(ASUSWmi.GPUEco);
int mux = Program.wmi.DeviceGet(ASUSWmi.GPUMux);
if (mux == 0) // GPU in Ultimate, ignore
return;
return false;
else
{
if (eco == 1 && Plugged == PowerLineStatus.Online) // Eco going Standard on plugged
{
Program.wmi.DeviceSet(ASUSWmi.GPUEco, 0);
InitGPUMode();
SetEcoGPU(0);
return true;
}
else if (eco == 0 && Plugged != PowerLineStatus.Online) // Standard going Eco on plugged
{
Program.wmi.DeviceSet(ASUSWmi.GPUEco, 1);
InitGPUMode();
SetEcoGPU(1);
return true;
}
}
return false;
}
private void UltimateUI(bool ultimate)
{
if (!ultimate)
{
tableGPU.Controls.Remove(buttonUltimate);
/*
* buttonFans.Image = null;
buttonFans.Height = 44;
*/
tablePerf.ColumnCount = 0;
tableGPU.ColumnCount = 0;
tableScreen.ColumnCount = 0;
}
tableLayoutKeyboard.ColumnCount = 0;
tableLayoutMatrix.ColumnCount = 0;
}
public int InitGPUMode()
@@ -813,10 +1027,15 @@ namespace GHelper
else
GpuMode = ASUSWmi.GPUModeStandard;
if (mux != 1)
Disable_Ultimate();
UltimateUI(mux == 1);
}
ButtonEnabled(buttonOptimized, true);
ButtonEnabled(buttonEco, true);
ButtonEnabled(buttonStandard, true);
ButtonEnabled(buttonUltimate, true);
Program.config.setConfig("gpu_mode", GpuMode);
VisualiseGPUMode(GpuMode);
@@ -824,13 +1043,54 @@ namespace GHelper
}
public void SetGPUMode(int GPUMode = ASUSWmi.GPUModeStandard)
public void SetEcoGPU(int eco)
{
ButtonEnabled(buttonOptimized, false);
ButtonEnabled(buttonEco, false);
ButtonEnabled(buttonStandard, false);
ButtonEnabled(buttonUltimate, false);
labelGPU.Text = "GPU Mode: Changing ...";
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
if (eco == 1)
{
string[] tokill = { "EADesktop", "RadeonSoftware" };
foreach (string kill in tokill)
foreach (var process in Process.GetProcessesByName(kill)) process.Kill();
}
Program.wmi.DeviceSet(ASUSWmi.GPUEco, eco);
Program.settingsForm.BeginInvoke(delegate
{
InitGPUMode();
HardwareMonitor.RecreateGpuTemperatureProviderWithRetry();
Thread.Sleep(500);
AutoScreen(SystemInformation.PowerStatus.PowerLineStatus);
});
})
{
}.Start();
}
public void SetGPUMode(int GPUMode)
{
int CurrentGPU = Program.config.getConfig("gpu_mode");
Program.config.setConfig("gpu_auto", 0);
if (CurrentGPU == GPUMode)
{
VisualiseGPUMode();
return;
}
var restart = false;
var changed = false;
@@ -847,7 +1107,7 @@ namespace GHelper
}
else if (GPUMode == ASUSWmi.GPUModeUltimate)
{
DialogResult dialogResult = MessageBox.Show(" Ultimate Mode requires restart", "Reboot now?", MessageBoxButtons.YesNo);
DialogResult dialogResult = MessageBox.Show("Ultimate Mode requires restart", "Reboot now?", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes)
{
Program.wmi.DeviceSet(ASUSWmi.GPUMux, 0);
@@ -859,68 +1119,68 @@ namespace GHelper
else if (GPUMode == ASUSWmi.GPUModeEco)
{
VisualiseGPUMode(GPUMode);
Program.wmi.DeviceSet(ASUSWmi.GPUEco, 1);
SetEcoGPU(1);
changed = true;
}
else if (GPUMode == ASUSWmi.GPUModeStandard)
{
VisualiseGPUMode(GPUMode);
Program.wmi.DeviceSet(ASUSWmi.GPUEco, 0);
SetEcoGPU(0);
changed = true;
}
if (changed)
{
Program.config.setConfig("gpu_mode", GPUMode);
HardwareMonitor.RecreateGpuTemperatureProviderWithRetry();
}
if (restart)
{
VisualiseGPUMode(GPUMode);
VisualiseGPUMode();
Process.Start("shutdown", "/r /t 1");
}
}
public void VisualiseGPUAuto(int GPUAuto)
{
checkGPU.Checked = (GPUAuto == 1);
}
public void VisualiseScreenAuto(int ScreenAuto)
{
checkScreen.Checked = (ScreenAuto == 1);
}
public void VisualiseGPUMode(int GPUMode = -1)
{
if (GPUMode == -1)
{
GPUMode = Program.config.getConfig("gpu_mode");
}
buttonEco.FlatAppearance.BorderSize = buttonInactive;
buttonStandard.FlatAppearance.BorderSize = buttonInactive;
buttonUltimate.FlatAppearance.BorderSize = buttonInactive;
bool GPUAuto = (Program.config.getConfig("gpu_auto") == 1);
buttonEco.Activated = false;
buttonStandard.Activated = false;
buttonUltimate.Activated = false;
buttonOptimized.Activated = false;
switch (GPUMode)
{
case ASUSWmi.GPUModeEco:
buttonEco.FlatAppearance.BorderSize = buttonActive;
buttonOptimized.BorderColor = colorEco;
buttonEco.Activated = !GPUAuto;
buttonOptimized.Activated = GPUAuto;
labelGPU.Text = "GPU Mode: iGPU only";
Program.trayIcon.Icon = GHelper.Properties.Resources.eco;
Program.trayIcon.Icon = Properties.Resources.eco;
break;
case ASUSWmi.GPUModeUltimate:
buttonUltimate.FlatAppearance.BorderSize = buttonActive;
buttonUltimate.Activated = true;
labelGPU.Text = "GPU Mode: dGPU exclusive";
Program.trayIcon.Icon = GHelper.Properties.Resources.ultimate;
Program.trayIcon.Icon = Properties.Resources.ultimate;
break;
default:
buttonStandard.FlatAppearance.BorderSize = buttonActive;
labelGPU.Text = "GPU Mode: iGPU and dGPU";
Program.trayIcon.Icon = GHelper.Properties.Resources.standard;
buttonOptimized.BorderColor = colorStandard;
buttonStandard.Activated = !GPUAuto;
buttonOptimized.Activated = GPUAuto;
labelGPU.Text = "GPU Mode: iGPU + dGPU";
Program.trayIcon.Icon = Properties.Resources.standard;
break;
}
}
@@ -944,30 +1204,20 @@ namespace GHelper
}
public void Disable_Ultimate()
public void ButtonEnabled(Button but, bool enabled)
{
buttonUltimate.Enabled = false;
buttonUltimate.BackColor = SystemColors.ControlLight;
but.Enabled = enabled;
but.BackColor = enabled ? SystemColors.ControlLightLight : SystemColors.ControlLight;
}
public void SetStartupCheck(bool status)
{
checkStartup.CheckedChanged -= CheckStartup_CheckedChanged;
checkStartup.Checked = status;
}
private void checkStartup_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
if (chk.Checked)
{
Startup.Schedule();
}
else
{
Startup.UnSchedule();
}
checkStartup.CheckedChanged += CheckStartup_CheckedChanged;
}
public void SetBatteryChargeLimit(int limit = 100)
public void SetBatteryChargeLimit(int limit)
{
if (limit < 40 || limit > 100) return;
@@ -987,21 +1237,6 @@ namespace GHelper
SetBatteryChargeLimit(bar.Value);
}
private void checkGPU_CheckedChanged(object? sender, EventArgs e)
{
if (sender is null) return;
CheckBox check = (CheckBox)sender;
Program.config.setConfig("gpu_auto", check.Checked ? 1 : 0);
}
private void checkScreen_CheckedChanged(object? sender, EventArgs e)
{
if (sender is null) return;
CheckBox check = (CheckBox)sender;
Program.config.setConfig("screen_auto", check.Checked ? 1 : 0);
}
}

View File

@@ -22,16 +22,26 @@ public class Startup
var userId = WindowsIdentity.GetCurrent().Name;
//Debug.WriteLine(strExeFilePath);
TaskDefinition td = TaskService.Instance.NewTask();
td.RegistrationInfo.Description = "GHelper Auto Start";
td.Triggers.Add(new LogonTrigger { UserId = userId, });
td.Triggers.Add(new LogonTrigger { UserId = userId });
td.Actions.Add(strExeFilePath);
td.Settings.StopIfGoingOnBatteries = false;
td.Settings.DisallowStartIfOnBatteries = false;
td.Settings.ExecutionTimeLimit = TimeSpan.Zero;
Debug.WriteLine(strExeFilePath);
Debug.WriteLine(userId);
try
{
TaskService.Instance.RootFolder.RegisterTaskDefinition(taskName, td);
} catch (Exception e)
{
MessageBox.Show(e.ToString(), "Scheduler Error", MessageBoxButtons.OK);
}
TaskService.Instance.RootFolder.RegisterTaskDefinition(taskName, td);
}
public static void UnSchedule()

View File

@@ -54,7 +54,8 @@
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!--<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor/dpiAwareness>-->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor, System</dpiAwareness>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">System</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

View File

@@ -5,6 +5,7 @@ sc STOP ASUSSoftwareManager
sc STOP ASUSSwitch
sc STOP ASUSSystemAnalysis
sc STOP ASUSSystemDiagnosis
sc STOP ArmouryCrateControlInterface
sc DELETE AsusAppService
sc DELETE ASUSLinkNear
@@ -13,3 +14,4 @@ sc DELETE ASUSSoftwareManager
sc DELETE ASUSSwitch
sc DELETE ASUSSystemAnalysis
sc DELETE ASUSSystemDiagnosis
sc DELETE ArmouryCrateControlInterface

109
docs/README.md Normal file
View File

@@ -0,0 +1,109 @@
# [G-Helper (GHelper)](https://github.com/seerge/g-helper)
[![Github all releases](https://img.shields.io/github/downloads/seerge/g-helper/total.svg)](https://GitHub.com/seerge/g-helper/releases/) [![GitHub release](https://img.shields.io/github/release/seerge/g-helper.svg)](https://GitHub.com/seerge/g-helper/releases/) [![GitHub license](https://badgen.net/github/license/seerge/g-helper)](https://github.com/seerge/g-helper/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/seerge/g-helper.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/seerge/g-helper/stargazers/)
## Open source Armory Crate alternative for Asus ROG Zephyrus G14, G15, Flow X13, Flow X16, and other models
A small utility that allows you to do almost everything you could do with Armory Crate but without extra bloat and unnecessary services.
### :gift: Main advantages
1. Seamless and automatic GPU switching (without asking you to close all apps, etc)
2. All performance modes can be fully customized (with fan curves and PPTs)
3. Very lightweight and consumes almost no resources, doesn't install any services. Just a single exe to run
### [:floppy_disk: Download latest release](https://github.com/seerge/g-helper/releases/latest/download/GHelper.zip)
If you like this app, please [star :star: it on Github](https://github.com/seerge/g-helper) and spread a word about it!
![Screenshot](https://raw.githubusercontent.com/seerge/g-helper/main/docs/screenshot.png)
### :zap: Main features
1. Built-in **Performance modes**: Silent - Balanced - Turbo (with default fan curves)
2. **GPU modes**: Eco - Standard - Ultimate - Optimized
3. Laptop screen refresh rate 60hz or 120hz (144hz, etc depending on the model) with display overdrive (OD)
4. Default and custom fan profiles for every performance mode
5. Power limits (PPT) for every performance mode
6. CPU turbo boost mode
7. Keyboard backlit animation and colors
8. Anime matrix control thanks to [Starlight](https://github.com/vddCore/Starlight) + some tweaks from my side (including animated GIFs)
9. FN+F5 cycles performance modes, FN+F4 cycles keyboard animation modes
10. Keybindings for M3 and M4 keys
11. Battery charge limit to preserve battery health
12. Monitor CPU / GPU temperature, fan speeds and battery discharge rate
### :apple: Automatic switching of modes when on battery or plugged in
- Performance modes (app remembers last mode used on battery or when plugged)
- Optimized GPU mode - disables dGPU on battery and enables when plugged
- Auto Screen refresh rate (60hz on battery, 120+ hz when plugged)
To keep auto switching and hotkeys working the app needs to stay in running in the tray. It doesn't consume any resources.
### :rocket: Performance Modes
Modes are **same** as in Armory Crate (as they are stored in bios), including default fan curves
1. Silent (minimal or no fans, 70W PPT total, up to 45W PPT to CPU) + Best power efficiency setting in windows
2. Balanced (balanced fans, 100W PPT total, up to 45W PPT to CPU) + Balanced setting in windows
3. Turbo (intense fans, 125W PPT total, up to 80W PPT to CPU) + Best performance setting in windows
PPTs are shown for G14 2022, for other models PPTs will be different as they are set in bios.
### :video_game: GPU Modes
1. Eco mode : only low power integrated GPU enabled, iGPU drives built in display
2. Standard mode (Windows Hybrid) : iGPU and dGPU enabled, iGPU drives built in display
3. Ultimate mode: iGPU and dGPU enabled, but dGPU drives built in display (supported only on G14 2022 model)
4. Optimized (formely existed as a checkbox): disables dGPU on battery (Eco) and enables when plugged (Standard)
### :question: FAQ
#### How do I stop Armory Crate install popup appearing every time I press M4 / Rog key?
Go to BIOS (F2 on boot), open Advanced Settings (F8) and disable "Armory Control Intrerface"
#### Why Ultimate GPU mode is not available on my laptop?
Ultimate mode is supported (by hardware) only on G14 2022 (and possibly other models from 2022+)
#### App doesn't start / or crashes, what should I do ?
Open "Event Viewer" from start menu, go to Windows Logs -> Application and check for recent Errors mentioning G-Helper. If you see one - please post a [new issue](https://github.com/seerge/g-helper/issues) with all details from this error.
----------------------------
### How to install
1. Download latest release from [**Releases Page**](https://github.com/seerge/g-helper/releases)
2. Unzip to a folder of your choice
3. Run **GHelper.exe**
### Dependencies
- App requires [.NET7](https://dotnet.microsoft.com/en-us/download) to be installed. Most probably you already have it. Otherwise you can [download it](https://dotnet.microsoft.com/en-us/download).
- I recommend keeping "Asus Optimization Service" running, as it keeps basic laptop hotkeys such as screen or keyboard brightness adjustment working. If you have (or had) MyASUS app installed, that service is most probably still up and running even after MyASUS uninstalls. It's part of [Asus System Control Interface](https://www.asus.com/support/FAQ/1047338/). You can install it, and later disable / remove unnecessary services by running [this bat file](https://raw.githubusercontent.com/seerge/g-helper/main/debloat.bat) as admin.
- It's not recommended to use an app in combination with Armory Crate, cause they adjust the same settings. You can [uninstall it using it's own uninstall tool](https://dlcdnets.asus.com/pub/ASUS/mb/14Utilities/Armoury_Crate_Uninstall_Tool.zip?model=armoury%20crate). Just in case, you can always install it back later.
Note: Doesn't need administrator privileges to run!
-------------------------------
Designed and developed for Asus Zephyrus G14 2022 (with AMD Radeon iGPU and dGPU). But could and should potentially work for G14 of 2021 and 2020, G15, X FLOW, and other ROG models for relevant and supported features.
I don't have a Microsoft certificate to sign the app yet, so if you get a warning from Windows Defender on launch (Windows Protected your PC), click More Info -> Run anyway. Alternatively you can compile and run project by yourself using Visual Studio :)
Settings file is stored at ``%AppData%\GHelper``
------------------
Debloating helps to save your battery and keep laptop a bit cooler
![Helps to save your battery](https://raw.githubusercontent.com/seerge/g-helper/main/docs/screenshots/screen-5w.png)
---------
**Disclaimers**
"ROG", "TUF", and "Armoury Crate" are trademarked by and belong to AsusTek Computer, Inc. I make no claims to these or any assets belonging to AsusTek Computer and use them purely for informational purposes only.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MISUSE OF THIS SOFTWARE COULD CAUSE SYSTEM INSTABILITY OR MALFUNCTION.

4
docs/_config.yml Normal file
View File

@@ -0,0 +1,4 @@
title: G-Helper
description: Open source Armory Crate alternative for Asus ROG Zephyrus G14, G15, Flow X13, Flow X16, and other models
plugins:
- jemoji

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="{{ page.lang | default: site.lang | default: "en-US" }}">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
{% seo %}
<link rel="stylesheet" href="{{ "/assets/css/style.css?v=" | append: site.github.build_revision | relative_url }}">
{% include head-custom.html %}
</head>
<body>
<div class="container-lg px-3 my-5 markdown-body">
{{ content }}
{% if site.github.private != true and site.github.license %}
<div class="footer border-top border-gray-light mt-5 pt-3 text-right text-gray">
This site is open source. {% github_edit_link "Improve this page" %}.
</div>
{% endif %}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/4.1.0/anchor.min.js" integrity="sha256-lZaRhKri35AyJSypXXs4o6OPFTbTmUoltBbDCbdzegg=" crossorigin="anonymous"></script>
<script>anchors.add();</script>
</body>
</html>

BIN
docs/screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

Before

Width:  |  Height:  |  Size: 955 KiB

After

Width:  |  Height:  |  Size: 955 KiB

View File

@@ -1 +0,0 @@
ps2exe .\ghelper.ps1 g14-helper.exe -title 'G14 Helper' -DPIAware -winFormsDPIAware -requireAdmin -iconFile 'standard.ico' -noConsole -copyright 'G14 Helper Tool' -noOutput

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB