Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9558fd67bb | ||
|
|
59b62a835b | ||
|
|
ad6847ec59 | ||
|
|
061c255978 | ||
|
|
bb44d0907d | ||
|
|
2215b17a54 | ||
|
|
cc52eab3f6 | ||
|
|
155a4ce50a | ||
|
|
17739377bd | ||
|
|
782fae1624 | ||
|
|
59ca1f18d6 | ||
|
|
c6cda6eb30 | ||
|
|
9f3c5d8de6 | ||
|
|
e4c9ac6ee3 | ||
|
|
5d6500523b | ||
|
|
b111ccabb5 | ||
|
|
b90a67aa43 | ||
|
|
9ed72839f4 | ||
|
|
b8f50da45f | ||
|
|
1e4dada672 | ||
|
|
a943d14807 | ||
|
|
2cf437ff34 | ||
|
|
7cbccbbb5b | ||
|
|
f79af5b6f7 | ||
|
|
05af1d04ff | ||
|
|
2753646f06 | ||
|
|
2b3889c897 | ||
|
|
e01e346dea | ||
|
|
7735037ad9 | ||
|
|
b2bcd5fc3a | ||
|
|
a40ea357db | ||
|
|
7434c22772 | ||
|
|
f0eb25b88c | ||
|
|
7ec9827db5 | ||
|
|
eeca31c92e | ||
|
|
2cd736035c | ||
|
|
bc99616e43 | ||
|
|
732f27fcf6 | ||
|
|
54e8465e47 | ||
|
|
7ceb02c001 | ||
|
|
2450a348f1 | ||
|
|
7bd469939e | ||
|
|
89180359c0 | ||
|
|
4259ace5c4 | ||
|
|
d7e5c38a62 | ||
|
|
b601105998 | ||
|
|
ca07d0716f | ||
|
|
eb16df3450 | ||
|
|
b44684760d | ||
|
|
be3fc1bb84 | ||
|
|
e781e67b43 | ||
|
|
40800ffe4b | ||
|
|
4e704e59e8 | ||
|
|
06e5d5e3d1 | ||
|
|
06010d7cd6 | ||
|
|
2549cd9a71 | ||
|
|
e89e35436e | ||
|
|
f5029ee3e9 | ||
|
|
08a84e0a8b | ||
|
|
36c819de04 | ||
|
|
f62987af4b | ||
|
|
8d9b44d6ec | ||
|
|
a5babb722d | ||
|
|
bde65f094d | ||
|
|
3fa2cfabd3 | ||
|
|
b8f4d02e4f | ||
|
|
436b7feb8e | ||
|
|
8bab4dd6ee | ||
|
|
99dfea631b | ||
|
|
16501bd6a8 | ||
|
|
88201b7308 | ||
|
|
2fb680b06a | ||
|
|
fb8116107b | ||
|
|
e6b83a1db5 | ||
|
|
607a19048b | ||
|
|
0db831e0c3 | ||
|
|
863cca507d | ||
|
|
3916a252d4 | ||
|
|
1594b76851 | ||
|
|
9e14fc5241 | ||
|
|
54fd3e2fd1 | ||
|
|
2348f8dba2 | ||
|
|
f0a3dc48f9 | ||
|
|
58ad43213b | ||
|
|
4a505b7238 | ||
|
|
7c6c0e68d2 | ||
|
|
1c5b22710d | ||
|
|
75755528b1 | ||
|
|
4dadcaf574 | ||
|
|
5a88d53443 | ||
|
|
2bd5faa7d9 | ||
|
|
29cb868f50 | ||
|
|
4eb222f5aa | ||
|
|
eca6ab2297 | ||
|
|
749e5147df | ||
|
|
55e84d0051 | ||
|
|
8cd9727429 | ||
|
|
660e839bed | ||
|
|
afb16d2045 | ||
|
|
f4b025f33c | ||
|
|
e03c3b7be0 | ||
|
|
5a2ba5f785 | ||
|
|
e1463dca05 | ||
|
|
82972127a1 | ||
|
|
272eaed351 | ||
|
|
989e67daac | ||
|
|
dcec618ae9 | ||
|
|
bc12388b6d | ||
|
|
6625488180 | ||
|
|
1209337af6 | ||
|
|
0f608b1702 | ||
|
|
cf547d517b | ||
|
|
8c75c68dca | ||
|
|
ab020c0a90 | ||
|
|
44dc402b54 | ||
|
|
a1d047f48d | ||
|
|
cbed5e11ab | ||
|
|
1ad3f6c441 | ||
|
|
820a26ba2a | ||
|
|
f0952119b6 | ||
|
|
ca5ddbd779 | ||
|
|
be49a27118 | ||
|
|
190353dc11 | ||
|
|
4a1772df77 | ||
|
|
460d1b8471 | ||
|
|
2493c798bc | ||
|
|
7525baf567 | ||
|
|
3f9a5f61fb | ||
|
|
b9156d6861 | ||
|
|
5d59be7b77 | ||
|
|
dd4c5a8732 | ||
|
|
837543fb0f | ||
|
|
03ede8f171 | ||
|
|
078d8164fc | ||
|
|
ceff8a083e | ||
|
|
b32efcc177 | ||
|
|
d57fccc463 | ||
|
|
26cf028f2d | ||
|
|
6e80c9a75f | ||
|
|
42bdfb55f2 | ||
|
|
e0967a9fd6 | ||
|
|
2406ce4f86 | ||
|
|
3b40a4a3e5 | ||
|
|
38c408dde6 | ||
|
|
5e62eb3f5d | ||
|
|
b4b5599ed2 | ||
|
|
b4917f3e1a | ||
|
|
e6b4cb6612 | ||
|
|
b1ca62ce61 | ||
|
|
243f614887 | ||
|
|
a8577378f6 | ||
|
|
564703b7c5 | ||
|
|
5ef56bed25 | ||
|
|
afddb963a9 | ||
|
|
aa72176196 | ||
|
|
7af0721847 | ||
|
|
2a6320e646 | ||
|
|
fc212bb419 | ||
|
|
14e0053335 | ||
|
|
8f28daceef | ||
|
|
f1044673d0 | ||
|
|
61a0ebffee | ||
|
|
8de8f4013e | ||
|
|
dd447553d4 | ||
|
|
11c456e00c | ||
|
|
5efb4bdd6b | ||
|
|
e331f1249b | ||
|
|
786467d7ea | ||
|
|
496e77301b | ||
|
|
d657f1d156 | ||
|
|
7ab5c2f540 | ||
|
|
71900721cf | ||
|
|
0bc9547701 | ||
|
|
96ac254022 | ||
|
|
92f378a80f | ||
|
|
589af01ad8 |
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -6,4 +6,4 @@
|
|||||||
url = https://github.com/ppkantorski/libultrahand
|
url = https://github.com/ppkantorski/libultrahand
|
||||||
[submodule "Source/sys-clk/overlay/lib/libultrahand"]
|
[submodule "Source/sys-clk/overlay/lib/libultrahand"]
|
||||||
path = Source/sys-clk/overlay/lib/libultrahand
|
path = Source/sys-clk/overlay/lib/libultrahand
|
||||||
url = https://github.com/ppkantorski/libultrahand
|
url = https://github.com/ppkantorski/libultrahand
|
||||||
2
LICENSE
2
LICENSE
@@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
- Although "sys-clk" uses permissive license, all modifications towards it in this repo ("hoc-clk") are licensed under GPL v2.
|
- Although "sys-clk" uses permissive license, all modifications towards it in this repo ("hoc-clk") are licensed under GPL v2.
|
||||||
|
|
||||||
|
- Status-Monitor is licensed under the GPLv2
|
||||||
|
|
||||||
GNU GENERAL PUBLIC LICENSE
|
GNU GENERAL PUBLIC LICENSE
|
||||||
Version 2, June 1991
|
Version 2, June 1991
|
||||||
|
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
<img src="assets/logo.png" alt="logo" width="350"/>
|
<img src="assets/logo.png" alt="logo" width="768"/>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -36,12 +36,12 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
|
|||||||
|
|
||||||
* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista)
|
* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista)
|
||||||
* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista)
|
* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista)
|
||||||
* **RAM:** Up to 1866MHz (Mariko) / 1600MHz (Erista)
|
* **RAM:** Up to 1866/2133MHz (Mariko) / 1600MHz (Erista)
|
||||||
* Over/undervolting support
|
* Over/undervolting support
|
||||||
* Built-in configurator
|
* Built-in configurator
|
||||||
* Compatible with most homebrew
|
* Compatible with most homebrew
|
||||||
|
|
||||||
> It is reccomended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
|
> It is recommended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -56,7 +56,6 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
|
|||||||
|
|
||||||
```
|
```
|
||||||
kip1=atmosphere/kips/hoc.kip
|
kip1=atmosphere/kips/hoc.kip
|
||||||
secmon=exosphere.bin
|
|
||||||
```
|
```
|
||||||
|
|
||||||
*(No changes needed if using fusee.)*
|
*(No changes needed if using fusee.)*
|
||||||
@@ -114,6 +113,9 @@ Refer to COMPILATION.md
|
|||||||
* 816
|
* 816
|
||||||
* 714
|
* 714
|
||||||
* 612 → sleep mode
|
* 612 → sleep mode
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
1. On Erista, CPU in handheld is capped to 1581MHz
|
||||||
|
|
||||||
### GPU clocks
|
### GPU clocks
|
||||||
* 1536 → absolute max clock on mariko. very dangerous
|
* 1536 → absolute max clock on mariko. very dangerous
|
||||||
@@ -140,8 +142,10 @@ Refer to COMPILATION.md
|
|||||||
* 76 → boost mode
|
* 76 → boost mode
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
1. GPU overclock is capped at 460MHz in handheld and capped at 768MHz if charging, unless you're using the official charger.
|
1. GPU overclock is capped at 460MHz on erista in handheld
|
||||||
2. Clocks higher than 768MHz need the official charger is plugged in.
|
2. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz
|
||||||
|
3. Clocks higher than 768MHz on erista need the official charger is plugged in.
|
||||||
|
4. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -160,5 +164,5 @@ Refer to COMPILATION.md
|
|||||||
* **b0rd2death** – Ultrahand sys-clk & Status Monitor fork
|
* **b0rd2death** – Ultrahand sys-clk & Status Monitor fork
|
||||||
* **MasaGratoR and ZachyCatGames** - General help
|
* **MasaGratoR and ZachyCatGames** - General help
|
||||||
* **MasaGratoR** - Status Monitor & Display Refresh Rate Driver
|
* **MasaGratoR** - Status Monitor & Display Refresh Rate Driver
|
||||||
* **Dom, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh and Xenshen** - Testing
|
* **Dom, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00 and Xenshen** - Testing
|
||||||
* **Samybigio2011** - Italian translations
|
* **Samybigio2011** - Italian translations
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| 0.x | :white_check_mark: |
|
| 1.x | :white_check_mark: |
|
||||||
|
| 0.x | Not supported |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
Contact me on discord (soul_9017) or email me (souldbminer@gmail.com)
|
Contact Souldbminer or Lightos_ on discord (souldbminer, lightos_)
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define __ACCESS_TABLE_NAME__ SocthermAccessTable
|
#define __ACCESS_TABLE_NAME__ EmcAccessTable1
|
||||||
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceSoctherm.GetAddress()
|
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController1.GetAddress()
|
||||||
#define __ACCESS_TABLE_INC__ "secmon_soctherm_access_table_data.inc"
|
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
|
||||||
|
|
||||||
#include "secmon_define_access_table.inc"
|
#include "secmon_define_access_table.inc"
|
||||||
|
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __ACCESS_TABLE_NAME__ EmcAccessTable2
|
||||||
|
#define __ACCESS_TABLE_ADDRESS__ MemoryRegionPhysicalDeviceExternalMemoryController2.GetAddress()
|
||||||
|
#define __ACCESS_TABLE_INC__ "secmon_emc_access_table_data.inc"
|
||||||
|
|
||||||
|
#include "secmon_define_access_table.inc"
|
||||||
|
|
||||||
|
#undef __ACCESS_TABLE_INC__
|
||||||
|
#undef __ACCESS_TABLE_ADDRESS__
|
||||||
|
#undef __ACCESS_TABLE_NAME__
|
||||||
@@ -965,3 +965,76 @@ SetRegisterAllowed(0xECC);
|
|||||||
SetRegisterAllowed(0xED0);
|
SetRegisterAllowed(0xED0);
|
||||||
SetRegisterAllowed(0xED4);
|
SetRegisterAllowed(0xED4);
|
||||||
SetRegisterAllowed(0xED8);
|
SetRegisterAllowed(0xED8);
|
||||||
|
SetRegisterAllowed(0xEDC);
|
||||||
|
SetRegisterAllowed(0xEE0);
|
||||||
|
SetRegisterAllowed(0xEE4);
|
||||||
|
SetRegisterAllowed(0xEE8);
|
||||||
|
SetRegisterAllowed(0xEEC);
|
||||||
|
SetRegisterAllowed(0xEF0);
|
||||||
|
SetRegisterAllowed(0xEF4);
|
||||||
|
SetRegisterAllowed(0xEF8);
|
||||||
|
SetRegisterAllowed(0xEFC);
|
||||||
|
SetRegisterAllowed(0xF00);
|
||||||
|
SetRegisterAllowed(0xF04);
|
||||||
|
SetRegisterAllowed(0xF08);
|
||||||
|
SetRegisterAllowed(0xF0C);
|
||||||
|
SetRegisterAllowed(0xF10);
|
||||||
|
SetRegisterAllowed(0xF14);
|
||||||
|
SetRegisterAllowed(0xF18);
|
||||||
|
SetRegisterAllowed(0xF1C);
|
||||||
|
SetRegisterAllowed(0xF20);
|
||||||
|
SetRegisterAllowed(0xF24);
|
||||||
|
SetRegisterAllowed(0xF28);
|
||||||
|
SetRegisterAllowed(0xF2C);
|
||||||
|
SetRegisterAllowed(0xF30);
|
||||||
|
SetRegisterAllowed(0xF34);
|
||||||
|
SetRegisterAllowed(0xF38);
|
||||||
|
SetRegisterAllowed(0xF3C);
|
||||||
|
SetRegisterAllowed(0xF40);
|
||||||
|
SetRegisterAllowed(0xF44);
|
||||||
|
SetRegisterAllowed(0xF48);
|
||||||
|
SetRegisterAllowed(0xF4C);
|
||||||
|
SetRegisterAllowed(0xF50);
|
||||||
|
SetRegisterAllowed(0xF54);
|
||||||
|
SetRegisterAllowed(0xF58);
|
||||||
|
SetRegisterAllowed(0xF5C);
|
||||||
|
SetRegisterAllowed(0xF60);
|
||||||
|
SetRegisterAllowed(0xF64);
|
||||||
|
SetRegisterAllowed(0xF68);
|
||||||
|
SetRegisterAllowed(0xF6C);
|
||||||
|
SetRegisterAllowed(0xF70);
|
||||||
|
SetRegisterAllowed(0xF74);
|
||||||
|
SetRegisterAllowed(0xF78);
|
||||||
|
SetRegisterAllowed(0xF7C);
|
||||||
|
SetRegisterAllowed(0xF80);
|
||||||
|
SetRegisterAllowed(0xF84);
|
||||||
|
SetRegisterAllowed(0xF88);
|
||||||
|
SetRegisterAllowed(0xF8C);
|
||||||
|
SetRegisterAllowed(0xF90);
|
||||||
|
SetRegisterAllowed(0xF94);
|
||||||
|
SetRegisterAllowed(0xF98);
|
||||||
|
SetRegisterAllowed(0xF9C);
|
||||||
|
SetRegisterAllowed(0xFA0);
|
||||||
|
SetRegisterAllowed(0xFA4);
|
||||||
|
SetRegisterAllowed(0xFA8);
|
||||||
|
SetRegisterAllowed(0xFAC);
|
||||||
|
SetRegisterAllowed(0xFB0);
|
||||||
|
SetRegisterAllowed(0xFB4);
|
||||||
|
SetRegisterAllowed(0xFB8);
|
||||||
|
SetRegisterAllowed(0xFBC);
|
||||||
|
SetRegisterAllowed(0xFC0);
|
||||||
|
SetRegisterAllowed(0xFC4);
|
||||||
|
SetRegisterAllowed(0xFC8);
|
||||||
|
SetRegisterAllowed(0xFCC);
|
||||||
|
SetRegisterAllowed(0xFD0);
|
||||||
|
SetRegisterAllowed(0xFD4);
|
||||||
|
SetRegisterAllowed(0xFD8);
|
||||||
|
SetRegisterAllowed(0xFDC);
|
||||||
|
SetRegisterAllowed(0xFE0);
|
||||||
|
SetRegisterAllowed(0xFE4);
|
||||||
|
SetRegisterAllowed(0xFE8);
|
||||||
|
SetRegisterAllowed(0xFEC);
|
||||||
|
SetRegisterAllowed(0xFF0);
|
||||||
|
SetRegisterAllowed(0xFF4);
|
||||||
|
SetRegisterAllowed(0xFF8);
|
||||||
|
SetRegisterAllowed(0xFFC);
|
||||||
|
|||||||
@@ -129,33 +129,32 @@ namespace ams::secmon {
|
|||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceEmpty = MemoryRegion(MemoryRegionVirtualDevice.GetStartAddress(), 0);
|
constexpr inline const MemoryRegion MemoryRegionVirtualDeviceEmpty = MemoryRegion(MemoryRegionVirtualDevice.GetStartAddress(), 0);
|
||||||
|
|
||||||
#define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
|
#define AMS_SECMON_FOREACH_DEVICE_REGION(HANDLER, ...) \
|
||||||
HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(GicDistributor, Empty, UINT64_C(0x50041000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
HANDLER(GicCpuInterface, GicDistributor, UINT64_C(0x50042000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Uart, GicCpuInterface, UINT64_C(0x70006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
|
HANDLER(Uart, GicCpuInterface, UINT64_C(0x70006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
|
||||||
HANDLER(ClkRst, Uart, UINT64_C(0x60006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
|
HANDLER(ClkRst, Uart, UINT64_C(0x60006000), UINT64_C(0x1000), false, ## __VA_ARGS__) \
|
||||||
HANDLER(RtcPmc, ClkRst, UINT64_C(0x7000E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(RtcPmc, ClkRst, UINT64_C(0x7000E000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Timer, RtcPmc, UINT64_C(0x60005000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(Timer, RtcPmc, UINT64_C(0x60005000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(System, Timer, UINT64_C(0x6000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(System, Timer, UINT64_C(0x6000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(SecurityEngine, System, UINT64_C(0x70012000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
HANDLER(SecurityEngine, System, UINT64_C(0x70012000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
HANDLER(SecurityEngine2, SecurityEngine, UINT64_C(0x70412000), UINT64_C(0x2000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(SysCtr0, SecurityEngine2, UINT64_C(0x700F0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(SysCtr0, SecurityEngine2, UINT64_C(0x700F0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(MemoryController, SysCtr0, UINT64_C(0x70019000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(MemoryController, SysCtr0, UINT64_C(0x70019000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(ExternalMemoryController, MemoryController, UINT64_C(0x7001b000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(ExternalMemoryController, MemoryController, UINT64_C(0x7001b000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(FuseKFuse, ExternalMemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(FuseKFuse, ExternalMemoryController, UINT64_C(0x7000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(ApbMisc, FuseKFuse, UINT64_C(0x70000000), UINT64_C(0x4000), true, ## __VA_ARGS__) \
|
HANDLER(ApbMisc, FuseKFuse, UINT64_C(0x70000000), UINT64_C(0x4000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(FlowController, ApbMisc, UINT64_C(0x60007000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(FlowController, ApbMisc, UINT64_C(0x60007000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(BootloaderParams, FlowController, UINT64_C(0x40000000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(BootloaderParams, FlowController, UINT64_C(0x40000000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(I2c5, BootloaderParams, UINT64_C(0x7000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(I2c5, BootloaderParams, UINT64_C(0x7000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Gpio, I2c5, UINT64_C(0x6000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(Gpio, I2c5, UINT64_C(0x6000D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(I2c1, Gpio, UINT64_C(0x7000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(I2c1, Gpio, UINT64_C(0x7000C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(ExceptionVectors, I2c1, UINT64_C(0x6000F000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(MemoryController0, ExceptionVectors, UINT64_C(0x7001C000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(MemoryController1, MemoryController0, UINT64_C(0x7001D000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(Sdmmc, MemoryController1, UINT64_C(0x700B0000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
|
HANDLER(Disp1, Sdmmc, UINT64_C(0x54200000), UINT64_C(0x3000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(Dsi, Disp1, UINT64_C(0x54300000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
HANDLER(MipiCal, Dsi, UINT64_C(0x700E3000), UINT64_C(0x1000), true, ## __VA_ARGS__) \
|
||||||
HANDLER(Soctherm, MipiCal, UINT64_C(0x700E2000), UINT64_C(0x1000), true, ## __VA_ARGS__)
|
|
||||||
|
|
||||||
#define DEFINE_DEVICE_REGION(_NAME_, _PREV_, _ADDRESS_, _SIZE_, _SECURE_) \
|
#define DEFINE_DEVICE_REGION(_NAME_, _PREV_, _ADDRESS_, _SIZE_, _SECURE_) \
|
||||||
constexpr inline const MemoryRegion MemoryRegionVirtualDevice##_NAME_ = MemoryRegion(MemoryRegionVirtualDevice##_PREV_.GetEndAddress() + 0x1000, _SIZE_); \
|
constexpr inline const MemoryRegion MemoryRegionVirtualDevice##_NAME_ = MemoryRegion(MemoryRegionVirtualDevice##_PREV_.GetEndAddress() + 0x1000, _SIZE_); \
|
||||||
|
|||||||
268
Source/Atmosphere-Patches/secmon_smc_handler.cpp
Normal file
268
Source/Atmosphere-Patches/secmon_smc_handler.cpp
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <exosphere.hpp>
|
||||||
|
#include "../secmon_error.hpp"
|
||||||
|
#include "../secmon_misc.hpp"
|
||||||
|
#include "secmon_smc_common.hpp"
|
||||||
|
#include "secmon_smc_handler.hpp"
|
||||||
|
#include "secmon_smc_aes.hpp"
|
||||||
|
#include "secmon_smc_carveout.hpp"
|
||||||
|
#include "secmon_smc_device_unique_data.hpp"
|
||||||
|
#include "secmon_smc_error.hpp"
|
||||||
|
#include "secmon_smc_info.hpp"
|
||||||
|
#include "secmon_smc_memory_access.hpp"
|
||||||
|
#include "secmon_smc_power_management.hpp"
|
||||||
|
#include "secmon_smc_random.hpp"
|
||||||
|
#include "secmon_smc_register_access.hpp"
|
||||||
|
#include "secmon_smc_result.hpp"
|
||||||
|
#include "secmon_smc_rsa.hpp"
|
||||||
|
|
||||||
|
namespace ams::secmon::smc {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct HandlerInfo {
|
||||||
|
u32 function_id;
|
||||||
|
u32 restriction_mask;
|
||||||
|
SmcHandler handler;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HandlerTable {
|
||||||
|
const HandlerInfo *entries;
|
||||||
|
size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum HandlerType : int {
|
||||||
|
HandlerType_User = 0,
|
||||||
|
HandlerType_Kern = 1,
|
||||||
|
HandlerType_Count = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Restriction {
|
||||||
|
Restriction_None = (0 << 0),
|
||||||
|
Restriction_Normal = (1 << 0),
|
||||||
|
Restriction_DeviceUniqueDataNotAllowed = (1 << 1),
|
||||||
|
Restriction_SafeModeNotAllowed = (1 << 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SmcCallRange {
|
||||||
|
SmcCallRange_ArmArch = 0,
|
||||||
|
SmcCallRange_Cpu = 1,
|
||||||
|
SmcCallRange_Sip = 2,
|
||||||
|
SmcCallRange_Oem = 3,
|
||||||
|
SmcCallRange_Standard = 4,
|
||||||
|
|
||||||
|
SmcCallRange_TrustedApp = 0x30,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SmcArgumentType {
|
||||||
|
ArgumentType_Integer = 0,
|
||||||
|
ArgumentType_Pointer = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SmcConvention {
|
||||||
|
Convention_Smc32 = 0,
|
||||||
|
Convention_Smc64 = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SmcCallType {
|
||||||
|
SmcCallType_YieldingCall = 0,
|
||||||
|
SmcCallType_FastCall = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SmcFunctionId {
|
||||||
|
using FunctionId = util::BitPack64::Field< 0, 8, u32>;
|
||||||
|
using ArgumentType0 = util::BitPack64::Field< 8, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType1 = util::BitPack64::Field< 9, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType2 = util::BitPack64::Field<10, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType3 = util::BitPack64::Field<11, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType4 = util::BitPack64::Field<12, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType5 = util::BitPack64::Field<13, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType6 = util::BitPack64::Field<14, 1, SmcArgumentType>;
|
||||||
|
using ArgumentType7 = util::BitPack64::Field<15, 1, SmcArgumentType>;
|
||||||
|
using Reserved = util::BitPack64::Field<16, 8, u32>;
|
||||||
|
using CallRange = util::BitPack64::Field<24, 6, SmcCallRange>;
|
||||||
|
using Convention = util::BitPack64::Field<30, 1, SmcConvention>;
|
||||||
|
using CallType = util::BitPack64::Field<31, 1, SmcCallType>;
|
||||||
|
using Reserved2 = util::BitPack64::Field<32, 32, u32>;
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit HandlerInfo g_user_handlers[] = {
|
||||||
|
{ 0x00000000, Restriction_SafeModeNotAllowed, nullptr },
|
||||||
|
{ 0xC3000401, Restriction_SafeModeNotAllowed, SmcSetConfig },
|
||||||
|
{ 0xC3000002, Restriction_Normal, SmcGetConfigUser },
|
||||||
|
{ 0xC3000003, Restriction_Normal, SmcGetResult },
|
||||||
|
{ 0xC3000404, Restriction_Normal, SmcGetResultData },
|
||||||
|
{ 0xC3000E05, Restriction_SafeModeNotAllowed, SmcModularExponentiate },
|
||||||
|
{ 0xC3000006, Restriction_Normal, SmcGenerateRandomBytes },
|
||||||
|
{ 0xC3000007, Restriction_Normal, SmcGenerateAesKek },
|
||||||
|
{ 0xC3000008, Restriction_Normal, SmcLoadAesKey },
|
||||||
|
{ 0xC3000009, Restriction_Normal, SmcComputeAes },
|
||||||
|
{ 0xC300000A, Restriction_Normal, SmcGenerateSpecificAesKey },
|
||||||
|
{ 0xC300040B, Restriction_Normal, SmcComputeCmac },
|
||||||
|
{ 0xC300D60C, Restriction_Normal, SmcReencryptDeviceUniqueData },
|
||||||
|
{ 0xC300100D, Restriction_DeviceUniqueDataNotAllowed, SmcDecryptDeviceUniqueData },
|
||||||
|
{ 0xC300000E, Restriction_SafeModeNotAllowed, nullptr },
|
||||||
|
{ 0xC300060F, Restriction_DeviceUniqueDataNotAllowed, SmcModularExponentiateByStorageKey },
|
||||||
|
{ 0xC3000610, Restriction_SafeModeNotAllowed, SmcPrepareEsDeviceUniqueKey },
|
||||||
|
{ 0xC3000011, Restriction_SafeModeNotAllowed, SmcLoadPreparedAesKey },
|
||||||
|
{ 0xC3000012, Restriction_SafeModeNotAllowed, SmcPrepareEsCommonTitleKey }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Deprecated handlerss. */
|
||||||
|
constexpr inline const HandlerInfo DecryptAndImportEsDeviceKeyHandlerInfo = {
|
||||||
|
0xC300100C, Restriction_Normal, SmcDecryptAndImportEsDeviceKey
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr inline const HandlerInfo DecryptAndImportLotusKeyHandlerInfo = {
|
||||||
|
0xC300100E, Restriction_SafeModeNotAllowed, SmcDecryptAndImportLotusKey
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit HandlerInfo g_kern_handlers[] = {
|
||||||
|
{ 0x00000000, Restriction_SafeModeNotAllowed, nullptr },
|
||||||
|
{ 0xC4000001, Restriction_SafeModeNotAllowed, SmcSuspendCpu },
|
||||||
|
{ 0x84000002, Restriction_SafeModeNotAllowed, SmcPowerOffCpu },
|
||||||
|
{ 0xC4000003, Restriction_SafeModeNotAllowed, SmcPowerOnCpu },
|
||||||
|
{ 0xC3000004, Restriction_Normal, SmcGetConfigKern },
|
||||||
|
{ 0xC3000005, Restriction_Normal, SmcGenerateRandomBytesNonBlocking },
|
||||||
|
{ 0xC3000006, Restriction_Normal, SmcShowError },
|
||||||
|
{ 0xC3000007, Restriction_Normal, SmcSetKernelCarveoutRegion },
|
||||||
|
{ 0xC3000008, Restriction_Normal, SmcReadWriteRegister },
|
||||||
|
|
||||||
|
/* NOTE: Atmosphere extension for mesosphere. This ID is subject to change at any time. */
|
||||||
|
{ 0xC3000409, Restriction_Normal, SmcSetConfig },
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit HandlerInfo g_ams_handlers[] = {
|
||||||
|
{ 0x00000000, Restriction_SafeModeNotAllowed, nullptr },
|
||||||
|
{ 0xF0000201, Restriction_None, SmcIramCopy },
|
||||||
|
{ 0xF0000002, Restriction_None, SmcReadWriteRegister },
|
||||||
|
{ 0xF0000003, Restriction_None, SmcWriteAddress },
|
||||||
|
{ 0xF0000404, Restriction_None, SmcGetEmummcConfig },
|
||||||
|
{ 0xF0000005, Restriction_None, SmcShowError },
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr const HandlerInfo GetSecureDataHandlerInfo = {
|
||||||
|
0x67891234, Restriction_None, SmcGetSecureData
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit HandlerTable g_handler_tables[] = {
|
||||||
|
{ g_user_handlers, util::size(g_user_handlers) },
|
||||||
|
{ g_kern_handlers, util::size(g_kern_handlers) },
|
||||||
|
};
|
||||||
|
|
||||||
|
constinit HandlerTable g_ams_handler_table = {
|
||||||
|
g_ams_handlers, util::size(g_ams_handlers)
|
||||||
|
};
|
||||||
|
|
||||||
|
NORETURN void InvalidSmcError(u64 id) {
|
||||||
|
SetError(pkg1::ErrorInfo_UnknownSmc);
|
||||||
|
AMS_ABORT("Invalid SMC: %lx", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const HandlerTable &GetHandlerTable(HandlerType type, u64 id) {
|
||||||
|
/* Ensure we have a valid handler type. */
|
||||||
|
if (AMS_UNLIKELY(!(0 <= type && type < HandlerType_Count))) {
|
||||||
|
InvalidSmcError(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Provide support for legacy SmcGetSecureData. */
|
||||||
|
if (id == GetSecureDataHandlerInfo.function_id) {
|
||||||
|
return g_handler_tables[HandlerType_User];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if we're a user SMC. */
|
||||||
|
if (type == HandlerType_User) {
|
||||||
|
/* Nintendo uses OEM SMCs. */
|
||||||
|
/* We will assign Atmosphere extension SMCs the TrustedApplication range. */
|
||||||
|
if (util::BitPack64{id}.Get<SmcFunctionId::CallRange>() == SmcCallRange_TrustedApp) {
|
||||||
|
return g_ams_handler_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we're not performing an atmosphere extension smc, require that we're being invoked by spl on core 3. */
|
||||||
|
if (AMS_UNLIKELY(hw::GetCurrentCoreId() != 3)) {
|
||||||
|
InvalidSmcError(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_handler_tables[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
const HandlerInfo &GetHandlerInfo(const HandlerTable &table, u64 id) {
|
||||||
|
/* Provide support for legacy SmcGetSecureData. */
|
||||||
|
if (id == GetSecureDataHandlerInfo.function_id) {
|
||||||
|
return GetSecureDataHandlerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get and check the index. */
|
||||||
|
const auto index = util::BitPack64{id}.Get<SmcFunctionId::FunctionId>();
|
||||||
|
if (AMS_UNLIKELY(index >= table.count)) {
|
||||||
|
InvalidSmcError(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get and check the handler info. */
|
||||||
|
const auto &handler_info = table.entries[index];
|
||||||
|
|
||||||
|
/* Check that the handler isn't null. */
|
||||||
|
if (AMS_UNLIKELY(handler_info.handler == nullptr)) {
|
||||||
|
InvalidSmcError(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the handler's id matches. */
|
||||||
|
if (AMS_UNLIKELY(handler_info.function_id != id)) {
|
||||||
|
InvalidSmcError(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return handler_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsHandlerRestricted(const HandlerInfo &info) {
|
||||||
|
return (info.restriction_mask & secmon::GetRestrictedSmcMask()) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmcResult InvokeSmcHandler(const HandlerInfo &info, SmcArguments &args) {
|
||||||
|
/* Check if the smc is restricted. */
|
||||||
|
if (GetTargetFirmware() >= TargetFirmware_8_0_0 && AMS_UNLIKELY(IsHandlerRestricted(info))) {
|
||||||
|
return SmcResult::NotPermitted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invoke the smc. */
|
||||||
|
return info.handler(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConfigureSmcHandlersForTargetFirmware() {
|
||||||
|
const auto target_fw = GetTargetFirmware();
|
||||||
|
|
||||||
|
if (target_fw < TargetFirmware_5_0_0) {
|
||||||
|
g_user_handlers[DecryptAndImportEsDeviceKeyHandlerInfo.function_id & 0xFF] = DecryptAndImportEsDeviceKeyHandlerInfo;
|
||||||
|
g_user_handlers[DecryptAndImportLotusKeyHandlerInfo.function_id & 0xFF] = DecryptAndImportLotusKeyHandlerInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleSmc(int type, SmcArguments &args) {
|
||||||
|
/* Get the table. */
|
||||||
|
const auto &table = GetHandlerTable(static_cast<HandlerType>(type), args.r[0]);
|
||||||
|
|
||||||
|
/* Get the handler info. */
|
||||||
|
const auto &info = GetHandlerInfo(table, args.r[0]);
|
||||||
|
|
||||||
|
/* Set the invocation result. */
|
||||||
|
args.r[0] = static_cast<u64>(InvokeSmcHandler(info, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -99,14 +99,16 @@ namespace ams::secmon::smc {
|
|||||||
#include "secmon_define_pmc_access_table.inc"
|
#include "secmon_define_pmc_access_table.inc"
|
||||||
#include "secmon_define_mc_access_table.inc"
|
#include "secmon_define_mc_access_table.inc"
|
||||||
#include "secmon_define_emc_access_table.inc"
|
#include "secmon_define_emc_access_table.inc"
|
||||||
#include "secmon_define_soctherm_access_table.inc"
|
#include "secmon_define_emc1_access_table.inc"
|
||||||
|
#include "secmon_define_emc2_access_table.inc"
|
||||||
#include "secmon_define_mc01_access_table.inc"
|
#include "secmon_define_mc01_access_table.inc"
|
||||||
|
|
||||||
constexpr const AccessTableEntry AccessTables[] = {
|
constexpr const AccessTableEntry AccessTables[] = {
|
||||||
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
|
{ PmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDevicePmc.GetAddress(), PmcAccessTable::Address, PmcAccessTable::Size, },
|
||||||
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
|
{ McAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceMemoryController.GetAddress(), McAccessTable::Address, McAccessTable::Size, },
|
||||||
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
|
{ EmcAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController.GetAddress(), EmcAccessTable::Address, EmcAccessTable::Size, },
|
||||||
{ SocthermAccessTable::ReducedAccessTable.data(), MemoryRegionVirtualDeviceSoctherm.GetAddress(), SocthermAccessTable::Address, SocthermAccessTable::Size, },
|
{ EmcAccessTable1::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController1.GetAddress(), EmcAccessTable1::Address, EmcAccessTable1::Size, },
|
||||||
|
{ EmcAccessTable2::ReducedAccessTable.data(), MemoryRegionVirtualDeviceExternalMemoryController2.GetAddress(), EmcAccessTable2::Address, EmcAccessTable2::Size, },
|
||||||
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
|
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController0.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController0.GetAddress(), Mc01AccessTable::Size, },
|
||||||
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
|
{ Mc01AccessTable::ReducedAccessTable.data(), Mc01AccessTable::Address + MemoryRegionVirtualDeviceMemoryController1.GetAddress(), Mc01AccessTable::Address + MemoryRegionPhysicalDeviceMemoryController1.GetAddress(), Mc01AccessTable::Size, },
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -22,12 +22,11 @@
|
|||||||
|
|
||||||
/* Never edit these. */
|
/* Never edit these. */
|
||||||
#define AUTO 0
|
#define AUTO 0
|
||||||
#define AUTO_RAM 0
|
|
||||||
#define ENABLED 1
|
#define ENABLED 1
|
||||||
#define DISABLED 0
|
#define DISABLED 0
|
||||||
#define DEACTIVATED_GPU_FREQ 2000
|
#define DEACTIVATED_GPU_FREQ 2000
|
||||||
#define GPU_MIN_MIN_VOLT 480000
|
#define GPU_MIN_MIN_VOLT 480000
|
||||||
#define CPU_MAX_MAX_VOLT 1235000
|
#define CPU_MAX_MAX_VOLT 1200000
|
||||||
|
|
||||||
namespace ams::ldr::hoc {
|
namespace ams::ldr::hoc {
|
||||||
|
|
||||||
@@ -37,6 +36,8 @@ volatile CustomizeTable C = {
|
|||||||
|
|
||||||
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
|
.commonEmcMemVolt = 1175000, /* LPDDR4X JEDEC Specification */
|
||||||
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
.eristaEmcMaxClock = 1600000, /* Maximum HB-MGCH ram rating */
|
||||||
|
.eristaEmcMaxClock1 = 1600000,
|
||||||
|
.eristaEmcMaxClock2 = 1600000,
|
||||||
|
|
||||||
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
.marikoEmcMaxClock = 1866000, /* 1866MHz @ 1866tWRL is guaranteed to work on all Mariko units */
|
||||||
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
|
.marikoEmcVddqVolt = 600000, /* Micron: 600mV, other manafacturers: 640mV */
|
||||||
@@ -79,7 +80,7 @@ volatile CustomizeTable C = {
|
|||||||
.marikoCpuUVLow = 0, // No undervolt
|
.marikoCpuUVLow = 0, // No undervolt
|
||||||
.marikoCpuUVHigh = 0, // No undervolt
|
.marikoCpuUVHigh = 0, // No undervolt
|
||||||
|
|
||||||
.tableConf = DEFAULT_TABLE,
|
.tableConf = TBREAK_1683,
|
||||||
.marikoCpuLowVmin = 620,
|
.marikoCpuLowVmin = 620,
|
||||||
.marikoCpuHighVmin = 750,
|
.marikoCpuHighVmin = 750,
|
||||||
/* 1120mV is NVIDIA rating */
|
/* 1120mV is NVIDIA rating */
|
||||||
@@ -105,7 +106,7 @@ volatile CustomizeTable C = {
|
|||||||
/* For automatic vmin detection, set this to AUTO. */
|
/* For automatic vmin detection, set this to AUTO. */
|
||||||
/* vmin past 795mV won't work due to HOS limitation */
|
/* vmin past 795mV won't work due to HOS limitation */
|
||||||
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
|
/* Vmin is automatically set to 800mV when SoC temperature is below 20C */
|
||||||
.marikoGpuVmin = AUTO,
|
.marikoGpuVmin = AUTO,
|
||||||
|
|
||||||
.marikoGpuVmax = 800,
|
.marikoGpuVmax = 800,
|
||||||
|
|
||||||
@@ -176,6 +177,10 @@ volatile CustomizeTable C = {
|
|||||||
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
|
DEACTIVATED_GPU_FREQ /* 1536 (Disabled by default) */,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* Advanced. */
|
||||||
|
.fineTune_t6_tRTW = 0,
|
||||||
|
.fineTune_t7_tWTR = 0,
|
||||||
|
|
||||||
/* You shouldn't have to anything past here. */
|
/* You shouldn't have to anything past here. */
|
||||||
.eristaCpuDvfsTable = {
|
.eristaCpuDvfsTable = {
|
||||||
{ 204000, { 721094, }, { } },
|
{ 204000, { 721094, }, { } },
|
||||||
@@ -194,9 +199,9 @@ volatile CustomizeTable C = {
|
|||||||
{ 1581000, { 1130000, }, { 2889664, -122173, 1834, } },
|
{ 1581000, { 1130000, }, { 2889664, -122173, 1834, } },
|
||||||
{ 1683000, { 1168000, }, { 5100873, -279186, 4747, } },
|
{ 1683000, { 1168000, }, { 5100873, -279186, 4747, } },
|
||||||
{ 1785000, { 1225000, }, { 5100873, -279186, 4747, } },
|
{ 1785000, { 1225000, }, { 5100873, -279186, 4747, } },
|
||||||
// { 1887000, { 1225000, }, { 5100873, -279186, 4747, } },
|
{ 1887000, { 1225000, }, { 5100873, -279186, 4747, } },
|
||||||
// { 1989000, { 1227500, }, { 5100873, -279186, 4747, } },
|
{ 1989000, { 1227500, }, { 5100873, -279186, 4747, } },
|
||||||
// { 2091000, { 1256250, }, { 5100873, -279186, 4747, } },
|
{ 2091000, { 1256250, }, { 5100873, -279186, 4747, } },
|
||||||
},
|
},
|
||||||
|
|
||||||
.eristaCpuDvfsTableSLT = {
|
.eristaCpuDvfsTableSLT = {
|
||||||
@@ -217,10 +222,11 @@ volatile CustomizeTable C = {
|
|||||||
{ 1683000, { 1168000, }, { 5100873, -279186, 4747, } },
|
{ 1683000, { 1168000, }, { 5100873, -279186, 4747, } },
|
||||||
{ 1785000, { 1225000, }, { 5100873, -279186, 4747, } },
|
{ 1785000, { 1225000, }, { 5100873, -279186, 4747, } },
|
||||||
{ 1887000, { 1225000, }, { 5100873, -279186, 4747, } },
|
{ 1887000, { 1225000, }, { 5100873, -279186, 4747, } },
|
||||||
{ 1989000, { 1227500, }, { 5100873, -279186, 4747, } },
|
{ 1963500, { 1227500, }, { 5100873, -279186, 4747, } },
|
||||||
{ 2091000, { 1256250, }, { 5100873, -279186, 4747, } },
|
{ 2091000, { 1227500, }, { 5100873, -279186, 4747, } },
|
||||||
{ 2193000, { 1256250, }, { 5100873, -279186, 4747, } },
|
{ 2193000, { 1227500, }, { 5100873, -279186, 4747, } },
|
||||||
{ 2295000, { 1256250, }, { 5100873, -279186, 4747, } },
|
{ 2295000, { 1256250, }, { 5100873, -279186, 4747, } },
|
||||||
|
{ 2397000, { 1256250, }, { 5100873, -279186, 4747, } }, // Only for god speedo!
|
||||||
},
|
},
|
||||||
|
|
||||||
.marikoCpuDvfsTable = {
|
.marikoCpuDvfsTable = {
|
||||||
@@ -460,7 +466,7 @@ volatile CustomizeTable C = {
|
|||||||
{ 921600, { }, { 970060,-10108, -614,-179, 1508, -13 } },
|
{ 921600, { }, { 970060,-10108, -614,-179, 1508, -13 } },
|
||||||
{ 998400, { }, { 1065665,-16075, -497,-179, 3213, 9 } },
|
{ 998400, { }, { 1065665,-16075, -497,-179, 3213, 9 } },
|
||||||
{ 1075200, { }, { 1132576,-16093, -648, 0, 1077, 40 } },
|
{ 1075200, { }, { 1132576,-16093, -648, 0, 1077, 40 } },
|
||||||
{ 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
// { 1152000, { }, { 1180029,-14534, -830, 0, 1469, 110 } },
|
||||||
// { 1228800, { }, { 1248293,-16383, -859, 0, 3722, 313 } },
|
// { 1228800, { }, { 1248293,-16383, -859, 0, 3722, 313 } },
|
||||||
// { 1267200, { }, { 1286399,-17475, -867, 0, 3681, 559 } },
|
// { 1267200, { }, { 1286399,-17475, -867, 0, 3681, 559 } },
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ typedef struct CustomizeTable {
|
|||||||
|
|
||||||
u32 commonEmcMemVolt;
|
u32 commonEmcMemVolt;
|
||||||
u32 eristaEmcMaxClock;
|
u32 eristaEmcMaxClock;
|
||||||
|
u32 eristaEmcMaxClock1;
|
||||||
|
u32 eristaEmcMaxClock2;
|
||||||
u32 marikoEmcMaxClock;
|
u32 marikoEmcMaxClock;
|
||||||
u32 marikoEmcVddqVolt;
|
u32 marikoEmcVddqVolt;
|
||||||
u32 emcDvbShift;
|
u32 emcDvbShift;
|
||||||
@@ -121,12 +123,16 @@ typedef struct CustomizeTable {
|
|||||||
|
|
||||||
u32 commonGpuVoltOffset;
|
u32 commonGpuVoltOffset;
|
||||||
|
|
||||||
/* TODO: Automatically detect speedo. */
|
|
||||||
u32 gpuSpeedo;
|
u32 gpuSpeedo;
|
||||||
|
|
||||||
u32 eristaGpuVoltArray[27];
|
u32 eristaGpuVoltArray[27];
|
||||||
u32 marikoGpuVoltArray[24];
|
u32 marikoGpuVoltArray[24];
|
||||||
u32 reserved[64];
|
|
||||||
|
u32 fineTune_t6_tRTW;
|
||||||
|
u32 fineTune_t7_tWTR;
|
||||||
|
|
||||||
|
u32 reserved[60];
|
||||||
|
|
||||||
CustomizeCpuDvfsTable eristaCpuDvfsTable;
|
CustomizeCpuDvfsTable eristaCpuDvfsTable;
|
||||||
CustomizeCpuDvfsTable eristaCpuDvfsTableSLT;
|
CustomizeCpuDvfsTable eristaCpuDvfsTableSLT;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Lightos_
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../oc_common.hpp"
|
||||||
|
#include "../mtc_timing_value.hpp"
|
||||||
|
|
||||||
|
namespace ams::ldr::hoc::pcv::erista {
|
||||||
|
|
||||||
|
void CalculateTimings(double tCK_avg) {
|
||||||
|
tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW;
|
||||||
|
tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
|
||||||
|
tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
|
||||||
|
|
||||||
|
pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
|
||||||
|
tCLKSTOP = FLOOR(MIN(8.488 / tCK_avg, 23.0)) + 8.0;
|
||||||
|
|
||||||
|
const double tMMRI = tRCD + (tCK_avg * 3);
|
||||||
|
pdex2mrr = tMMRI + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Lightos_
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace ams::ldr::hoc::pcv::erista {
|
||||||
|
|
||||||
|
void CalculateTimings(double tCK_avg);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
u32 wlIndex = 0;
|
u32 wlIndex = 0;
|
||||||
|
|
||||||
for (u32 i = 0; i < std::size(rlMapDBI); ++i) {
|
for (u32 i = 0; i < std::size(rlMapDBI); ++i) {
|
||||||
if (rlMapDBI[i] == RL_DBI) {
|
if (rlMapDBI[i] == RL) {
|
||||||
rlIndex = i;
|
rlIndex = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,3 +21,4 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
void CalculateTimings();
|
void CalculateTimings();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,25 +30,13 @@ namespace ams::ldr::hoc {
|
|||||||
#define PACK_U32(high, low) ((static_cast<u32>(high) << 16) | (static_cast<u32>(low) & 0xFFFF))
|
#define PACK_U32(high, low) ((static_cast<u32>(high) << 16) | (static_cast<u32>(low) & 0xFFFF))
|
||||||
#define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast<u32>(high & 0xF) << 28) | (static_cast<u32>(low) & 0xFF))
|
#define PACK_U32_NIBBLE_HIGH_BYTE_LOW(high, low) ((static_cast<u32>(high & 0xF) << 28) | (static_cast<u32>(low) & 0xFF))
|
||||||
|
|
||||||
/* Primary timings. */
|
|
||||||
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
|
||||||
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
|
||||||
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
|
||||||
const std::array<double, 7> tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
|
|
||||||
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
|
||||||
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
|
||||||
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
|
||||||
|
|
||||||
/* Burst latency, not to be confused with base latency (tWRL). */
|
/* Burst latency, not to be confused with base latency (tWRL). */
|
||||||
const u32 BL = 16;
|
const u32 BL = 16;
|
||||||
|
|
||||||
/* Base latency for read and write (tWRL). */
|
/* Base latency for read and write (tWRL). */
|
||||||
const u32 RL = C.mem_burst_read_latency - 4; /* (This is a lazy fix for now) */
|
const u32 RL = C.mem_burst_read_latency;
|
||||||
const u32 WL = C.mem_burst_write_latency;
|
const u32 WL = C.mem_burst_write_latency;
|
||||||
|
|
||||||
/* Switch uses RL_DBI, todo: get rid of non DBI_RL. */
|
|
||||||
const u32 RL_DBI = RL + 4;
|
|
||||||
|
|
||||||
/* Precharge to Precharge Delay. (tCK) */
|
/* Precharge to Precharge Delay. (tCK) */
|
||||||
const u32 tPPD = 4;
|
const u32 tPPD = 4;
|
||||||
|
|
||||||
@@ -75,56 +63,14 @@ namespace ams::ldr::hoc {
|
|||||||
/* Write recovery time. */
|
/* Write recovery time. */
|
||||||
const u32 tWR = 18;
|
const u32 tWR = 18;
|
||||||
|
|
||||||
/* TOOD: Fix erista */
|
|
||||||
namespace pcv::erista {
|
namespace pcv::erista {
|
||||||
const double tCK_avg = 1000'000.0 / C.eristaEmcMaxClock;
|
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||||
|
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
const std::array<double, 8> tRRD_values = { 10.0, 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 };
|
||||||
const u32 tRAS = tRAS_values[C.t3_tRAS];
|
const std::array<u32, 6> tRFC_values = { 90, 80, 70, 60, 50, 40 };
|
||||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
|
||||||
|
|
||||||
const u32 tRC = tRAS + tRPpb;
|
|
||||||
const u32 tRFCab = tRFCpb * 2;
|
|
||||||
const double tXSR = (double) (tRFCab + 7.5);
|
|
||||||
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
|
||||||
const double tRPab = tRPpb + 3;
|
|
||||||
|
|
||||||
const u32 tR2P = 12;
|
|
||||||
|
|
||||||
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
|
||||||
const u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (C.eristaEmcMaxClock / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
|
|
||||||
|
|
||||||
const u32 wdv = WL;
|
|
||||||
const u32 wsv = WL - 2;
|
|
||||||
const u32 wev = 0xA + (WL - 14);
|
|
||||||
|
|
||||||
const double freq_mhz = C.eristaEmcMaxClock / 1000.0;
|
|
||||||
|
|
||||||
const u32 quse_width = CEIL(((3.7165006256863955 - freq_mhz) + (-0.002446584377651142 * freq_mhz)) - FLOOR(freq_mhz / -0.9952024303111688));
|
|
||||||
const u32 quse = CEIL(MIN(RL_DBI + (2.991255208275918 - (quse_width + (-0.00511180626826906 * freq_mhz))), freq_mhz * 0.021333773138874437));
|
|
||||||
const u32 ibdly = 0x10000000 + FLOOR(MAX(RL_DBI - 1.9999956603408224, quse - 5.9999987787411175) + (-0.0011929079761504341 * freq_mhz));
|
|
||||||
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
|
|
||||||
const u32 obdlyLow = WL - MIN(static_cast<double>(WL), 12 - (CEIL(-0.0003991 * freq_mhz) * 2));
|
|
||||||
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
|
|
||||||
const u32 tCKE = CEIL(1.0795 * CEIL(0.0074472 * (C.eristaEmcMaxClock / 1000.0)));
|
|
||||||
|
|
||||||
const double tMMRI = tRCD + (tCK_avg * 3);
|
|
||||||
const double pdex2mrr = tMMRI + 10;
|
|
||||||
const u32 tWTPDEN = tW2P + 1 + CEIL(tDQSS_max / tCK_avg) + CEIL(tDQS2DQ_max / tCK_avg) + 6;
|
|
||||||
const u32 tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (C.t6_tRTW * 3);
|
|
||||||
|
|
||||||
const double pdex_local = (0.011 * freq_mhz) - 1.443;
|
|
||||||
const u32 pdex2rw = static_cast<u32>(ROUND(pdex_local)) < 22 ? 22 : (static_cast<u32>(ROUND(pdex_local)) > 33 ? 33 : static_cast<u32>(ROUND(pdex_local)));
|
|
||||||
|
|
||||||
const double cke2pden = (static_cast<double>((C.eristaEmcMaxClock / 1000.0) * 0.00875) - 0.65);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace pcv::mariko {
|
|
||||||
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock;
|
|
||||||
const double ramFreqMhz = C.marikoEmcMaxClock / 1000.0;
|
|
||||||
|
|
||||||
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||||
const u32 tRPpb = tRP_values[C.t2_tRP];
|
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||||
@@ -132,6 +78,8 @@ namespace ams::ldr::hoc {
|
|||||||
const double tRRD = tRRD_values[C.t4_tRRD];
|
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||||
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||||
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||||
|
const s32 finetRTW = C.fineTune_t6_tRTW;
|
||||||
|
const s32 finetWTR = C.fineTune_t7_tWTR;
|
||||||
|
|
||||||
const u32 tRC = tRAS + tRPpb;
|
const u32 tRC = tRAS + tRPpb;
|
||||||
const u32 tRFCab = tRFCpb * 2;
|
const u32 tRFCab = tRFCpb * 2;
|
||||||
@@ -139,16 +87,57 @@ namespace ams::ldr::hoc {
|
|||||||
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||||
const double tRPab = tRPpb + 3;
|
const double tRPab = tRPpb + 3;
|
||||||
|
|
||||||
const u32 tR2P = CEIL((RL_DBI * 0.426) - 2.0);
|
const u32 tR2P = CEIL((RL * 0.426) - 2.0);
|
||||||
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL_DBI - (C.t6_tRTW * 3);
|
inline u32 tR2W;
|
||||||
const u32 tRTM = FLOOR((10.0 + RL_DBI) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
|
|
||||||
const u32 tRATM = CEIL((tRTM - 10.0) + (RL_DBI * 0.426));
|
|
||||||
inline u32 rext;
|
inline u32 rext;
|
||||||
|
|
||||||
const u32 rdv = RL_DBI + FLOOR((5.105 / tCK_avg) + 17.017);
|
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||||
|
inline u32 tWTPDEN;
|
||||||
|
inline u32 tW2R;
|
||||||
|
|
||||||
|
inline u32 pdex2rw;
|
||||||
|
|
||||||
|
inline u32 tCLKSTOP;
|
||||||
|
|
||||||
|
inline double pdex2mrr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace pcv::mariko {
|
||||||
|
const std::array<u32, 8> tRCD_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||||
|
const std::array<u32, 8> tRP_values = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
||||||
|
const std::array<u32, 10> tRAS_values = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
||||||
|
const std::array<double, 7> tRRD_values = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? 8gb uses 7.5 tRRD on >=1331. */
|
||||||
|
const std::array<u32, 11> tRFC_values = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
||||||
|
const std::array<u32, 10> tWTR_values = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||||
|
const std::array<u32, 6> tREFpb_values = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
||||||
|
|
||||||
|
const double tCK_avg = 1000'000.0 / C.marikoEmcMaxClock;
|
||||||
|
|
||||||
|
const u32 tRCD = tRCD_values[C.t1_tRCD];
|
||||||
|
const u32 tRPpb = tRP_values[C.t2_tRP];
|
||||||
|
const u32 tRAS = tRAS_values[C.t3_tRAS];
|
||||||
|
const double tRRD = tRRD_values[C.t4_tRRD];
|
||||||
|
const u32 tRFCpb = tRFC_values[C.t5_tRFC];
|
||||||
|
const u32 tWTR = 10 - tWTR_values[C.t7_tWTR];
|
||||||
|
const s32 finetRTW = C.fineTune_t6_tRTW;
|
||||||
|
const s32 finetWTR = C.fineTune_t7_tWTR;
|
||||||
|
|
||||||
|
const u32 tRC = tRAS + tRPpb;
|
||||||
|
const u32 tRFCab = tRFCpb * 2;
|
||||||
|
const double tXSR = static_cast<double>(tRFCab + 7.5);
|
||||||
|
const u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
||||||
|
const double tRPab = tRPpb + 3;
|
||||||
|
|
||||||
|
const u32 tR2P = CEIL((RL * 0.426) - 2.0);
|
||||||
|
const u32 tR2W = FLOOR(FLOOR((5.0 / tCK_avg) + ((FLOOR(48.0 / WL) - 0.478) * 3.0)) / 1.501) + RL - (C.t6_tRTW * 3) + finetRTW;
|
||||||
|
const u32 tRTM = FLOOR((10.0 + RL) + (3.502 / tCK_avg)) + FLOOR(7.489 / tCK_avg);
|
||||||
|
const u32 tRATM = CEIL((tRTM - 10.0) + (RL * 0.426));
|
||||||
|
inline u32 rext;
|
||||||
|
|
||||||
|
const u32 rdv = RL + FLOOR((5.105 / tCK_avg) + 17.017);
|
||||||
const u32 qpop = rdv - 14;
|
const u32 qpop = rdv - 14;
|
||||||
const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
|
const u32 quse_width = CEIL(((4.897 / tCK_avg) - FLOOR(2.538 / tCK_avg)) + 3.782);
|
||||||
const u32 quse = FLOOR(RL_DBI + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
|
const u32 quse = FLOOR(RL + ((5.082 / tCK_avg) + FLOOR(2.560 / tCK_avg))) - CEIL(4.820 / tCK_avg);
|
||||||
const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
|
const u32 einput_duration = FLOOR(9.936 / tCK_avg) + 5.0 + quse_width;
|
||||||
const u32 einput = quse - CEIL(9.928 / tCK_avg);
|
const u32 einput = quse - CEIL(9.928 / tCK_avg);
|
||||||
const u32 qrst_duration = FLOOR(8.399 - tCK_avg);
|
const u32 qrst_duration = FLOOR(8.399 - tCK_avg);
|
||||||
@@ -157,8 +146,8 @@ namespace ams::ldr::hoc {
|
|||||||
const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
|
const u32 ibdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(1, quse - qrst_duration - 2.0);
|
||||||
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
|
const u32 qsafe = (einput_duration + 3) + MAX(MIN(qrstLow * rdv, qrst_duration + qrst_duration), einput);
|
||||||
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
const u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
||||||
const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL_DBI + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
|
const u32 tWTPDEN = CEIL(((1.803 / tCK_avg) + MAX(RL + (2.694 / tCK_avg), static_cast<double>(tW2P))) + (BL / 2));
|
||||||
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL_DBI)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg);
|
const u32 tW2R = FLOOR(MAX((5.020 / tCK_avg) + 1.130, WL - MAX(-CEIL(0.258 * (WL - RL)), 1.964)) * 1.964) + WL - CEIL(tWTR / tCK_avg) + finetWTR;
|
||||||
const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
|
const u32 tWTM = CEIL(WL + ((7.570 / tCK_avg) + 8.753));
|
||||||
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
|
const u32 tWATM = (tWTM + (FLOOR(WL / 0.816) * 2.0)) - 4.0;
|
||||||
|
|
||||||
@@ -168,7 +157,6 @@ namespace ams::ldr::hoc {
|
|||||||
|
|
||||||
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
|
const u32 obdlyHigh = 3 / FLOOR(MIN(static_cast<double>(2), tCK_avg * (WL - 7)));
|
||||||
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
|
const u32 obdlyLow = MAX(WL - FLOOR((126.0 / CEIL(tCK_avg + 8.601))), 0.0);
|
||||||
|
|
||||||
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
|
const u32 obdly = PACK_U32_NIBBLE_HIGH_BYTE_LOW(obdlyHigh, obdlyLow);
|
||||||
|
|
||||||
const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
|
const u32 pdex2rw = CEIL((CEIL(12.335 - tCK_avg) + (7.430 / tCK_avg) - CEIL(tCK_avg * 11.361)));
|
||||||
@@ -183,3 +171,4 @@ namespace ams::ldr::hoc {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -99,4 +99,25 @@ namespace ams::ldr::hoc {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace panic {
|
||||||
|
/* Requires modifying g_ams_handlers in secmon_smc_handler.cpp */
|
||||||
|
constexpr inline void SmcError(u32 rgb) {
|
||||||
|
SecmonArgs args = {};
|
||||||
|
constexpr u32 SmcShowErrorID = 0xF0000005;
|
||||||
|
args.X[0] = SmcShowErrorID;
|
||||||
|
args.X[1] = rgb;
|
||||||
|
svcCallSecureMonitor(&args);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr inline u32 PackCode(u32 r, u32 g, u32 b) {
|
||||||
|
return ((r & 0xF) << 8) | ((g & 0xF) << 4) | ((b & 0xF) << 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr u32 Gpu = PackCode(0xF, 0x7, 0x0);
|
||||||
|
constexpr u32 Cpu = PackCode(0xF, 0x0, 0x0);
|
||||||
|
constexpr u32 Emc = PackCode(0x0, 0xF, 0xF);
|
||||||
|
constexpr u32 Patch = PackCode(0x8, 0x0, 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,152 +22,163 @@
|
|||||||
|
|
||||||
namespace ams::ldr::hoc::pcv {
|
namespace ams::ldr::hoc::pcv {
|
||||||
|
|
||||||
Result MemFreqPllmLimit(u32* ptr) {
|
Result MemFreqPllmLimit(u32* ptr) {
|
||||||
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
clk_pll_param* entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||||
R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry());
|
R_UNLESS(entry->freq == entry->vco_max, ldr::ResultInvalidMemPllmEntry());
|
||||||
|
|
||||||
// Double the max clk simply
|
// Double the max clk simply
|
||||||
u32 max_clk = entry->freq * 2;
|
u32 max_clk = entry->freq * 2;
|
||||||
entry->freq = max_clk;
|
entry->freq = max_clk;
|
||||||
entry->vco_max = max_clk;
|
entry->vco_max = max_clk;
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MemVoltHandler(u32* ptr) {
|
|
||||||
// ptr value might be default_uv or max_uv
|
|
||||||
regulator* entries[2] = {
|
|
||||||
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.default_uv)),
|
|
||||||
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.max_uv)),
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr u32 uv_step = 12'500;
|
|
||||||
constexpr u32 uv_min = 600'000;
|
|
||||||
|
|
||||||
auto validator = [](regulator* entry) {
|
|
||||||
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
|
|
||||||
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
|
|
||||||
R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry());
|
|
||||||
R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
|
|
||||||
R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry());
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
};
|
|
||||||
|
|
||||||
regulator* entry = nullptr;
|
|
||||||
for (auto& i : entries) {
|
|
||||||
if (R_SUCCEEDED(validator(i)))
|
|
||||||
entry = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
R_UNLESS(entry, ldr::ResultInvalidRegulatorEntry());
|
Result MemVoltHandler(u32* ptr) {
|
||||||
|
// ptr value might be default_uv or max_uv
|
||||||
|
regulator* entries[2] = {
|
||||||
|
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.default_uv)),
|
||||||
|
reinterpret_cast<regulator *>(reinterpret_cast<u8 *>(ptr) - offsetof(regulator, type_1.max_uv)),
|
||||||
|
};
|
||||||
|
|
||||||
u32 emc_uv = C.commonEmcMemVolt;
|
constexpr u32 uv_step = 12'500;
|
||||||
if (!emc_uv)
|
constexpr u32 uv_min = 600'000;
|
||||||
R_SKIP();
|
|
||||||
|
|
||||||
if (emc_uv % uv_step)
|
|
||||||
emc_uv = emc_uv / uv_step * uv_step; // rounding
|
|
||||||
|
|
||||||
PATCH_OFFSET(ptr, emc_uv);
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SafetyCheck() {
|
|
||||||
// if (C.custRev != CUST_REV)
|
|
||||||
// CRASH("Triggered");
|
|
||||||
|
|
||||||
struct sValidator {
|
|
||||||
volatile u32 value;
|
|
||||||
u32 min;
|
|
||||||
u32 max;
|
|
||||||
bool value_required = false;
|
|
||||||
|
|
||||||
Result check() {
|
|
||||||
if (!value_required && !value)
|
|
||||||
R_SUCCEED();
|
|
||||||
|
|
||||||
if (min && value < min)
|
|
||||||
R_THROW(ldr::ResultSafetyCheckFailure());
|
|
||||||
if (max && value > max)
|
|
||||||
R_THROW(ldr::ResultSafetyCheckFailure());
|
|
||||||
|
|
||||||
|
auto validator = [](regulator* entry) {
|
||||||
|
R_UNLESS(entry->id == 1, ldr::ResultInvalidRegulatorEntry());
|
||||||
|
R_UNLESS(entry->type == 1, ldr::ResultInvalidRegulatorEntry());
|
||||||
|
R_UNLESS(entry->type_1.volt_reg == 0x17, ldr::ResultInvalidRegulatorEntry());
|
||||||
|
R_UNLESS(entry->type_1.step_uv == uv_step, ldr::ResultInvalidRegulatorEntry());
|
||||||
|
R_UNLESS(entry->type_1.min_uv == uv_min, ldr::ResultInvalidRegulatorEntry());
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
};
|
||||||
|
|
||||||
|
regulator* entry = nullptr;
|
||||||
|
for (auto& i : entries) {
|
||||||
|
if (R_SUCCEEDED(validator(i))) {
|
||||||
|
entry = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
|
R_UNLESS(entry, ldr::ResultInvalidRegulatorEntry());
|
||||||
u32 marikoCpuDvfsMaxFreq;
|
|
||||||
if (C.marikoCpuUVHigh) {
|
u32 emc_uv = C.commonEmcMemVolt;
|
||||||
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
if (!emc_uv) {
|
||||||
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
|
R_SKIP();
|
||||||
);
|
|
||||||
} else {
|
|
||||||
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
|
||||||
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
u32 eristaGpuDvfsMaxFreq;
|
|
||||||
switch (C.eristaGpuUV)
|
if (emc_uv % uv_step) {
|
||||||
{
|
emc_uv = emc_uv / uv_step * uv_step; // rounding
|
||||||
case 0:
|
}
|
||||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
|
||||||
break;
|
PATCH_OFFSET(ptr, emc_uv);
|
||||||
case 1:
|
|
||||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
|
R_SUCCEED();
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 marikoGpuDvfsMaxFreq;
|
void SafetyCheck() {
|
||||||
switch (C.marikoGpuUV) {
|
// if (C.custRev != CUST_REV)
|
||||||
|
// CRASH("Triggered");
|
||||||
|
|
||||||
|
struct sValidator {
|
||||||
|
volatile u32 value;
|
||||||
|
u32 min;
|
||||||
|
u32 max;
|
||||||
|
bool value_required = false;
|
||||||
|
u32 panic;
|
||||||
|
|
||||||
|
Result check() {
|
||||||
|
if (!value_required && !value)
|
||||||
|
R_SUCCEED();
|
||||||
|
|
||||||
|
if (min && value < min)
|
||||||
|
R_THROW(ldr::ResultSafetyCheckFailure());
|
||||||
|
if (max && value > max)
|
||||||
|
R_THROW(ldr::ResultSafetyCheckFailure());
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
u32 eristaCpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaCpuDvfsTable)->freq);
|
||||||
|
u32 marikoCpuDvfsMaxFreq;
|
||||||
|
if (C.marikoCpuUVHigh) {
|
||||||
|
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
||||||
|
GetDvfsTableLastEntry(C.marikoCpuDvfsTableSLT)->freq
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
marikoCpuDvfsMaxFreq = static_cast<u32>(
|
||||||
|
GetDvfsTableLastEntry(C.marikoCpuDvfsTable)->freq
|
||||||
|
);
|
||||||
|
}
|
||||||
|
u32 eristaGpuDvfsMaxFreq;
|
||||||
|
switch (C.eristaGpuUV) {
|
||||||
case 0:
|
case 0:
|
||||||
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq);
|
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTableSLT)->freq);
|
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableSLT)->freq);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq);
|
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTableHiOPT)->freq);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq);
|
eristaGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.eristaGpuDvfsTable)->freq);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 marikoGpuDvfsMaxFreq;
|
||||||
|
switch (C.marikoGpuUV) {
|
||||||
|
case 0:
|
||||||
|
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTableSLT)->freq);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTableHiOPT)->freq);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
marikoGpuDvfsMaxFreq = static_cast<u32>(GetDvfsTableLastEntry(C.marikoGpuDvfsTable)->freq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace ams::ldr::hoc::pcv;
|
||||||
|
sValidator validators[] = {
|
||||||
|
{ C.eristaCpuBoostClock, 1020'000, 2295'000, true, panic::Cpu },
|
||||||
|
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true, panic::Cpu },
|
||||||
|
{ C.eristaCpuMaxVolt, 1000, 1260, false, panic::Cpu },
|
||||||
|
{ C.marikoCpuMaxVolt, 1000, 1200, false, panic::Cpu },
|
||||||
|
{ eristaCpuDvfsMaxFreq, 1785'000, 2295'000, false, panic::Cpu },
|
||||||
|
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000, false, panic::Cpu },
|
||||||
|
{ C.commonEmcMemVolt, 912'500, 1350'000, false, panic::Emc }, // Official burst vmax for the RAMs is 1500mV
|
||||||
|
{ GET_MAX_OF_ARR(erista::maxEmcClocks), 1600'000, 2600'000, false, panic::Emc },
|
||||||
|
{ C.marikoEmcMaxClock, 1600'000, 3500'000, false, panic::Emc },
|
||||||
|
{ C.marikoEmcVddqVolt, 250'000, 700'000, false, panic::Emc },
|
||||||
|
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000, false, panic::Gpu },
|
||||||
|
{ marikoGpuDvfsMaxFreq, 768'000, 1570'000, false, panic::Gpu },
|
||||||
|
{ C.marikoGpuVmax, 800, 960, false, panic::Gpu },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto &v : validators) {
|
||||||
|
if (R_FAILED(v.check())) {
|
||||||
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
||||||
|
panic::SmcError(v.panic);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
CRASH("Validation FAIL");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sValidator validators[] = {
|
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||||
{ C.eristaCpuBoostClock, 1020'000, 2295'000, true },
|
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||||
{ C.marikoCpuBoostClock, 1020'000, 2703'000, true },
|
SafetyCheck();
|
||||||
{ C.commonEmcMemVolt, 912'500, 1350'000 }, // Official burst vmax for the RAMs is 1500mV
|
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
||||||
{ C.eristaCpuMaxVolt, 1000, 1257 },
|
if (isMariko)
|
||||||
{ C.eristaEmcMaxClock, 1600'000, 2600'000 },
|
mariko::Patch(mapped_nso, nso_size);
|
||||||
{ C.marikoCpuMaxVolt, 1000, 1235 },
|
else
|
||||||
{ C.marikoEmcMaxClock, 1600'000, 3500'000 },
|
erista::Patch(mapped_nso, nso_size);
|
||||||
{ C.marikoEmcVddqVolt, 250'000, 700'000 },
|
#endif
|
||||||
{ eristaCpuDvfsMaxFreq, 1785'000, 2295'000 },
|
|
||||||
{ marikoCpuDvfsMaxFreq, 1785'000, 2703'000 },
|
|
||||||
{ eristaGpuDvfsMaxFreq, 768'000, 1152'000 },
|
|
||||||
{ marikoGpuDvfsMaxFreq, 768'000, 1536'000 },
|
|
||||||
};
|
|
||||||
|
|
||||||
for (auto& i : validators) {
|
|
||||||
if (R_FAILED(i.check()))
|
|
||||||
CRASH("Validation FAIL");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
|
||||||
SafetyCheck();
|
|
||||||
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
|
||||||
if (isMariko)
|
|
||||||
mariko::Patch(mapped_nso, nso_size);
|
|
||||||
else
|
|
||||||
erista::Patch(mapped_nso, nso_size);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -122,16 +122,6 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
{0xFFFFFFFF, 35},
|
{0xFFFFFFFF, 35},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 ramBrackets[][22] = {
|
|
||||||
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
|
||||||
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
|
||||||
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
|
||||||
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u32 gpuBudgetDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
|
||||||
|
|
||||||
|
|
||||||
/* GPU Max Clock asm Pattern:
|
/* GPU Max Clock asm Pattern:
|
||||||
*
|
*
|
||||||
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
||||||
@@ -188,6 +178,9 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace erista {
|
namespace erista {
|
||||||
|
static u32 maxEmcClocks[] = { C.eristaEmcMaxClock2, C.eristaEmcMaxClock1, C.eristaEmcMaxClock, };
|
||||||
|
#define GET_MAX_OF_ARR(ARR) (*std::max_element(ARR, ARR + std::size(ARR)))
|
||||||
|
|
||||||
constexpr cvb_entry_t CpuCvbTableDefault[] = {
|
constexpr cvb_entry_t CpuCvbTableDefault[] = {
|
||||||
// CPU_PLL_CVB_TABLE_ODN
|
// CPU_PLL_CVB_TABLE_ODN
|
||||||
{ 204000, {721094}, { } },
|
{ 204000, {721094}, { } },
|
||||||
@@ -209,30 +202,34 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr u32 CpuVoltOfficial = 1227;
|
||||||
constexpr u32 CpuVoltOfficial = 1235;
|
|
||||||
|
|
||||||
constexpr u32 CpuVminOfficial = 825;
|
constexpr u32 CpuVminOfficial = 825;
|
||||||
|
|
||||||
constexpr u32 CpuVoltL4T = 1235'000;
|
constexpr u32 CpuVoltL4T = 1257'000;
|
||||||
|
|
||||||
static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 };
|
static const u32 cpuVoltDvfsPattern[] = { 1227, 1000, 100, 1000, 0 };
|
||||||
static const u32 cpuVoltDvfsOffsets[] = { 5, 6, 7, 8, 9 };
|
static_assert(sizeof(cpuVoltDvfsPattern) == 0x14, "invalid cpuVoltDvfsPattern size");
|
||||||
static_assert(sizeof(cpuVoltDvfsPattern) == sizeof(cpuVoltDvfsOffsets), "Invalid cpuVoltDvfsPattern");
|
|
||||||
|
|
||||||
static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 };
|
static const u32 cpuVoltageThermalPattern[] = { 950, 1132, 0, 950, 1227, 0, 825, 1227, 15000, 825, 1170, 60000, 825, 1132, 80000 };
|
||||||
static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "invalid cpuVoltageThermalPattern size");
|
static_assert(sizeof(cpuVoltageThermalPattern) == 0x3c, "invalid cpuVoltageThermalPattern size");
|
||||||
|
constexpr u32 GpuClkPllLimit = 2'600'000;
|
||||||
constexpr u32 GpuClkPllLimit = 921'600'000;
|
constexpr u32 GpuClkPllMax = 921'600'000;
|
||||||
constexpr u32 GpuVminOfficial = 810;
|
constexpr u32 GpuVminOfficial = 810;
|
||||||
|
|
||||||
|
constexpr u16 CpuMinVolts[] = { 950, 850, 825, 810 };
|
||||||
|
|
||||||
|
inline bool CpuMaxVoltPatternFn(u32* ptr32) {
|
||||||
|
u32 val = *ptr32;
|
||||||
|
return (val == 1132 || val == 1170 || val == 1227);
|
||||||
|
}
|
||||||
|
|
||||||
static const u32 gpuVoltDvfsPattern[] = { 810, 1150, 1000, 100, 1000, 10, };
|
static const u32 gpuVoltDvfsPattern[] = { 810, 1150, 1000, 100, 1000, 10, };
|
||||||
static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern");
|
static_assert(sizeof(gpuVoltDvfsPattern) == (sizeof(u32) * 6), "Invalid gpuVoltDvfsPattern");
|
||||||
|
|
||||||
static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 };
|
static const u32 gpuVoltThermalPattern[] = { 950, 1132, 0, 810, 1132, 15000, 810, 1132, 30000, 810, 1132, 50000, 810, 1132, 70000, 810, 1132, 105000 };
|
||||||
static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "invalid gpuVoltageThermalPattern size");
|
static_assert(sizeof(gpuVoltThermalPattern) == 0x48, "invalid gpuVoltageThermalPattern size");
|
||||||
|
|
||||||
|
|
||||||
/* GPU Max Clock asm Pattern:
|
/* GPU Max Clock asm Pattern:
|
||||||
*
|
*
|
||||||
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
* MOV W11, #0x1000 MOV (wide immediate) 0x1000 0xB (11)
|
||||||
@@ -287,6 +284,7 @@ namespace ams::ldr::hoc::pcv {
|
|||||||
};
|
};
|
||||||
|
|
||||||
constexpr u32 MemVoltHOS = 1125'000;
|
constexpr u32 MemVoltHOS = 1125'000;
|
||||||
|
constexpr u32 EmcClkMinFreq = 40800; /* 40.8 MHz table only exists on erista. */
|
||||||
constexpr u32 EmcClkPllmLimit = 1866'000'000;
|
constexpr u32 EmcClkPllmLimit = 1866'000'000;
|
||||||
|
|
||||||
constexpr u32 MTC_TABLE_REV = 7;
|
constexpr u32 MTC_TABLE_REV = 7;
|
||||||
|
|||||||
@@ -16,153 +16,154 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace ams::ldr::hoc::pcv {
|
namespace ams::ldr::hoc::pcv {
|
||||||
|
|
||||||
typedef struct cvb_coefficients {
|
typedef struct cvb_coefficients {
|
||||||
s32 c0 = 0;
|
s32 c0 = 0;
|
||||||
s32 c1 = 0;
|
s32 c1 = 0;
|
||||||
s32 c2 = 0;
|
s32 c2 = 0;
|
||||||
s32 c3 = 0;
|
s32 c3 = 0;
|
||||||
s32 c4 = 0;
|
s32 c4 = 0;
|
||||||
s32 c5 = 0;
|
s32 c5 = 0;
|
||||||
} cvb_coefficients;
|
} cvb_coefficients;
|
||||||
|
|
||||||
typedef struct cvb_entry_t {
|
typedef struct cvb_entry_t {
|
||||||
u64 freq;
|
u64 freq;
|
||||||
cvb_coefficients cvb_dfll_param;
|
cvb_coefficients cvb_dfll_param;
|
||||||
cvb_coefficients cvb_pll_param;
|
cvb_coefficients cvb_pll_param;
|
||||||
} cvb_entry_t;
|
} cvb_entry_t;
|
||||||
static_assert(sizeof(cvb_entry_t) == 0x38);
|
static_assert(sizeof(cvb_entry_t) == 0x38);
|
||||||
|
|
||||||
typedef struct cvb_cpu_dfll_data {
|
typedef struct cvb_cpu_dfll_data {
|
||||||
u32 tune0_low;
|
u32 tune0_low;
|
||||||
u32 tune0_high;
|
u32 tune0_high;
|
||||||
u32 tune1_low;
|
u32 tune1_low;
|
||||||
u32 tune1_high;
|
u32 tune1_high;
|
||||||
unsigned int tune_high_min_millivolts;
|
unsigned int tune_high_min_millivolts;
|
||||||
unsigned int tune_high_margin_millivolts;
|
unsigned int tune_high_margin_millivolts;
|
||||||
unsigned long dvco_calibration_max;
|
unsigned long dvco_calibration_max;
|
||||||
} cvb_cpu_dfll_data;
|
} cvb_cpu_dfll_data;
|
||||||
|
|
||||||
typedef struct emc_dvb_dvfs_table_t {
|
typedef struct emc_dvb_dvfs_table_t {
|
||||||
u64 freq;
|
u64 freq;
|
||||||
s32 volt[4] = {0};
|
s32 volt[4] = {0};
|
||||||
} emc_dvb_dvfs_table_t;
|
} emc_dvb_dvfs_table_t;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) div_nmp {
|
typedef struct __attribute__((packed)) div_nmp {
|
||||||
u8 divn_shift;
|
u8 divn_shift;
|
||||||
u8 divn_width;
|
u8 divn_width;
|
||||||
u8 divm_shift;
|
u8 divm_shift;
|
||||||
u8 divm_width;
|
u8 divm_width;
|
||||||
u8 divp_shift;
|
u8 divp_shift;
|
||||||
u8 divp_width;
|
u8 divp_width;
|
||||||
u8 override_divn_shift;
|
u8 override_divn_shift;
|
||||||
u8 override_divm_shift;
|
u8 override_divm_shift;
|
||||||
u8 override_divp_shift;
|
u8 override_divp_shift;
|
||||||
} div_nmp;
|
} div_nmp;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) clk_pll_param {
|
typedef struct __attribute__((packed)) clk_pll_param {
|
||||||
u32 freq;
|
u32 freq;
|
||||||
u32 input_min;
|
u32 input_min;
|
||||||
u32 input_max;
|
u32 input_max;
|
||||||
u32 cf_min;
|
u32 cf_min;
|
||||||
u32 cf_max;
|
u32 cf_max;
|
||||||
u32 vco_min;
|
u32 vco_min;
|
||||||
u32 vco_max;
|
u32 vco_max;
|
||||||
s32 lock_delay;
|
s32 lock_delay;
|
||||||
u32 fixed_rate;
|
u32 fixed_rate;
|
||||||
u32 unk_0;
|
u32 unk_0;
|
||||||
struct div_nmp *div_nmp;
|
struct div_nmp *div_nmp;
|
||||||
u32 unk_1[4];
|
u32 unk_1[4];
|
||||||
void (*unk_fn)(u64* unk_struct); // set_defaults?
|
void (*unk_fn)(u64* unk_struct); // set_defaults?
|
||||||
} clk_pll_param;
|
} clk_pll_param;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) dvfs_rail {
|
typedef struct __attribute__((packed)) dvfs_rail {
|
||||||
u32 id;
|
u32 id;
|
||||||
u32 unk_0[5];
|
u32 unk_0[5];
|
||||||
u32 freq;
|
u32 freq;
|
||||||
u32 unk_1[8];
|
u32 unk_1[8];
|
||||||
u32 unk_flag;
|
u32 unk_flag;
|
||||||
u32 min_mv;
|
u32 min_mv;
|
||||||
u32 step_mv;
|
u32 step_mv;
|
||||||
u32 max_mv;
|
u32 max_mv;
|
||||||
u32 unk_2[11];
|
u32 unk_2[11];
|
||||||
} dvfs_rail;
|
} dvfs_rail;
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) regulator {
|
typedef struct __attribute__((packed)) regulator {
|
||||||
u64 id;
|
u64 id;
|
||||||
const char* name;
|
const char* name;
|
||||||
u32 type;
|
u32 type;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
u32 volt_reg;
|
u32 volt_reg;
|
||||||
u32 step_uv;
|
u32 step_uv;
|
||||||
u32 min_uv;
|
u32 min_uv;
|
||||||
u32 default_uv;
|
u32 default_uv;
|
||||||
u32 max_uv;
|
u32 max_uv;
|
||||||
u32 unk_0[2];
|
u32 unk_0[2];
|
||||||
} type_1;
|
} type_1;
|
||||||
struct {
|
struct {
|
||||||
u32 unk_0;
|
u32 unk_0;
|
||||||
u32 step_uv;
|
u32 step_uv;
|
||||||
u32 unk_1;
|
u32 unk_1;
|
||||||
u32 min_uv;
|
u32 min_uv;
|
||||||
u32 max_uv;
|
u32 max_uv;
|
||||||
u32 unk_2;
|
u32 unk_2;
|
||||||
u32 default_uv;
|
u32 default_uv;
|
||||||
} type_2_3;
|
} type_2_3;
|
||||||
};
|
};
|
||||||
u32 unk_x[60];
|
u32 unk_x[60];
|
||||||
} regulator;
|
} regulator;
|
||||||
static_assert(sizeof(regulator) == 0x120);
|
static_assert(sizeof(regulator) == 0x120);
|
||||||
|
|
||||||
constexpr u32 CpuClkOSLimit = 1785'000;
|
constexpr u32 CpuClkOSLimit = 1785'000;
|
||||||
|
|
||||||
constexpr u32 EmcClkOSLimit = 1600'000;
|
constexpr u32 EmcClkOSLimit = 1600'000;
|
||||||
|
|
||||||
#define R_SKIP() R_SUCCEED()
|
#define R_SKIP() R_SUCCEED()
|
||||||
|
|
||||||
// Count 32 / Index 31 is reserved to be empty
|
// Count 32 / Index 31 is reserved to be empty
|
||||||
constexpr size_t DvfsTableEntryCount = 32;
|
constexpr size_t DvfsTableEntryCount = 32;
|
||||||
constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1;
|
constexpr size_t DvfsTableEntryLimit = DvfsTableEntryCount - 1;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
size_t GetDvfsTableEntryCount(T* table_head) {
|
size_t GetDvfsTableEntryCount(T* table_head) {
|
||||||
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
||||||
|
|
||||||
auto is_empty = [](NT* entry) {
|
auto is_empty = [](NT* entry) {
|
||||||
uint8_t* m = reinterpret_cast<uint8_t *>(entry);
|
uint8_t* m = reinterpret_cast<uint8_t *>(entry);
|
||||||
for (size_t i = 0; i < sizeof(NT); i++) {
|
for (size_t i = 0; i < sizeof(NT); i++) {
|
||||||
if (*(m + i))
|
if (*(m + i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
}
|
||||||
};
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
NT* table = const_cast<NT *>(table_head);
|
NT* table = const_cast<NT *>(table_head);
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
while (count < DvfsTableEntryLimit) {
|
while (count < DvfsTableEntryLimit) {
|
||||||
if (is_empty(table++)) {
|
if (is_empty(table++)) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return DvfsTableEntryLimit;
|
return DvfsTableEntryLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T* GetDvfsTableLastEntry(T* table_head) {
|
T* GetDvfsTableLastEntry(T* table_head) {
|
||||||
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
using NT = std::remove_const_t<std::remove_volatile_t<T>>;
|
||||||
|
|
||||||
NT* table = const_cast<NT *>(table_head);
|
NT* table = const_cast<NT *>(table_head);
|
||||||
size_t count = GetDvfsTableEntryCount(table_head);
|
size_t count = GetDvfsTableEntryCount(table_head);
|
||||||
if (!count) {
|
if (!count) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
size_t index = count - 1;
|
size_t index = count - 1;
|
||||||
return table + index;
|
return table + index;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,27 +20,28 @@
|
|||||||
|
|
||||||
#include "pcv.hpp"
|
#include "pcv.hpp"
|
||||||
#include "../mtc_timing_value.hpp"
|
#include "../mtc_timing_value.hpp"
|
||||||
|
#include "../erista/calculate_timings_erista.hpp"
|
||||||
|
|
||||||
namespace ams::ldr::hoc::pcv::erista {
|
namespace ams::ldr::hoc::pcv::erista {
|
||||||
|
|
||||||
Result CpuVoltDvfs(u32 *ptr) {
|
Result CpuVoltDvfs(u32 *ptr) {
|
||||||
if (MatchesPattern(ptr, cpuVoltDvfsPattern, cpuVoltDvfsOffsets)) {
|
if (std::memcmp(ptr + 5, cpuVoltDvfsPattern, sizeof(cpuVoltDvfsPattern))) {
|
||||||
if (C.eristaCpuVmin) {
|
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
||||||
PATCH_OFFSET(ptr, C.eristaCpuVmin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.eristaCpuUV) {
|
|
||||||
PATCH_OFFSET(ptr - 2, C.eristaCpuVmin);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (C.eristaCpuMaxVolt) {
|
|
||||||
PATCH_OFFSET(ptr + 5, C.eristaCpuMaxVolt);
|
|
||||||
}
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
R_THROW(ldr::ResultInvalidCpuMinVolt());
|
if (C.eristaCpuVmin) {
|
||||||
|
PATCH_OFFSET(ptr, C.eristaCpuVmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C.eristaCpuUV) {
|
||||||
|
PATCH_OFFSET(ptr - 2, C.eristaCpuVmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C.eristaCpuMaxVolt) {
|
||||||
|
PATCH_OFFSET(ptr + 5, C.eristaCpuMaxVolt);
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CpuVoltThermals(u32 *ptr) {
|
Result CpuVoltThermals(u32 *ptr) {
|
||||||
@@ -51,7 +52,7 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
if (C.eristaCpuVmin) {
|
if (C.eristaCpuVmin) {
|
||||||
PATCH_OFFSET( ptr, C.eristaCpuVmin);
|
PATCH_OFFSET( ptr, C.eristaCpuVmin);
|
||||||
PATCH_OFFSET(ptr + 3, C.eristaCpuVmin);
|
PATCH_OFFSET(ptr + 3, C.eristaCpuVmin);
|
||||||
PATCH_OFFSET(ptr + 9, C.eristaCpuVmin);
|
PATCH_OFFSET(ptr + 6, C.eristaCpuVmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C.eristaCpuMaxVolt) {
|
if (C.eristaCpuMaxVolt) {
|
||||||
@@ -66,12 +67,12 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
|
|
||||||
Result CpuVoltDfll(u32* ptr) {
|
Result CpuVoltDfll(u32* ptr) {
|
||||||
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
|
cvb_cpu_dfll_data *entry = reinterpret_cast<cvb_cpu_dfll_data *>(ptr);
|
||||||
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
|
R_UNLESS(entry->tune0_low == 0xFFEAD0FF, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||||
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
R_UNLESS(entry->tune0_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||||
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
R_UNLESS(entry->tune1_low == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||||
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
R_UNLESS(entry->tune1_high == 0x0, ldr::ResultInvalidCpuVoltDfllEntry());
|
||||||
|
|
||||||
if( !C.eristaCpuUV) {
|
if (!C.eristaCpuUV) {
|
||||||
R_SKIP();
|
R_SKIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,20 +104,19 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result GpuVoltDVFS(u32 *ptr) {
|
Result GpuVoltDVFS(u32 *ptr) {
|
||||||
u32 result = std::memcmp(ptr, gpuVoltDvfsPattern, sizeof(gpuVoltDvfsPattern));
|
if (std::memcmp(ptr, gpuVoltDvfsPattern, sizeof(gpuVoltDvfsPattern))) {
|
||||||
|
|
||||||
if (result)
|
|
||||||
R_THROW(ldr::ResultInvalidGpuDvfs());
|
R_THROW(ldr::ResultInvalidGpuDvfs());
|
||||||
|
}
|
||||||
|
|
||||||
if (C.eristaGpuVmin)
|
if (C.eristaGpuVmin) {
|
||||||
PATCH_OFFSET(ptr, C.eristaGpuVmin);
|
PATCH_OFFSET(ptr, C.eristaGpuVmin);
|
||||||
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GpuVoltThermals(u32 *ptr) {
|
Result GpuVoltThermals(u32 *ptr) {
|
||||||
u32 result = std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern));
|
if (std::memcmp(ptr - 3, gpuVoltThermalPattern, sizeof(gpuVoltThermalPattern))) {
|
||||||
if (result) {
|
|
||||||
R_THROW(ldr::ResultInvalidGpuDvfs());
|
R_THROW(ldr::ResultInvalidGpuDvfs());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,339 +166,19 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GpuFreqPllLimit(u32 *ptr) {
|
/* Note: This does not have proper timings, so base latency adjustment will not work. */
|
||||||
clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
|
/* However, it may still achieve a slightly higher frequency, but not as much as it could be. */
|
||||||
|
/* I'm certainly not insane enough to attempt this pain again, so this will have to do *for now*. */
|
||||||
// All zero except for freq
|
|
||||||
for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++) {
|
|
||||||
R_UNLESS(*(ptr + i) == 0, ldr::ResultInvalidGpuPllEntry());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Double the max clk simply
|
|
||||||
u32 max_clk = entry->freq * 2;
|
|
||||||
entry->freq = max_clk;
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
// void MemMtcTableAutoAdjustBaseLatency(EristaMtcTable *table) {
|
|
||||||
// using namespace pcv::erista;
|
|
||||||
/* #define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \
|
|
||||||
TABLE->burst_regs.PARAM = VALUE; \
|
|
||||||
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
|
||||||
TABLE->shadow_regs_quse_train.PARAM = VALUE; \
|
|
||||||
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
|
||||||
*/
|
|
||||||
// #define GET_CYCLE(PARAM) ((u32)((double)(PARAM) / tCK_avg))
|
|
||||||
|
|
||||||
/* This condition is insane but it's done in eos. */
|
|
||||||
/* Need to clean up at some point. */
|
|
||||||
// u32 rext;
|
|
||||||
// u32 wext;
|
|
||||||
// if (C.eristaEmcMaxClock < 3200001) {
|
|
||||||
// if (C.eristaEmcMaxClock < 2133001) {
|
|
||||||
// rext = 26;
|
|
||||||
// wext = 22;
|
|
||||||
// } else {
|
|
||||||
// rext = 28;
|
|
||||||
// wext = 22;
|
|
||||||
//
|
|
||||||
// if (2400000 < C.eristaEmcMaxClock) {
|
|
||||||
// wext = 25;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// rext = 30;
|
|
||||||
// wext = 25;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// u32 refresh_raw = 0xFFFF;
|
|
||||||
// u32 trefbw = 0;
|
|
||||||
//
|
|
||||||
// if (C.t8_tREFI != 6) {
|
|
||||||
// refresh_raw = static_cast<u32>(std::floor(static_cast<double>(tREFpb_values[C.t8_tREFI]) / tCK_avg)) - 0x40;
|
|
||||||
// refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// trefbw = refresh_raw + 0x40;
|
|
||||||
// trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
|
||||||
//
|
|
||||||
// if (C.hpMode) {
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cfg, 0x13200000);
|
|
||||||
// } else {
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cfg, 0xF3200000);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rc, /*0x00000060*/ GET_CYCLE(tRC));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rfc, /*0x00000120*/ GET_CYCLE(tRFCab));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ras, /*0x00000044*/ GET_CYCLE(tRAS));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rp, /*0x0000001D*/ GET_CYCLE(tRPpb));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_r2w, /*0x0000002A*/ tR2W);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_w2r, /*0x00000021*/ tW2R);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_r2p, 0x0000000C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_w2p, 0x0000002D);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rd_rcd, /*0x0000001D*/ GET_CYCLE(tRCD));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wr_rcd, /*0x0000001D*/ GET_CYCLE(tRCD));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rrd, /*0x00000010*/ GET_CYCLE(tRRD));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rext, 0x00000017);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wdv, 0x0000000E);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_quse, 0x00000024);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_qrst, 0x0006000C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_qsafe, 0x00000034);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rdv, 0x0000003C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_refresh, /*0x00001820*/ refresh_raw);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_burst_refresh_num, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2wr, 0x00000010);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2rd, 0x00000010);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pchg2pden, 0x00000003);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_act2pden, 0x00000003);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ar2pden, 0x00000003);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rw2pden, /*0x00000038*/ GET_CYCLE(tRW2PDEN));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_txsr, /*0x0000012C*/ MIN(GET_CYCLE(tXSR), (u32) 1022));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tcke, 0x0000000D);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tfaw, /*0x00000040*/ GET_CYCLE(tFAW));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_trpab, /*0x00000022*/ GET_CYCLE(tRPab));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tclkstable, 0x00000004);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tclkstop, 0x00000014);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_trefbw, /* 0x00001860*/ trefbw);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tppd, 0x00000004);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_odt_write, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, /*0x0000002E*/ GET_CYCLE(pdex2mrr));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wext, 0x00000016);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rfc_slr, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt2, 0x01900017);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_mrs_wait_cnt, 0x0640002F);
|
|
||||||
// // table->emc_mrs = 0x00000000;
|
|
||||||
// // table->emc_emrs = 0x00000000;
|
|
||||||
// // table->emc_mrw = 0x00170040;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_spare, 0x00000012);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_cfg5, 0x9960A00D);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2cke, 0x00000002);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cke2pden, 0x0000000E);
|
|
||||||
// // table->emc_emrs2 = 0x00000000;
|
|
||||||
// // table->emc_mrw2 = 0x0802002D;
|
|
||||||
// // table->emc_mrw3 = 0x0C0D00C0;
|
|
||||||
// // table->emc_mrw4 = 0xC0000000;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_r2r, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_einput, 0x00000014);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_einput_duration, 0x0000001D);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_puterm_extra, 0x0000001F);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tckesr, 0x00000018);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tpd, 0x0000000C);
|
|
||||||
// table->emc_auto_cal_config = 0x201A51D8;
|
|
||||||
// table->emc_cfg_2 = 0x00110835;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll, 0x002C03A9);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_dig_dll_period, 0x00008000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, 0x0000003E);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wdv_mask, 0x0000000E);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, 0x0000003C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rdv_early, 0x0000003A);
|
|
||||||
// table->emc_auto_cal_config8 = 0x00770000;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_zcal_interval, 0x00064000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_zcal_wait_cnt, 0x00310640);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_dq, 0x8020221F);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_fdpd_ctrl_cmd, 0x0220F40F);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_brick_ctrl_fdpd, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_brick_ctrl_fdpd, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_brick_ctrl_rfu1, 0x1FFF1FFF);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_brick_ctrl_rfu2, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_timing_0, 0x01186190);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_tr_ctrl_1, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, 0x0000003C);
|
|
||||||
// table->emc_sel_dpd_ctrl = 0x00040000;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, /*0x00000608*/ (u32) (refresh_raw / 4));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, 0x8000308C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_txsrdll, /*0x0000012C*/ MIN(GET_CYCLE(tXSR), (u32) 1022));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qpop, 0x0000002C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv_mask, 0x0000003E);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qsafe, 0x00000034);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_tr_qrst, 0x0006000C);
|
|
||||||
// table->emc_auto_cal_config2 = 0x05500000;
|
|
||||||
// table->emc_auto_cal_config3 = 0x00770000;
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_tr_dvfs, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_auto_cal_channel, 0xC1E0030A);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ibdly, 0x1000001C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_obdly, 0x10000002);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_txdsrvttgen, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_we_duration, 0x0000000D);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ws_duration, 0x00000008);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wev, 0x0000000A);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wsv, 0x0000000C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cfg_3, 0x00000040);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw6, 0x08037171);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw7, 0x48037171);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw8, 0x080B6666);
|
|
||||||
// // table->emc_mrw9 = 0x0C0E7272;
|
|
||||||
// // table->emc_mrw10 = 0x880C4848;
|
|
||||||
// // table->emc_mrw11 = 0x480C4848; /* Check them maybe */
|
|
||||||
// // table->emc_mrw12 = 0x880E1718;
|
|
||||||
// // table->emc_mrw13 = 0x480E1814;
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw14, 0x08161414);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_mrw15, 0x48161414);
|
|
||||||
// // table->emc_fdpd_ctrl_cmd_no_ramp = 0x00000001;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_wdv_chk, 0x00000006);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_2, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe_1, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_cfg_pipe, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_qpop, 0x0000002C);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_quse_width, 0x00000009);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_puterm_width, 0x0000000E);
|
|
||||||
// table->emc_auto_cal_config7 = 0x00770000;
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_refctrl2, 0x00000000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_fbio_cfg7, 0x00003BFF);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_rfcpb, /*0x00000090*/ GET_CYCLE(tRFCpb));
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_dqs_brlshft_0, 0x00000000); /* brlshft may or may not be important, I don't think it matters but who knows. */
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_dqs_brlshft_1, 0x00000000);
|
|
||||||
// table->emc_auto_cal_config4 = 0x00770000;
|
|
||||||
// table->emc_auto_cal_config5 = 0x00770000;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ccdmw, 0x00000020);
|
|
||||||
// table->emc_auto_cal_config6 = 0x00770000;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_dll_cfg_0, 0x1F13612F);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_dll_cfg_1, 0x00000014);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_config_sample_delay, 0x00000020);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_0, 0x10000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_1, 0x08000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_2, 0x08000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_3, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_4, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_tx_pwrd_5, 0x00001000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_bypass, 0xEFFF2210);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_0, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_1, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_pwrd_2, 0xDCDCDCDC);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_0, 0x0A0A0A0A);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_1, 0x0A0A0A0A);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_ctrl_2, 0x000A0A0A);
|
|
||||||
// // table->trim_regs.emc_pmacro_ib_vref_dq_0 = 0x15171414;
|
|
||||||
// // table->trim_regs.emc_pmacro_ib_vref_dq_1 = 0x15131513;
|
|
||||||
// // table->trim_regs.emc_pmacro_ib_vref_dqs_0 = 0x11111111;
|
|
||||||
// // table->trim_regs.emc_pmacro_ib_vref_dqs_1 = 0x11111111;
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_0, 0x000C000C);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_1, 0x000B000B);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_2, 0x000A000A);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_3, 0x000C000C);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_long_cmd_4, 0x0000000C);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_0, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_1, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ddll_short_cmd_2, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_0, 0x00030808);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_1, 0x00015C00);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_bg_bias_ctrl_0, 0x00000034);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_pad_cfg_ctrl, 0x00020000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_zctrl, 0x00000550);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_pad_rx_ctrl, 0x00000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_pad_rx_ctrl, 0x00000033);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_rx_term_mode, 0x00003000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_rx_term_mode, 0x00000011);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_cmd_pad_tx_ctrl, 0x02000000);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_data_pad_tx_ctrl, 0x02000101);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_common_pad_tx_ctrl, 0x00000007);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_autocal_cfg_common, 0x0000080D);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_vttgen_ctrl_2, 0x00102020);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_pmacro_ib_rxrt, 0x00000055);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_ctrl, 0x00009080);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_cors_ctrl, 0x01124000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_fine_ctrl, 0x01125B6A);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_quse_ctrl_misc, 0x0F081000);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_fine_ctrl, 0x1114FC00);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_ctrl_misc, 0x07004300);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_write_vref_ctrl, 0x00103200);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_fine_ctrl, 0x1110FC00);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_ctrl_misc, 0x0F085300);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_read_vref_ctrl, 0x00105800);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_fine_ctrl, 0x0513801F);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_ctrl_misc, 0x1F101100);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_ctrl_misc1, 0x00000014);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_ca_vref_ctrl, 0x00103200);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_training_settle, 0x07070404);
|
|
||||||
// // WRITE_PARAM_ALL_REG(table, emc_training_mpc, 0x00000000);
|
|
||||||
//
|
|
||||||
// const u32 mc_tRCD = (int) ((double) (GET_CYCLE(tRCD) >> 2) - 2.0);
|
|
||||||
// const u32 mc_tRPpb = (int) (((double) (GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0);
|
|
||||||
// const u32 mc_tRC = (uint) ((double) (GET_CYCLE(tRC) >> 2) - 1.0);
|
|
||||||
// const u32 mc_tR2W = (uint) (((double) ((uint)tR2W >> 2) - 1.0) + 2.0);
|
|
||||||
// const u32 mc_tW2R = (uint) (((double) (tW2R >> 2) - 1.0) + 2.0);
|
|
||||||
// const u32 mc_tRAS = MIN(GET_CYCLE(tRAS), (u32) 0x7F);
|
|
||||||
// const u32 mc_tRRD = MIN(GET_CYCLE(tRRD), (u32) 31);
|
|
||||||
//
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_ras = (int) ((double) (mc_tRAS >> 2) - 2.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rcd = (int) ((double) (GET_CYCLE(tRCD) >> 2) - 2.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rp = (int) (((double) (GET_CYCLE(tRPpb) >> 2) - 1.0) + 2.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rc = (int) ((double) (GET_CYCLE(tRC) >> 2) - 1.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_faw = (int) ((double) (GET_CYCLE(tFAW) >> 2) - 1.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rrd = (int) ((double) (mc_tRRD >> 2) - 1.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_r2w = (uint) (((double) ((uint) tR2W >> 2) - 1.0) + 2.0);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_w2r = (uint) (((double) (tW2R >> 2) - 1.0) + 2.0);
|
|
||||||
//
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_da_turns = (table->burst_mc_regs.mc_emem_arb_da_turns & 0x0000FFFF) | (mc_tW2R << 24) | (mc_tR2W << 16);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_da_covers = (((uint) (mc_tRCD + 3 + mc_tRPpb) >> 1 & 0xff) << 8) | (((uint) (mc_tRCD + 11 + mc_tRPpb) >> 1 & 0xff) << 0x10) | ((mc_tRC >> 1) & 0xff);
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xffe08000U) | ((mc_tRC + 1) & 0xff); /* Missing in l4t dump? TODO */
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rfcpb = GET_CYCLE(tRFCpb) >> 2;
|
|
||||||
//
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_cfg = 0x0000000c;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_rcd = 0x00000006;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_rp = 0x00000007;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_rc = 0x00000018;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_ras = 0x0000000f;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_faw = 0x0000000f;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_rrd = 0x00000003;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_rap2pre = 0x00000003;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_wap2pre = 0x0000000d;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_r2r = 0x00000007;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_w2w = 0x00000007;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_r2w = 0x0000000c;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_w2r = 0x0000000a;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_da_turns = 0x05060303;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_da_covers = 0x000d080c;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_ring1_throttle = 0x001f0000;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_timing_rfcpb = 0x00000023;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_timing_ccdmw = 0x00000008;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_refpb_hp_ctrl = 0x000a1020;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_refpb_bank_ctrl = 0x80001028;
|
|
||||||
// // table->burst_mc_regs.mc_emem_arb_dhyst_ctrl = 0x00000002;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_0 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_1 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_2 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_3 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_4 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_5 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_6 = 0x0000001a;
|
|
||||||
// table->burst_mc_regs.mc_emem_arb_dhyst_timeout_util_7 = 0x0000001a;
|
|
||||||
// table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x000000d0;
|
|
||||||
// table->la_scale_regs.mc_ftop_ptsa_rate = 0x00000018;
|
|
||||||
// table->la_scale_regs.mc_ptsa_grant_decrement = 0x00001203;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_avpc_0 = 0x00800004;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_xusb_1 = 0x00800038;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = 0x00800005;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_sdmmca_0 = 0x00800014;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_isp2_0 = 0x0000002c;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_isp2_1 = 0x00800080;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_vic_0 = 0x0080001d;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_nvdec_0 = 0x00800095;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_tsec_0 = 0x00800041;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_ppcs_1 = 0x00800080;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_xusb_0 = 0x0080003d;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_ppcs_0 = 0x00340049;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_gpu2_0 = 0x00800019;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_hc_1 = 0x00000080;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_sdmmc_0 = 0x00800090;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_mpcore_0 = 0x00800004;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_vi2_0 = 0x00000080;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_hc_0 = 0x00080016;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_gpu_0 = 0x00800019;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = 0x00800005;
|
|
||||||
// table->la_scale_regs.mc_latency_allowance_nvenc_0 = 0x00800018;
|
|
||||||
// table->dram_timings.t_rp = tRFCpb;
|
|
||||||
// table->dram_timings.t_rfc = tRFCab;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* These timings are slightly off from eos, I am not sure why but I am going to figure it out at some point. */
|
|
||||||
void MemMtcTableAutoAdjust(EristaMtcTable *table) {
|
void MemMtcTableAutoAdjust(EristaMtcTable *table) {
|
||||||
|
const double tCK_avg = 1000'000.0 / table->rate_khz;
|
||||||
|
|
||||||
#define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \
|
#define WRITE_PARAM_ALL_REG(TABLE, PARAM, VALUE) \
|
||||||
TABLE->burst_regs.PARAM = VALUE; \
|
TABLE->burst_regs.PARAM = VALUE; \
|
||||||
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
TABLE->shadow_regs_ca_train.PARAM = VALUE; \
|
||||||
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
TABLE->shadow_regs_rdwr_train.PARAM = VALUE;
|
||||||
|
|
||||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
||||||
|
|
||||||
/* Ram power down */
|
/* Ram power down */
|
||||||
/* B31: DRAM_CLKSTOP_PD */
|
/* B31: DRAM_CLKSTOP_PD */
|
||||||
/* B30: DRAM_CLKSTOP_SR */
|
/* B30: DRAM_CLKSTOP_SR */
|
||||||
@@ -515,9 +195,19 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (table->rate_khz > 3200000) {
|
||||||
|
rext = 30;
|
||||||
|
} else if (table->rate_khz >= 2133001) {
|
||||||
|
rext = 28;
|
||||||
|
} else {
|
||||||
|
rext = 26;
|
||||||
|
}
|
||||||
|
|
||||||
u32 trefbw = refresh_raw + 0x40;
|
u32 trefbw = refresh_raw + 0x40;
|
||||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||||
|
|
||||||
|
CalculateTimings(tCK_avg);
|
||||||
|
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
|
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
WRITE_PARAM_ALL_REG(table, emc_rc, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
||||||
@@ -531,15 +221,15 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
|
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_trpab, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
WRITE_PARAM_ALL_REG(table, emc_trpab, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
|
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_tcke, tCKE);
|
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(7.425) + 2);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP));
|
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tXP));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tXP) + 8);
|
WRITE_PARAM_ALL_REG(table, emc_tclkstop, tCLKSTOP);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P);
|
WRITE_PARAM_ALL_REG(table, emc_r2p, tR2P);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W);
|
WRITE_PARAM_ALL_REG(table, emc_r2w, tR2W);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_w2p, tW2P);
|
WRITE_PARAM_ALL_REG(table, emc_w2p, tW2P);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R);
|
WRITE_PARAM_ALL_REG(table, emc_w2r, tW2R);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rext, C.eristaEmcMaxClock < 2133001 ? 26 : 28); // rext shouldn't be causing issues?
|
WRITE_PARAM_ALL_REG(table, emc_rext, rext);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_wext, (C.eristaEmcMaxClock >= 2533000) ? 0x19 : 0x16);
|
WRITE_PARAM_ALL_REG(table, emc_wext, (table->rate_khz >= 2533000) ? 0x19 : 0x16);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
|
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
|
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
|
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
|
||||||
@@ -547,20 +237,46 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
|
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
|
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
|
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.75));
|
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(1.763));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75));
|
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(1.75));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(1.05));
|
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(1.05));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0));
|
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(14.0));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_cke2pden, /* cke2pden */ GET_CYCLE_CEIL(8.5));
|
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(8.499));
|
||||||
(void) cke2pden;
|
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr));
|
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(pdex2mrr));
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN);
|
WRITE_PARAM_ALL_REG(table, emc_rw2pden, tWTPDEN);
|
||||||
|
|
||||||
|
/* Accept imperfection or prepare for suffering. */
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_einput, einput);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_einput_duration, einput_duration);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_obdly, obdly);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_ibdly, ibdly);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_wdv_mask, wdv);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_quse_width, quse_width);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_quse, quse);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_wdv, wdv);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_wsv, wsv);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_wev, wev);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_qrst, qrst);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_tr_qrst, qrst);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_qsafe, qsafe);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_tr_qsafe, qsafe);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_tr_qpop, qpop);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_qpop, qpop);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_rdv, rdv);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv_mask, rdv + 2);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_rdv_early, rdv - 2);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
|
||||||
|
// WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
|
||||||
|
// ams::ldr::hoc::pcv::mariko::CalculateMrw2();
|
||||||
|
// table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
|
||||||
|
// table->dram_timings.rl = RL;
|
||||||
|
|
||||||
/* This needs some clean up. */
|
/* This needs some clean up. */
|
||||||
constexpr double MC_ARB_DIV = 4.0;
|
constexpr double MC_ARB_DIV = 4.0;
|
||||||
constexpr u32 MC_ARB_SFA = 2;
|
constexpr u32 MC_ARB_SFA = 2;
|
||||||
|
|
||||||
table->burst_mc_regs.mc_emem_arb_cfg = C.eristaEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV;
|
table->burst_mc_regs.mc_emem_arb_cfg = table->rate_khz / (33.3 * 1000) / MC_ARB_DIV;
|
||||||
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
|
||||||
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
|
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1;
|
||||||
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
|
||||||
@@ -593,102 +309,153 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
|
|
||||||
table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xFFE08000) | (table->burst_mc_regs.mc_emem_arb_timing_rc + 1);
|
table->burst_mc_regs.mc_emem_arb_misc0 = (table->burst_mc_regs.mc_emem_arb_misc0 & 0xFFE08000) | (table->burst_mc_regs.mc_emem_arb_timing_rc + 1);
|
||||||
|
|
||||||
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = 0x115;
|
u32 mpcorer_ptsa_rate = MIN(static_cast<u32>(227), (table->rate_khz / 1600000) * 208);
|
||||||
|
table->la_scale_regs.mc_mll_mpcorer_ptsa_rate = mpcorer_ptsa_rate;
|
||||||
|
|
||||||
if (C.eristaEmcMaxClock >= 2133000) {
|
u32 ftop_ptsa_rate = MIN(static_cast<u32>(31), (table->rate_khz / 1600000) * 24);
|
||||||
table->la_scale_regs.mc_ftop_ptsa_rate = 0x1F;
|
table->la_scale_regs.mc_ftop_ptsa_rate = ftop_ptsa_rate;
|
||||||
} else {
|
|
||||||
table->la_scale_regs.mc_ftop_ptsa_rate = 0x1B;
|
|
||||||
}
|
|
||||||
|
|
||||||
table->la_scale_regs.mc_ptsa_grant_decrement = 0x17ff;
|
u32 grant_decrement = MIN(static_cast<u32>(6143), (table->rate_khz / 1600000) * 4611);
|
||||||
|
table->la_scale_regs.mc_ptsa_grant_decrement = grant_decrement;
|
||||||
|
|
||||||
constexpr u32 MaskHigh = 0xFF00FFFF;
|
constexpr u32 MaskHigh = 0xFF00FFFF;
|
||||||
constexpr u32 Mask2 = 0xFFFFFF00;
|
constexpr u32 Mask2 = 0xFFFFFF00;
|
||||||
constexpr u32 Mask3 = 0xFF00FF00;
|
constexpr u32 Mask3 = 0xFF00FF00;
|
||||||
|
|
||||||
const u32 allowance1 = static_cast<u32>(0x32000 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance1 = static_cast<u32>(0x32000 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||||
const u32 allowance2 = static_cast<u32>(0x9C40 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance2 = static_cast<u32>(0x9C40 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||||
const u32 allowance3 = static_cast<u32>(0xB540 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance3 = static_cast<u32>(0xB540 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||||
const u32 allowance4 = static_cast<u32>(0x9600 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance4 = static_cast<u32>(0x9600 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||||
const u32 allowance5 = static_cast<u32>(0x8980 / (C.eristaEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance5 = static_cast<u32>(0x8980 / (table->rate_khz / 0x3E8)) & 0xFF;
|
||||||
|
|
||||||
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_isp2_1 = allowance1 | (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||||
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
|
||||||
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
|
||||||
|
|
||||||
table->dram_timings.t_rp = tRFCpb;
|
table->dram_timings.t_rp = tRFCpb;
|
||||||
table->dram_timings.t_rfc = tRFCab;
|
table->dram_timings.t_rfc = tRFCab;
|
||||||
table->dram_timings.rl = RL_DBI;
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_obdly, obdly);
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ibdly, ibdly);
|
|
||||||
|
|
||||||
table->emc_cfg_2 = 0x11083D;
|
table->emc_cfg_2 = 0x11083D;
|
||||||
|
table->min_volt = std::min(static_cast<u32>(1050), 900 + C.emcDvbShift * 25);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Probably more intuitive to point to 40800 rather than 1600000, but oh well. */
|
||||||
|
Result MemFreqMtcTable(u32 *ptr) {
|
||||||
|
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
|
||||||
|
R_SKIP();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MemFreqMtcTable(u32 *ptr) {
|
u32 khz_list[] = { 40800, 68000, 102000, 204000, 408000, 665600, 800000, 1065600, 1331200, 1600000 };
|
||||||
u32 khz_list[] = {1600000, 1331200, 1065600, 800000, 665600, 408000, 204000, 102000, 68000, 40800};
|
std::sort(maxEmcClocks, maxEmcClocks + std::size(maxEmcClocks));
|
||||||
u32 khz_list_size = sizeof(khz_list) / sizeof(u32);
|
u32 khz_list_size = std::size(khz_list);
|
||||||
|
|
||||||
// Generate list for mtc table pointers
|
// Generate list for mtc table pointers
|
||||||
EristaMtcTable *table_list[khz_list_size];
|
EristaMtcTable *table_list[khz_list_size];
|
||||||
for (u32 i = 0; i < khz_list_size; i++) {
|
for (u32 i = 0; i < khz_list_size; i++) {
|
||||||
|
u32 mtcIndex = khz_list_size - 1 - i;
|
||||||
u8 *table = reinterpret_cast<u8 *>(ptr) - offsetof(EristaMtcTable, rate_khz) - i * sizeof(EristaMtcTable);
|
u8 *table = reinterpret_cast<u8 *>(ptr) - offsetof(EristaMtcTable, rate_khz) - i * sizeof(EristaMtcTable);
|
||||||
table_list[i] = reinterpret_cast<EristaMtcTable *>(table);
|
table_list[mtcIndex] = reinterpret_cast<EristaMtcTable *>(table);
|
||||||
R_UNLESS(table_list[i]->rate_khz == khz_list[i], ldr::ResultInvalidMtcTable());
|
R_UNLESS(table_list[mtcIndex]->rate_khz == khz_list[mtcIndex], ldr::ResultInvalidMtcTable());
|
||||||
R_UNLESS(table_list[i]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
|
R_UNLESS(table_list[mtcIndex]->rev == MTC_TABLE_REV, ldr::ResultInvalidMtcTable());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (C.eristaEmcMaxClock <= EmcClkOSLimit)
|
/* If we oc ram at all, tables are always shifted by at least 1. */
|
||||||
R_SKIP();
|
u32 tableShifts = 1;
|
||||||
|
for (u32 i = 0; i < std::size(maxEmcClocks) - 1; ++i) {
|
||||||
|
/* Duplicated mtc tables may cause pcv to not select frequencies properly, causing issues. */
|
||||||
|
if (maxEmcClocks[i] != maxEmcClocks[i + 1] && maxEmcClocks[i] > EmcClkOSLimit) {
|
||||||
|
++tableShifts;
|
||||||
|
} else {
|
||||||
|
maxEmcClocks[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Make room for new mtc table, discarding useless 40.8 MHz table
|
/* Erista has extra, useless mtc tables, such as 40.8 Mhz, overwrite them to make room for oc freqs. */
|
||||||
// 40800 overwritten by 68000, ..., 1331200 overwritten by 1600000, leaving table_list[0] not overwritten
|
/* More than 3 tables can be overwritten, but 3 is plenty. */
|
||||||
for (u32 i = khz_list_size - 1; i > 0; i--)
|
std::memmove(table_list[0], table_list[tableShifts], sizeof(EristaMtcTable) * (khz_list_size - tableShifts));
|
||||||
std::memcpy(static_cast<void *>(table_list[i]), static_cast<void *>(table_list[i - 1]), sizeof(EristaMtcTable));
|
|
||||||
|
|
||||||
MemMtcTableAutoAdjust(table_list[0]);
|
/* Since we're not scaling r/w latency properly on Erista, we first overwrite the tables with the 1600 MHz table before scaling it. */
|
||||||
|
for (u32 i = 0; i < tableShifts; ++i) {
|
||||||
|
std::memcpy(table_list[khz_list_size - i - 1], table_list[khz_list_size - tableShifts - 1], sizeof(EristaMtcTable));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = tableShifts, j = 0; i > 0 && j < std::size(maxEmcClocks); ++j) {
|
||||||
|
if (!maxEmcClocks[j]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
table_list[khz_list_size - i]->rate_khz = maxEmcClocks[j];
|
||||||
|
MemMtcTableAutoAdjust(table_list[khz_list_size - i]);
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
|
||||||
PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MemFreqMax(u32 *ptr) {
|
Result MemFreqMax(u32 *ptr) {
|
||||||
if (C.eristaEmcMaxClock <= EmcClkOSLimit)
|
if (GET_MAX_OF_ARR(maxEmcClocks) <= EmcClkOSLimit) {
|
||||||
R_SKIP();
|
R_SKIP();
|
||||||
|
}
|
||||||
|
|
||||||
PATCH_OFFSET(ptr, C.eristaEmcMaxClock);
|
PATCH_OFFSET(ptr, GET_MAX_OF_ARR(maxEmcClocks));
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result GpuFreqPllMax(u32 *ptr) {
|
||||||
|
clk_pll_param *entry = reinterpret_cast<clk_pll_param *>(ptr);
|
||||||
|
|
||||||
|
// All zero except for freq
|
||||||
|
for (size_t i = 1; i < sizeof(clk_pll_param) / sizeof(u32); i++) {
|
||||||
|
R_UNLESS(*(ptr + i) == 0, ldr::ResultInvalidGpuPllEntry());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double the max clk simply
|
||||||
|
u32 max_clk = entry->freq * 2;
|
||||||
|
entry->freq = max_clk;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// patch out 1305MHz limit on erista, don't use this!
|
||||||
|
// Result GpuFreqPllLimit(u32 *ptr) {
|
||||||
|
// u32 prev_freq = *(ptr - 1);
|
||||||
|
|
||||||
|
// if (prev_freq != 128000 && prev_freq != 1300000 && prev_freq != 76800) {
|
||||||
|
// R_THROW(ldr::ResultInvalidGpuPllEntry());
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PATCH_OFFSET(ptr, 3600000);
|
||||||
|
|
||||||
|
// R_SUCCEED();
|
||||||
|
// }
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||||
PatcherEntry<u32> patches[] = {
|
PatcherEntry<u32> patches[] = {
|
||||||
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)},
|
{"CPU Freq Table", CpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(CpuCvbTableDefault)->freq)},
|
||||||
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, 825},
|
{"CPU Volt DVFS", &CpuVoltDvfs, 1, nullptr, CpuVminOfficial},
|
||||||
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, 825},
|
{"CPU Volt Thermals", &CpuVoltThermals, 1, nullptr, CpuVminOfficial},
|
||||||
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF},
|
{"CPU Volt Dfll", &CpuVoltDfll, 1, nullptr, 0xFFEAD0FF},
|
||||||
{"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, 810},
|
{"GPU Volt DVFS", &GpuVoltDVFS, 1, nullptr, GpuVminOfficial},
|
||||||
{"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, 810},
|
{"GPU Volt Thermals", &GpuVoltThermals, 1, nullptr, GpuVminOfficial},
|
||||||
{"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)},
|
{"GPU Freq Table", GpuFreqCvbTable<false>, 1, nullptr, static_cast<u32>(GetDvfsTableLastEntry(GpuCvbTableDefault)->freq)},
|
||||||
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn},
|
{"GPU Freq Asm", &GpuFreqMaxAsm, 2, &GpuMaxClockPatternFn},
|
||||||
{"GPU Freq PLL", &GpuFreqPllLimit, 1, nullptr, GpuClkPllLimit},
|
{"GPU PLL Max", &GpuFreqPllMax, 1, nullptr, GpuClkPllMax},
|
||||||
|
// {"GPU PLL Limit", &GpuFreqPllLimit, 4, nullptr, GpuClkPllLimit},
|
||||||
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit},
|
{"MEM Freq Mtc", &MemFreqMtcTable, 0, nullptr, EmcClkOSLimit},
|
||||||
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit},
|
{"MEM Freq Max", &MemFreqMax, 0, nullptr, EmcClkOSLimit},
|
||||||
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit},
|
{"MEM Freq PLLM", &MemFreqPllmLimit, 2, nullptr, EmcClkPllmLimit},
|
||||||
@@ -707,8 +474,13 @@ namespace ams::ldr::hoc::pcv::erista {
|
|||||||
for (auto &entry : patches) {
|
for (auto &entry : patches) {
|
||||||
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
|
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
|
||||||
if (R_FAILED(entry.CheckResult())) {
|
if (R_FAILED(entry.CheckResult())) {
|
||||||
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
||||||
|
panic::SmcError(panic::Patch);
|
||||||
|
#endif
|
||||||
|
|
||||||
CRASH(entry.description);
|
CRASH(entry.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,30 +50,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
return ramScale;
|
return ramScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetSpeedoBracket() {
|
|
||||||
u32 speedoBracket = 3;
|
|
||||||
if ((C.gpuSpeedo < 1754) && (speedoBracket = 2, C.gpuSpeedo < 1690)) {
|
|
||||||
speedoBracket = !!(1625 < C.gpuSpeedo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return speedoBracket;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 GetGpuBudgetDvfsVoltage() {
|
|
||||||
u32 bracket = GetSpeedoBracket();
|
|
||||||
|
|
||||||
if (ramFreqMhz <= 1600)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for (u32 voltageIndex = 0; voltageIndex < 22; voltageIndex++) {
|
|
||||||
if (ramFreqMhz <= ramBrackets[bracket][voltageIndex]) {
|
|
||||||
return gpuBudgetDvfsArray[voltageIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 800;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */
|
/* Note: EOS (probably?) has a bug in this function that always results in high vmin, this is fixed here. */
|
||||||
u32 GetAutoVoltage() {
|
u32 GetAutoVoltage() {
|
||||||
u32 voltage = GetGpuVminVoltage();
|
u32 voltage = GetGpuVminVoltage();
|
||||||
@@ -102,14 +78,13 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* C.marikoGpuVmin is non zero, user sets manual voltage. */
|
/* C.marikoGpuVmin is non zero, user sets manual voltage. */
|
||||||
if (C.marikoGpuVmin != 0 && C.marikoGpuVmin != 1) {
|
if (C.marikoGpuVmin) {
|
||||||
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
PATCH_OFFSET(ptr, C.marikoGpuVmin);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* C.marikoGpuVmin is zero OR one, auto voltage is applied. */
|
/* C.marikoGpuVmin is zero, auto voltage is applied. */
|
||||||
/* Get vmin depending on speedo and ram clock. */
|
u32 autoVmin = GetAutoVoltage();
|
||||||
u32 autoVmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
|
||||||
PATCH_OFFSET(ptr, autoVmin);
|
PATCH_OFFSET(ptr, autoVmin);
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -122,8 +97,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
u32 vmin = C.marikoGpuVmin;
|
u32 vmin = C.marikoGpuVmin;
|
||||||
|
|
||||||
/* Automatic voltage. */
|
/* Automatic voltage. */
|
||||||
if (!C.marikoGpuVmin || C.marikoGpuVmin == 1) {
|
if (!C.marikoGpuVmin) {
|
||||||
vmin = C.marikoGpuVmin == 0 ? GetAutoVoltage() : GetGpuBudgetDvfsVoltage();
|
vmin = GetAutoVoltage();
|
||||||
PATCH_OFFSET(ptr, vmin);
|
PATCH_OFFSET(ptr, vmin);
|
||||||
PATCH_OFFSET(ptr + 3, vmin);
|
PATCH_OFFSET(ptr + 3, vmin);
|
||||||
PATCH_OFFSET(ptr + 6, vmin);
|
PATCH_OFFSET(ptr + 6, vmin);
|
||||||
@@ -291,7 +266,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
switch (C.marikoCpuUVHigh) {
|
switch (C.marikoCpuUVHigh) {
|
||||||
case 1:
|
case 1:
|
||||||
PATCH_OFFSET(&(entry->tune1_high), 0);
|
PATCH_OFFSET(&(entry->tune1_high), 0);
|
||||||
@@ -441,6 +415,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
u32 trefbw = refresh_raw + 0x40;
|
u32 trefbw = refresh_raw + 0x40;
|
||||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
||||||
|
|
||||||
|
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
|
||||||
|
|
||||||
CalculateTimings();
|
CalculateTimings();
|
||||||
|
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
|
||||||
@@ -472,7 +448,6 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
|
WRITE_PARAM_ALL_REG(table, emc_refresh, refresh_raw);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
|
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, refresh_raw / 4);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
|
WRITE_PARAM_ALL_REG(table, emc_trefbw, trefbw);
|
||||||
const u32 dyn_self_ref_control = (static_cast<u32>(7605.0 / tCK_avg) + 260) | (table->burst_regs.emc_dyn_self_ref_control & 0xffff0000);
|
|
||||||
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
|
WRITE_PARAM_ALL_REG(table, emc_dyn_self_ref_control, dyn_self_ref_control);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
|
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, pdex2rw);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
|
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, pdex2rw);
|
||||||
@@ -505,8 +480,9 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
|
WRITE_PARAM_ALL_REG(table, emc_rdv_early_mask, rdv);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
|
WRITE_PARAM_ALL_REG(table, emc_rdv_mask, rdv + 2);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
|
WRITE_PARAM_ALL_REG(table, emc_tr_rdv, rdv);
|
||||||
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_2, 0x24)
|
/* TODO: Check this out again at some point. */
|
||||||
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_3, 0x24)
|
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_2, 0x24);
|
||||||
|
WRITE_PARAM_ALL_REG(table, emc_cmd_brlshft_3, 0x24);
|
||||||
|
|
||||||
/* This needs some clean up. */
|
/* This needs some clean up. */
|
||||||
constexpr double MC_ARB_DIV = 4.0;
|
constexpr double MC_ARB_DIV = 4.0;
|
||||||
@@ -524,7 +500,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA;
|
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA;
|
||||||
|
|
||||||
/* Two consecutive reads between two different dram modules. */
|
/* Two consecutive reads between two different dram modules. */
|
||||||
/* Only be above 1 for 8gb ram. */
|
/* Only above 1 for 8gb ram. */
|
||||||
if (table->burst_mc_regs.mc_emem_arb_timing_r2r > 1) {
|
if (table->burst_mc_regs.mc_emem_arb_timing_r2r > 1) {
|
||||||
table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / 4) - 1 + MC_ARB_SFA;
|
table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / 4) - 1 + MC_ARB_SFA;
|
||||||
}
|
}
|
||||||
@@ -572,42 +548,34 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
const u32 allowance4 = static_cast<u32>(0x9600 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance4 = static_cast<u32>(0x9600 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
||||||
const u32 allowance5 = static_cast<u32>(0x8980 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
const u32 allowance5 = static_cast<u32>(0x8980 / (C.marikoEmcMaxClock / 0x3E8)) & 0xFF;
|
||||||
|
|
||||||
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_xusb_0 = (table->la_scale_regs.mc_latency_allowance_xusb_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_xusb_1 = (table->la_scale_regs.mc_latency_allowance_xusb_1 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_tsec_0 = (table->la_scale_regs.mc_latency_allowance_tsec_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcaa_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmcab_0 = (table->la_scale_regs.mc_latency_allowance_sdmmcab_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmc_0 = (table->la_scale_regs.mc_latency_allowance_sdmmc_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_sdmmca_0 = (table->la_scale_regs.mc_latency_allowance_sdmmca_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_ppcs_1 = (table->la_scale_regs.mc_latency_allowance_ppcs_1 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_nvdec_0 = (table->la_scale_regs.mc_latency_allowance_nvdec_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_mpcore_0 = (table->la_scale_regs.mc_latency_allowance_mpcore_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_avpc_0 = (table->la_scale_regs.mc_latency_allowance_avpc_0 & MaskHigh) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_isp2_1 = allowance1 | (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_isp2_1 = (table->la_scale_regs.mc_latency_allowance_isp2_1 & Mask3) | (allowance1 << 16) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
table->la_scale_regs.mc_latency_allowance_vic_0 = allowance3 | (table->la_scale_regs.mc_latency_allowance_vic_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_gpu_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_nvenc_0 = allowance4 | (table->la_scale_regs.mc_latency_allowance_nvenc_0 & Mask3) | (allowance1 << 16);
|
||||||
table->la_scale_regs.mc_latency_allowance_gpu2_0 = allowance2 | (table->la_scale_regs.mc_latency_allowance_gpu2_0 & Mask3) | (allowance1 << 16);
|
table->la_scale_regs.mc_latency_allowance_hc_0 = (table->la_scale_regs.mc_latency_allowance_hc_0 & Mask2) | allowance5;
|
||||||
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_hc_1 = (table->la_scale_regs.mc_latency_allowance_hc_1 & Mask2) | allowance1;
|
||||||
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
|
table->la_scale_regs.mc_latency_allowance_vi2_0 = (table->la_scale_regs.mc_latency_allowance_vi2_0 & Mask2) | allowance1;
|
||||||
|
|
||||||
table->dram_timings.t_rp = tRFCpb;
|
table->dram_timings.t_rp = tRFCpb;
|
||||||
table->dram_timings.t_rfc = tRFCab;
|
table->dram_timings.t_rfc = tRFCab;
|
||||||
table->dram_timings.rl = RL_DBI;
|
table->dram_timings.rl = RL;
|
||||||
|
|
||||||
table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
|
table->emc_mrw2 = (table->emc_mrw2 & ~0xFFu) | static_cast<u32>(mrw2);
|
||||||
table->emc_cfg_2 = 0x11083D;
|
table->emc_cfg_2 = 0x11083D;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE(10.0));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE(10.0));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE(1.75));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE(1.75));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE(1.75));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE(14.0));
|
|
||||||
// WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE(5.0));
|
|
||||||
|
|
||||||
void MemMtcPllmbDivisor(MarikoMtcTable *table) {
|
void MemMtcPllmbDivisor(MarikoMtcTable *table) {
|
||||||
constexpr u32 PllOscInKHz = 38400;
|
constexpr u32 PllOscInKHz = 38400;
|
||||||
constexpr u32 PllOscHalfKHz = 19200;
|
constexpr u32 PllOscHalfKHz = 19200;
|
||||||
@@ -686,9 +654,8 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
|
|
||||||
// Copy unmodified 1600000 table to tmp
|
// Copy unmodified 1600000 table to tmp
|
||||||
std::memcpy(reinterpret_cast<void *>(tmp), reinterpret_cast<void *>(table_max), sizeof(MarikoMtcTable));
|
std::memcpy(reinterpret_cast<void *>(tmp), reinterpret_cast<void *>(table_max), sizeof(MarikoMtcTable));
|
||||||
// Adjust max freq mtc timing parameters with reference to 1331200 table
|
|
||||||
/* TODO: Implement mariko */
|
|
||||||
|
|
||||||
|
/* Adjust timings properly according to the new frequency. */
|
||||||
MemMtcTableAutoAdjust(table_max);
|
MemMtcTableAutoAdjust(table_max);
|
||||||
|
|
||||||
MemMtcPllmbDivisor(table_max);
|
MemMtcPllmbDivisor(table_max);
|
||||||
@@ -717,6 +684,7 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
|
|
||||||
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
|
#define DVB_VOLT(zero, one, two) std::min(zero + voltAdd, 1050), std::min(one + voltAdd, 1025), std::min(two + voltAdd, 1000),
|
||||||
|
|
||||||
|
/* TODO: More fine tuned values? */
|
||||||
if (C.marikoEmcMaxClock < 1862400) {
|
if (C.marikoEmcMaxClock < 1862400) {
|
||||||
std::memcpy(new_start, default_end, sizeof(emc_dvb_dvfs_table_t));
|
std::memcpy(new_start, default_end, sizeof(emc_dvb_dvfs_table_t));
|
||||||
} else if (C.marikoEmcMaxClock < 2131200) {
|
} else if (C.marikoEmcMaxClock < 2131200) {
|
||||||
@@ -844,6 +812,10 @@ namespace ams::ldr::hoc::pcv::mariko {
|
|||||||
for (auto &entry : patches) {
|
for (auto &entry : patches) {
|
||||||
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
|
LOGGING("%s Count: %zu", entry.description, entry.patched_count);
|
||||||
if (R_FAILED(entry.CheckResult())) {
|
if (R_FAILED(entry.CheckResult())) {
|
||||||
|
#if defined(AMS_BUILD_FOR_AUDITING) || defined(AMS_BUILD_FOR_DEBUGGING)
|
||||||
|
panic::SmcError(panic::Patch);
|
||||||
|
#endif
|
||||||
|
|
||||||
CRASH(entry.description);
|
CRASH(entry.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,116 +20,111 @@
|
|||||||
|
|
||||||
namespace ams::ldr::hoc::ptm {
|
namespace ams::ldr::hoc::ptm {
|
||||||
|
|
||||||
Result CpuPtmBoost(perf_conf_entry* entry) {
|
Result CpuPtmBoost(perf_conf_entry* entry) {
|
||||||
|
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||||
|
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
||||||
|
#else
|
||||||
|
bool isMariko = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock) {
|
||||||
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
R_SUCCEED();
|
||||||
#else
|
}
|
||||||
bool isMariko = true;
|
|
||||||
#endif
|
u32 cpuPtmBoostNew = isMariko ? C.marikoCpuBoostClock * 1000 : C.eristaCpuBoostClock * 1000;
|
||||||
|
|
||||||
|
PATCH_OFFSET(&(entry->cpu_freq_1), cpuPtmBoostNew);
|
||||||
|
PATCH_OFFSET(&(entry->cpu_freq_2), cpuPtmBoostNew);
|
||||||
|
|
||||||
if (!C.eristaCpuBoostClock || !C.marikoCpuBoostClock)
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|
||||||
u32 cpuPtmBoostNew = isMariko ? C.marikoCpuBoostClock * 1000 : C.eristaCpuBoostClock * 1000;
|
|
||||||
|
|
||||||
PATCH_OFFSET(&(entry->cpu_freq_1), cpuPtmBoostNew);
|
|
||||||
PATCH_OFFSET(&(entry->cpu_freq_2), cpuPtmBoostNew);
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MemPtm(perf_conf_entry* entry) {
|
|
||||||
PATCH_OFFSET(&(entry->emc_freq_1), memPtmLimit);
|
|
||||||
PATCH_OFFSET(&(entry->emc_freq_2), memPtmLimit);
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PtmEntryIsValid(perf_conf_entry* entry) {
|
|
||||||
return (entry->cpu_freq_1 == entry->cpu_freq_2 &&
|
|
||||||
entry->gpu_freq_1 == entry->gpu_freq_2 &&
|
|
||||||
entry->emc_freq_1 == entry->emc_freq_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PtmTablePatternFn(u32* ptr) {
|
|
||||||
perf_conf_entry* entry = reinterpret_cast<perf_conf_entry *>(ptr);
|
|
||||||
if (!PtmEntryIsValid(entry))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return entry->cpu_freq_1 == cpuPtmDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
|
||||||
perf_conf_entry* confTable = nullptr;
|
|
||||||
for (uintptr_t ptr = mapped_nso;
|
|
||||||
ptr <= mapped_nso + nso_size - sizeof(perf_conf_entry) * entryCnt;
|
|
||||||
ptr += sizeof(u32))
|
|
||||||
{
|
|
||||||
u32* ptr32 = reinterpret_cast<u32 *>(ptr);
|
|
||||||
if (PtmTablePatternFn(ptr32)) {
|
|
||||||
confTable = reinterpret_cast<perf_conf_entry *>(ptr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!confTable) {
|
Result MemPtm(perf_conf_entry* entry) {
|
||||||
CRASH("confTable not found!");
|
PATCH_OFFSET(&(entry->emc_freq_1), memPtmLimit);
|
||||||
|
PATCH_OFFSET(&(entry->emc_freq_2), memPtmLimit);
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, };
|
bool PtmEntryIsValid(perf_conf_entry* entry) {
|
||||||
PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, };
|
return (entry->cpu_freq_1 == entry->cpu_freq_2 && entry->gpu_freq_1 == entry->gpu_freq_2 && entry->emc_freq_1 == entry->emc_freq_2);
|
||||||
|
}
|
||||||
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
|
||||||
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
|
||||||
#else
|
|
||||||
bool isMariko = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
for (u32 i = 0; i < entryCnt; i++) {
|
|
||||||
perf_conf_entry* entry = confTable + i;
|
|
||||||
|
|
||||||
|
bool PtmTablePatternFn(u32* ptr) {
|
||||||
|
perf_conf_entry* entry = reinterpret_cast<perf_conf_entry *>(ptr);
|
||||||
if (!PtmEntryIsValid(entry)) {
|
if (!PtmEntryIsValid(entry)) {
|
||||||
LOGGING("@%p", &entry);
|
return false;
|
||||||
CRASH("Invalid ptm confTable entry");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (entry->cpu_freq_1) {
|
return entry->cpu_freq_1 == cpuPtmDefault;
|
||||||
case cpuPtmBoost:
|
}
|
||||||
cpuPtmBoostPatch.Apply(entry);
|
|
||||||
|
void Patch(uintptr_t mapped_nso, size_t nso_size) {
|
||||||
|
perf_conf_entry* confTable = nullptr;
|
||||||
|
for (uintptr_t ptr = mapped_nso; ptr <= mapped_nso + nso_size - sizeof(perf_conf_entry) * entryCnt; ptr += sizeof(u32)) {
|
||||||
|
u32* ptr32 = reinterpret_cast<u32 *>(ptr);
|
||||||
|
if (PtmTablePatternFn(ptr32)) {
|
||||||
|
confTable = reinterpret_cast<perf_conf_entry *>(ptr);
|
||||||
break;
|
break;
|
||||||
case cpuPtmDefault:
|
}
|
||||||
case cpuPtmDevOC:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOGGING("%u (0x%08x) @%p", entry->cpu_freq_1, entry->conf_id, &(entry->cpu_freq_1));
|
|
||||||
CRASH("Unknown CPU Freq");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (entry->emc_freq_1) {
|
if (!confTable) {
|
||||||
case memPtmLimit:
|
CRASH("confTable not found!");
|
||||||
case memPtmAlt:
|
}
|
||||||
case memPtmClamp:
|
|
||||||
if (isMariko) {
|
PatcherEntry<perf_conf_entry> cpuPtmBoostPatch = { "CPU Ptm Boost", &CpuPtmBoost, 2, };
|
||||||
memPtmPatch.Apply(entry);
|
PatcherEntry<perf_conf_entry> memPtmPatch = { "MEM Ptm", &MemPtm, 16, };
|
||||||
}
|
|
||||||
break;
|
#ifdef ATMOSPHERE_IS_STRATOSPHERE
|
||||||
default:
|
bool isMariko = (spl::GetSocType() == spl::SocType_Mariko);
|
||||||
LOGGING("%u (0x%08x) @%p", entry->emc_freq_1, entry->conf_id, &(entry->emc_freq_2));
|
#else
|
||||||
CRASH("Unknown MEM Freq");
|
bool isMariko = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (u32 i = 0; i < entryCnt; i++) {
|
||||||
|
perf_conf_entry *entry = confTable + i;
|
||||||
|
|
||||||
|
if (!PtmEntryIsValid(entry)) {
|
||||||
|
LOGGING("@%p", &entry);
|
||||||
|
CRASH("Invalid ptm confTable entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entry->cpu_freq_1) {
|
||||||
|
case cpuPtmBoost:
|
||||||
|
cpuPtmBoostPatch.Apply(entry);
|
||||||
|
break;
|
||||||
|
case cpuPtmDefault:
|
||||||
|
case cpuPtmDevOC:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGGING("%u (0x%08x) @%p", entry->cpu_freq_1, entry->conf_id, &(entry->cpu_freq_1));
|
||||||
|
CRASH("Unknown CPU Freq");
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (entry->emc_freq_1) {
|
||||||
|
case memPtmLimit:
|
||||||
|
case memPtmAlt:
|
||||||
|
case memPtmClamp:
|
||||||
|
if (isMariko) {
|
||||||
|
memPtmPatch.Apply(entry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LOGGING("%u (0x%08x) @%p", entry->emc_freq_1, entry->conf_id, &(entry->emc_freq_2));
|
||||||
|
CRASH("Unknown MEM Freq");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGING("%s Count: %zu", cpuPtmBoostPatch.description, cpuPtmBoostPatch.patched_count);
|
||||||
|
if (R_FAILED(cpuPtmBoostPatch.CheckResult()))
|
||||||
|
CRASH(cpuPtmBoostPatch.description);
|
||||||
|
|
||||||
|
if (isMariko) {
|
||||||
|
LOGGING("%s Count: %zu", memPtmPatch.description, memPtmPatch.patched_count);
|
||||||
|
if (R_FAILED(memPtmPatch.CheckResult()))
|
||||||
|
CRASH(memPtmPatch.description);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGING("%s Count: %zu", cpuPtmBoostPatch.description, cpuPtmBoostPatch.patched_count);
|
|
||||||
if (R_FAILED(cpuPtmBoostPatch.CheckResult()))
|
|
||||||
CRASH(cpuPtmBoostPatch.description);
|
|
||||||
|
|
||||||
if (isMariko) {
|
|
||||||
LOGGING("%s Count: %zu", memPtmPatch.description, memPtmPatch.patched_count);
|
|
||||||
if (R_FAILED(memPtmPatch.CheckResult()))
|
|
||||||
CRASH(memPtmPatch.description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,26 +22,26 @@
|
|||||||
|
|
||||||
namespace ams::ldr::hoc::ptm {
|
namespace ams::ldr::hoc::ptm {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u32 conf_id;
|
u32 conf_id;
|
||||||
u32 cpu_freq_1; // min-max pair?
|
u32 cpu_freq_1; // min-max pair?
|
||||||
u32 cpu_freq_2;
|
u32 cpu_freq_2;
|
||||||
u32 gpu_freq_1;
|
u32 gpu_freq_1;
|
||||||
u32 gpu_freq_2;
|
u32 gpu_freq_2;
|
||||||
u32 emc_freq_1;
|
u32 emc_freq_1;
|
||||||
u32 emc_freq_2;
|
u32 emc_freq_2;
|
||||||
u32 padding;
|
u32 padding;
|
||||||
} perf_conf_entry;
|
} perf_conf_entry;
|
||||||
|
|
||||||
constexpr u32 entryCnt = 16;
|
constexpr u32 entryCnt = 16;
|
||||||
constexpr u32 cpuPtmDefault = 1020'000'000;
|
constexpr u32 cpuPtmDefault = 1020'000'000;
|
||||||
constexpr u32 cpuPtmDevOC = 1224'000'000;
|
constexpr u32 cpuPtmDevOC = 1224'000'000;
|
||||||
constexpr u32 cpuPtmBoost = 1785'000'000;
|
constexpr u32 cpuPtmBoost = 1785'000'000;
|
||||||
|
|
||||||
constexpr u32 memPtmLimit = 1600'000'000;
|
constexpr u32 memPtmLimit = 1600'000'000;
|
||||||
constexpr u32 memPtmAlt = 1331'200'000;
|
constexpr u32 memPtmAlt = 1331'200'000;
|
||||||
constexpr u32 memPtmClamp = 1065'600'000;
|
constexpr u32 memPtmClamp = 1065'600'000;
|
||||||
|
|
||||||
void Patch(uintptr_t mapped_nso, size_t nso_size);
|
void Patch(uintptr_t mapped_nso, size_t nso_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ include $(DEVKITPRO)/libnx/switch_rules
|
|||||||
# NACP building is skipped as well.
|
# NACP building is skipped as well.
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
APP_TITLE := Horizon OC Monitor
|
APP_TITLE := Horizon OC Monitor
|
||||||
APP_VERSION := 1.3.2+r4-hoc
|
APP_VERSION := 1.3.2+r4-hoc-r2
|
||||||
TARGET := $(notdir $(CURDIR))
|
TARGET := $(notdir $(CURDIR))
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := source
|
SOURCES := source
|
||||||
|
|||||||
@@ -685,7 +685,7 @@ void Misc2(void*) {
|
|||||||
|
|
||||||
void Misc3(void*) {
|
void Misc3(void*) {
|
||||||
const bool isUsingEOS = usingEOS();
|
const bool isUsingEOS = usingEOS();
|
||||||
|
|
||||||
// Initialize voltage reading if needed
|
// Initialize voltage reading if needed
|
||||||
bool canReadVoltages = false;
|
bool canReadVoltages = false;
|
||||||
if (!isUsingEOS && realVoltsPolling) {
|
if (!isUsingEOS && realVoltsPolling) {
|
||||||
@@ -694,7 +694,7 @@ void Misc3(void*) {
|
|||||||
realVoltsPolling = false;
|
realVoltsPolling = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
mutexLock(&mutex_Misc);
|
mutexLock(&mutex_Misc);
|
||||||
|
|
||||||
@@ -706,7 +706,7 @@ void Misc3(void*) {
|
|||||||
if (R_SUCCEEDED(tcCheck)) {
|
if (R_SUCCEEDED(tcCheck)) {
|
||||||
tcGetSkinTemperatureMilliC(&skin_temperaturemiliC);
|
tcGetSkinTemperatureMilliC(&skin_temperaturemiliC);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fan
|
// Fan
|
||||||
if (R_SUCCEEDED(pwmCheck)) {
|
if (R_SUCCEEDED(pwmCheck)) {
|
||||||
double temp = 0;
|
double temp = 0;
|
||||||
@@ -720,16 +720,21 @@ void Misc3(void*) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GPU Load
|
// GPU Load
|
||||||
if (R_SUCCEEDED(nvCheck)) {
|
if (R_SUCCEEDED(nvCheck)) {
|
||||||
nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &GPU_Load_u);
|
nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &GPU_Load_u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SysClkContext sysclkCTX;
|
||||||
|
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&sysclkCTX))) {
|
||||||
|
partLoad[SysClkPartLoad_EMC] = sysclkCTX.partLoad[SysClkPartLoad_EMC];
|
||||||
|
}
|
||||||
|
|
||||||
mutexUnlock(&mutex_Misc);
|
mutexUnlock(&mutex_Misc);
|
||||||
|
|
||||||
} while (!leventWait(&threadexit, 1'000'000'000)); // 1 second timeout
|
} while (!leventWait(&threadexit, 1'000'000'000)); // 1 second timeout
|
||||||
|
|
||||||
// Cleanup voltage reading if initialized
|
// Cleanup voltage reading if initialized
|
||||||
if (canReadVoltages) {
|
if (canReadVoltages) {
|
||||||
rgltrExit();
|
rgltrExit();
|
||||||
@@ -2453,4 +2458,4 @@ ALWAYS_INLINE void GetConfigSettings(ResolutionSettings* settings) {
|
|||||||
convertToUpper(key);
|
convertToUpper(key);
|
||||||
settings->disableScreenshots = (key != "FALSE");
|
settings->disableScreenshots = (key != "FALSE");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -79,14 +79,17 @@ Result sysclkIpcGetAPIVersion(u32* out_ver)
|
|||||||
Result sysclkIpcGetVersionString(char* out, size_t len)
|
Result sysclkIpcGetVersionString(char* out, size_t len)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetVersionString,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetVersionString,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out, len}},
|
.buffers = {{out, len}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcGetCurrentContext(SysClkContext* out_context)
|
Result sysclkIpcGetCurrentContext(SysClkContext* out_context)
|
||||||
{
|
{
|
||||||
return serviceDispatchOut(&g_sysclkSrv, SysClkIpcCmd_GetCurrentContext, *out_context);
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetCurrentContext,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
|
.buffers = {{out_context, sizeof(SysClkContext)}},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcGetProfileCount(u64 tid, u8* out_count)
|
Result sysclkIpcGetProfileCount(u64 tid, u8* out_count)
|
||||||
@@ -112,7 +115,7 @@ Result sysclkIpcSetOverride(SysClkModule module, u32 hz)
|
|||||||
Result sysclkIpcGetProfiles(u64 tid, SysClkTitleProfileList* out_profiles)
|
Result sysclkIpcGetProfiles(u64 tid, SysClkTitleProfileList* out_profiles)
|
||||||
{
|
{
|
||||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_GetProfiles, tid,
|
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_GetProfiles, tid,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out_profiles, sizeof(SysClkTitleProfileList)}},
|
.buffers = {{out_profiles, sizeof(SysClkTitleProfileList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -128,7 +131,7 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles)
|
|||||||
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetConfigValues,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetConfigValues,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out_configValues, sizeof(SysClkConfigValueList)}},
|
.buffers = {{out_configValues, sizeof(SysClkConfigValueList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,7 @@ Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
|||||||
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues)
|
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_SetConfigValues,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_SetConfigValues,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
|
||||||
.buffers = {{configValues, sizeof(SysClkConfigValueList)}},
|
.buffers = {{configValues, sizeof(SysClkConfigValueList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -153,12 +156,6 @@ Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* o
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode)
|
|
||||||
{
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result hocClkIpcSetKipData()
|
Result hocClkIpcSetKipData()
|
||||||
{
|
{
|
||||||
u32 temp = 0;
|
u32 temp = 0;
|
||||||
@@ -169,15 +166,4 @@ Result hocClkIpcGetKipData()
|
|||||||
{
|
{
|
||||||
u32 temp = 0;
|
u32 temp = 0;
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||||
}
|
|
||||||
|
|
||||||
Result hocClkIpcUpdateEmcRegs()
|
|
||||||
{
|
|
||||||
u32 temp = 0;
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
|
||||||
}
|
|
||||||
Result hocClkIpcCalculateGpuVmin()
|
|
||||||
{
|
|
||||||
u32 temp = 0;
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
|
||||||
}
|
}
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
@echo off
|
|
||||||
setlocal enabledelayedexpansion
|
|
||||||
|
|
||||||
REM --- Root directory ---
|
|
||||||
set ROOT_DIR=%~dp0
|
|
||||||
set DIST_DIR=%ROOT_DIR%dist
|
|
||||||
|
|
||||||
REM --- Number of CPU cores ---
|
|
||||||
set CORES=%NUMBER_OF_PROCESSORS%
|
|
||||||
|
|
||||||
REM --- Optional first argument as DIST_DIR ---
|
|
||||||
if not "%~1"=="" set DIST_DIR=%~1
|
|
||||||
|
|
||||||
echo DIST_DIR: %DIST_DIR%
|
|
||||||
echo CORES: %CORES%
|
|
||||||
|
|
||||||
REM ========================
|
|
||||||
REM sysmodule
|
|
||||||
REM ========================
|
|
||||||
echo *** sysmodule ***
|
|
||||||
|
|
||||||
REM Extract TITLE_ID from perms.json using findstr (rough approximation)
|
|
||||||
for /f "tokens=2 delims=: " %%A in ('findstr /i "title_id" "%ROOT_DIR%sysmodule\perms.json"') do (
|
|
||||||
set TITLE_ID=%%A
|
|
||||||
)
|
|
||||||
|
|
||||||
REM Remove quotes and 0x prefix
|
|
||||||
set TITLE_ID=!TITLE_ID:"=!
|
|
||||||
set TITLE_ID=!TITLE_ID:0x=!
|
|
||||||
|
|
||||||
REM Build sysmodule
|
|
||||||
pushd "%ROOT_DIR%sysmodule"
|
|
||||||
make -j %CORES%
|
|
||||||
popd
|
|
||||||
|
|
||||||
REM Copy sysmodule files to dist
|
|
||||||
if not exist "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags" mkdir "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags"
|
|
||||||
copy /Y "%ROOT_DIR%sysmodule\out\horizon-oc.nsp" "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\exefs.nsp"
|
|
||||||
type nul > "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\flags\boot2.flag"
|
|
||||||
copy /Y "%ROOT_DIR%sysmodule\toolbox.json" "%DIST_DIR%\atmosphere\contents\%TITLE_ID%\toolbox.json"
|
|
||||||
|
|
||||||
REM ========================
|
|
||||||
REM overlay
|
|
||||||
REM ========================
|
|
||||||
echo *** overlay ***
|
|
||||||
pushd "%ROOT_DIR%overlay"
|
|
||||||
make -j %CORES%
|
|
||||||
popd
|
|
||||||
|
|
||||||
if not exist "%DIST_DIR%\switch\.overlays" mkdir "%DIST_DIR%\switch\.overlays"
|
|
||||||
copy /Y "%ROOT_DIR%overlay\out\horizon-oc-overlay.ovl" "%DIST_DIR%\switch\.overlays\horizon-oc-overlay.ovl"
|
|
||||||
|
|
||||||
REM ========================
|
|
||||||
REM assets
|
|
||||||
REM ========================
|
|
||||||
echo *** assets ***
|
|
||||||
if not exist "%DIST_DIR%\config\horizon-oc" mkdir "%DIST_DIR%\config\horizon-oc"
|
|
||||||
copy /Y "%ROOT_DIR%config.ini.template" "%DIST_DIR%\config\horizon-oc\config.ini.template"
|
|
||||||
copy /Y "%ROOT_DIR%..\..\README.md" "%DIST_DIR%\README.md"
|
|
||||||
|
|
||||||
endlocal
|
|
||||||
@@ -36,3 +36,7 @@ echo "*** assets ***"
|
|||||||
mkdir -p "$DIST_DIR/config/horizon-oc"
|
mkdir -p "$DIST_DIR/config/horizon-oc"
|
||||||
cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
|
cp -vf "$ROOT_DIR/config.ini.template" "$DIST_DIR/config/horizon-oc/config.ini.template"
|
||||||
cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md"
|
cp -vf "$ROOT_DIR/../../README.md" "$DIST_DIR/README.md"
|
||||||
|
|
||||||
|
echo "*** lang ***"
|
||||||
|
|
||||||
|
cp -r "$ROOT_DIR/overlay/lang/" "$DIST_DIR/config/horizon-oc/lang/"
|
||||||
|
|||||||
248
Source/sys-clk/common/include/SaltyNX.h
Normal file
248
Source/sys-clk/common/include/SaltyNX.h
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) MasaGratoR
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "ipc.h"
|
||||||
|
|
||||||
|
Handle saltysd_orig;
|
||||||
|
|
||||||
|
Result SaltySD_Connect() {
|
||||||
|
for (int i = 0; i < 200; i++) {
|
||||||
|
if (!svcConnectToNamedPort(&saltysd_orig, "SaltySD"))
|
||||||
|
return 0;
|
||||||
|
svcSleepThread(1000*1000);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SaltySD_Term()
|
||||||
|
{
|
||||||
|
Result ret;
|
||||||
|
IpcCommand c;
|
||||||
|
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcSendPid(&c);
|
||||||
|
|
||||||
|
struct input
|
||||||
|
{
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 zero;
|
||||||
|
u64 reserved[2];
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = (input*)ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 0;
|
||||||
|
raw->zero = 0;
|
||||||
|
|
||||||
|
ret = ipcDispatch(saltysd_orig);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ret))
|
||||||
|
{
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct output {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *resp = (output*)r.Raw;
|
||||||
|
|
||||||
|
ret = resp->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session terminated works too.
|
||||||
|
svcCloseHandle(saltysd_orig);
|
||||||
|
if (ret == 0xf601) return 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SaltySD_CheckIfSharedMemoryAvailable(ptrdiff_t *offset, u64 size)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
// Send a command
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcSendPid(&c);
|
||||||
|
|
||||||
|
struct input {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 size;
|
||||||
|
u32 reserved[2];
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = (input*)ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 6;
|
||||||
|
raw->size = size;
|
||||||
|
|
||||||
|
ret = ipcDispatch(saltysd_orig);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ret)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct output {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 offset;
|
||||||
|
} *resp = (output*)r.Raw;
|
||||||
|
|
||||||
|
ret = resp->result;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
*offset = resp->offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SaltySD_GetSharedMemoryHandle(Handle *retrieve)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
// Send a command
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcSendPid(&c);
|
||||||
|
|
||||||
|
struct input {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u32 reserved[4];
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = (input*)ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 7;
|
||||||
|
|
||||||
|
ret = ipcDispatch(saltysd_orig);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ret)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct output {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 reserved[2];
|
||||||
|
} *resp = (output*)r.Raw;
|
||||||
|
|
||||||
|
ret = resp->result;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
*retrieve = r.Handles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SaltySD_GetDisplayRefreshRate(uint8_t* refreshRate)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
// Send a command
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcSendPid(&c);
|
||||||
|
|
||||||
|
struct input {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 zero;
|
||||||
|
u64 reserved;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = (input*)ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 10;
|
||||||
|
raw->zero = 0;
|
||||||
|
|
||||||
|
ret = ipcDispatch(saltysd_orig);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ret)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct output {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 refreshRate;
|
||||||
|
u64 reserved;
|
||||||
|
} *resp = (output*)r.Raw;
|
||||||
|
|
||||||
|
ret = resp->result;
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
{
|
||||||
|
*refreshRate = (uint8_t)(resp->refreshRate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SaltySD_SetDisplayRefreshRate(uint8_t refreshRate)
|
||||||
|
{
|
||||||
|
Result ret = 0;
|
||||||
|
|
||||||
|
// Send a command
|
||||||
|
IpcCommand c;
|
||||||
|
ipcInitialize(&c);
|
||||||
|
ipcSendPid(&c);
|
||||||
|
|
||||||
|
struct input {
|
||||||
|
u64 magic;
|
||||||
|
u64 cmd_id;
|
||||||
|
u64 refreshRate;
|
||||||
|
u64 reserved;
|
||||||
|
} *raw;
|
||||||
|
|
||||||
|
raw = (input*)ipcPrepareHeader(&c, sizeof(*raw));
|
||||||
|
|
||||||
|
raw->magic = SFCI_MAGIC;
|
||||||
|
raw->cmd_id = 11;
|
||||||
|
raw->refreshRate = refreshRate;
|
||||||
|
|
||||||
|
ret = ipcDispatch(saltysd_orig);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(ret)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct output {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u64 reserved[2];
|
||||||
|
} *resp = (output*)r.Raw;
|
||||||
|
|
||||||
|
ret = resp->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
// Battery charging flags
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BatteryFlag_NoHub = BIT(0), // Hub is disconnected
|
BatteryFlag_NoHub = BIT(0), // Hub is disconnected
|
||||||
BatteryFlag_Rail = BIT(8), // At least one Joy-con is charging from rail
|
BatteryFlag_Rail = BIT(8), // At least one Joy-con is charging from rail
|
||||||
@@ -27,7 +26,6 @@ typedef enum {
|
|||||||
BatteryFlag_ACC = BIT(16) // Accessory
|
BatteryFlag_ACC = BIT(16) // Accessory
|
||||||
} BatteryChargeFlags;
|
} BatteryChargeFlags;
|
||||||
|
|
||||||
// Power Delivery Controller State (BM92T series)
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PDState_NewPDO = 1, // Received new Power Data Object
|
PDState_NewPDO = 1, // Received new Power Data Object
|
||||||
PDState_NoPD = 2, // No Power Delivery source is detected
|
PDState_NoPD = 2, // No Power Delivery source is detected
|
||||||
@@ -47,14 +45,11 @@ typedef enum {
|
|||||||
ChargerType_Apple_1000mA = 8,
|
ChargerType_Apple_1000mA = 8,
|
||||||
ChargerType_Apple_2000mA = 9
|
ChargerType_Apple_2000mA = 9
|
||||||
} BatteryChargerType;
|
} BatteryChargerType;
|
||||||
|
|
||||||
// Power role (USB Power Delivery)
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
PowerRole_Sink = 1, // Device is receiving power
|
PowerRole_Sink = 1, // Device is receiving power
|
||||||
PowerRole_Source = 2 // Device is providing power
|
PowerRole_Source = 2 // Device is providing power
|
||||||
} BatteryPowerRole;
|
} BatteryPowerRole;
|
||||||
|
|
||||||
// Complete battery charge information structure
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t InputCurrentLimit; // Input (Sink) current limit in mA
|
int32_t InputCurrentLimit; // Input (Sink) current limit in mA
|
||||||
int32_t VBUSCurrentLimit; // Output (Source/VBUS/OTG) current limit in mA
|
int32_t VBUSCurrentLimit; // Output (Source/VBUS/OTG) current limit in mA
|
||||||
@@ -64,7 +59,7 @@ typedef struct {
|
|||||||
int32_t unk_x14; // Unknown field (possibly flags)
|
int32_t unk_x14; // Unknown field (possibly flags)
|
||||||
BatteryPDControllerState PDControllerState; // PD Controller State
|
BatteryPDControllerState PDControllerState; // PD Controller State
|
||||||
int32_t BatteryTemperature; // Battery temperature in milli-Celsius
|
int32_t BatteryTemperature; // Battery temperature in milli-Celsius
|
||||||
int32_t RawBatteryCharge; // Battery charge in per cent-mille (100% = 100000)
|
int32_t RawBatteryCharge; // Battery charge in percentmille
|
||||||
int32_t VoltageAvg; // Average voltage in mV
|
int32_t VoltageAvg; // Average voltage in mV
|
||||||
int32_t BatteryAge; // Battery health (capacity full/design) in pcm
|
int32_t BatteryAge; // Battery health (capacity full/design) in pcm
|
||||||
BatteryPowerRole PowerRole; // Current power role
|
BatteryPowerRole PowerRole; // Current power role
|
||||||
@@ -74,36 +69,27 @@ typedef struct {
|
|||||||
BatteryChargeFlags Flags; // Various status flags
|
BatteryChargeFlags Flags; // Various status flags
|
||||||
} BatteryChargeInfo;
|
} BatteryChargeInfo;
|
||||||
|
|
||||||
// Helper macro to check if battery charging is enabled
|
|
||||||
#define IS_BATTERY_CHARGING_ENABLED(info) (((info)->unk_x14 >> 8) & 1)
|
#define IS_BATTERY_CHARGING_ENABLED(info) (((info)->unk_x14 >> 8) & 1)
|
||||||
|
|
||||||
// Initialize the battery info driver
|
|
||||||
Result batteryInfoInitialize(void);
|
Result batteryInfoInitialize(void);
|
||||||
|
|
||||||
// Cleanup the battery info driver
|
|
||||||
void batteryInfoExit(void);
|
void batteryInfoExit(void);
|
||||||
|
|
||||||
// Get complete battery charge information
|
|
||||||
Result batteryInfoGetChargeInfo(BatteryChargeInfo *out);
|
Result batteryInfoGetChargeInfo(BatteryChargeInfo *out);
|
||||||
|
|
||||||
// Get battery charge percentage (0-100)
|
|
||||||
Result batteryInfoGetChargePercentage(u32 *out);
|
Result batteryInfoGetChargePercentage(u32 *out);
|
||||||
|
|
||||||
// Check if enough power is being supplied
|
|
||||||
Result batteryInfoIsEnoughPowerSupplied(bool *out);
|
Result batteryInfoIsEnoughPowerSupplied(bool *out);
|
||||||
|
|
||||||
// Battery charge control functions
|
|
||||||
Result batteryInfoEnableCharging(void);
|
Result batteryInfoEnableCharging(void);
|
||||||
Result batteryInfoDisableCharging(void);
|
Result batteryInfoDisableCharging(void);
|
||||||
Result batteryInfoEnableFastCharging(void);
|
Result batteryInfoEnableFastCharging(void);
|
||||||
Result batteryInfoDisableFastCharging(void);
|
Result batteryInfoDisableFastCharging(void);
|
||||||
|
|
||||||
// Helper functions to get human-readable strings
|
|
||||||
const char* batteryInfoGetChargerTypeString(BatteryChargerType type);
|
const char* batteryInfoGetChargerTypeString(BatteryChargerType type);
|
||||||
const char* batteryInfoGetPowerRoleString(BatteryPowerRole role);
|
const char* batteryInfoGetPowerRoleString(BatteryPowerRole role);
|
||||||
const char* batteryInfoGetPDStateString(BatteryPDControllerState state);
|
const char* batteryInfoGetPDStateString(BatteryPDControllerState state);
|
||||||
|
|
||||||
// Convenience functions for common values
|
|
||||||
static inline int batteryInfoGetTemperatureMiliCelsius(BatteryChargeInfo *info) {
|
static inline int batteryInfoGetTemperatureMiliCelsius(BatteryChargeInfo *info) {
|
||||||
return info->BatteryTemperature;
|
return info->BatteryTemperature;
|
||||||
}
|
}
|
||||||
@@ -120,7 +106,6 @@ static inline bool batteryInfoIsCharging(BatteryChargeInfo *info) {
|
|||||||
return IS_BATTERY_CHARGING_ENABLED(info);
|
return IS_BATTERY_CHARGING_ENABLED(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// String lookup tables
|
|
||||||
static const char* s_chargerTypeStrings[] = {
|
static const char* s_chargerTypeStrings[] = {
|
||||||
"None",
|
"None",
|
||||||
"Power Delivery",
|
"Power Delivery",
|
||||||
@@ -187,7 +172,6 @@ static Result psmDisableFastBatteryCharging_internal(void) {
|
|||||||
return serviceDispatch(&g_psmService, 11);
|
return serviceDispatch(&g_psmService, 11);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public API implementations
|
|
||||||
Result batteryInfoInitialize(void) {
|
Result batteryInfoInitialize(void) {
|
||||||
if (g_batteryInfoInitialized)
|
if (g_batteryInfoInitialized)
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -15,17 +15,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef DISPLAY_REFRESH_RATE_H
|
#pragma once
|
||||||
#define DISPLAY_REFRESH_RATE_H
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Display mode structures
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t hFrontPorch;
|
uint16_t hFrontPorch;
|
||||||
uint8_t hSyncWidth;
|
uint8_t hSyncWidth;
|
||||||
@@ -52,7 +47,6 @@ typedef struct {
|
|||||||
uint8_t max;
|
uint8_t max;
|
||||||
} MinMaxRefreshRate;
|
} MinMaxRefreshRate;
|
||||||
|
|
||||||
// Display mode information
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t unk0;
|
uint32_t unk0;
|
||||||
uint32_t hActive;
|
uint32_t hActive;
|
||||||
@@ -76,7 +70,6 @@ typedef struct {
|
|||||||
uint32_t num_modes;
|
uint32_t num_modes;
|
||||||
} NvdcModeDB2;
|
} NvdcModeDB2;
|
||||||
|
|
||||||
// PLL structures
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int PLLD_DIVM: 8;
|
unsigned int PLLD_DIVM: 8;
|
||||||
unsigned int reserved_1: 3;
|
unsigned int reserved_1: 3;
|
||||||
@@ -109,7 +102,6 @@ typedef struct {
|
|||||||
unsigned int reserved: 2;
|
unsigned int reserved: 2;
|
||||||
} PLLD_MISC;
|
} PLLD_MISC;
|
||||||
|
|
||||||
// Configuration structure
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t clkVirtAddr;
|
uint64_t clkVirtAddr;
|
||||||
uint64_t dsiVirtAddr;
|
uint64_t dsiVirtAddr;
|
||||||
@@ -124,17 +116,11 @@ typedef struct {
|
|||||||
bool displaySyncDocked;
|
bool displaySyncDocked;
|
||||||
bool displaySyncDockedOutOfFocus60;
|
bool displaySyncDockedOutOfFocus60;
|
||||||
} DisplayRefreshConfig;
|
} DisplayRefreshConfig;
|
||||||
|
|
||||||
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config);
|
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config);
|
||||||
|
void DisplayRefresh_SetDockedState(bool isDocked);
|
||||||
bool DisplayRefresh_SetRate(uint32_t new_refreshRate);
|
bool DisplayRefresh_SetRate(uint32_t new_refreshRate);
|
||||||
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal);
|
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal);
|
||||||
uint8_t DisplayRefresh_GetDockedHighestAllowed(void);
|
uint8_t DisplayRefresh_GetDockedHighestAllowed(void);
|
||||||
void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate);
|
void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate);
|
||||||
void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p);
|
void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p);
|
||||||
void DisplayRefresh_Shutdown(void);
|
void DisplayRefresh_Shutdown(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // DISPLAY_REFRESH_RATE_H
|
|
||||||
756
Source/sys-clk/common/include/ipc.h
Normal file
756
Source/sys-clk/common/include/ipc.h
Normal file
@@ -0,0 +1,756 @@
|
|||||||
|
/**
|
||||||
|
* @file ipc.h
|
||||||
|
* @brief Inter-process communication handling
|
||||||
|
* @author plutoo
|
||||||
|
* @copyright libnx Authors (ISC License)
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
/// IPC input header magic
|
||||||
|
#define SFCI_MAGIC 0x49434653
|
||||||
|
/// IPC output header magic
|
||||||
|
#define SFCO_MAGIC 0x4f434653
|
||||||
|
|
||||||
|
/// IPC invalid object ID
|
||||||
|
#define IPC_INVALID_OBJECT_ID UINT32_MAX
|
||||||
|
|
||||||
|
///@name IPC request building
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/// IPC command (request) structure.
|
||||||
|
#define IPC_MAX_BUFFERS 8
|
||||||
|
#define IPC_MAX_OBJECTS 8
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BufferType_Normal=0, ///< Regular buffer.
|
||||||
|
BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory.
|
||||||
|
BufferType_Invalid=2,
|
||||||
|
BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping.
|
||||||
|
} BufferType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BufferDirection_Send=0,
|
||||||
|
BufferDirection_Recv=1,
|
||||||
|
BufferDirection_Exch=2,
|
||||||
|
} BufferDirection;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
IpcCommandType_Invalid = 0,
|
||||||
|
IpcCommandType_LegacyRequest = 1,
|
||||||
|
IpcCommandType_Close = 2,
|
||||||
|
IpcCommandType_LegacyControl = 3,
|
||||||
|
IpcCommandType_Request = 4,
|
||||||
|
IpcCommandType_Control = 5,
|
||||||
|
IpcCommandType_RequestWithContext = 6,
|
||||||
|
IpcCommandType_ControlWithContext = 7,
|
||||||
|
} IpcCommandType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DomainMessageType_Invalid = 0,
|
||||||
|
DomainMessageType_SendMessage = 1,
|
||||||
|
DomainMessageType_Close = 2,
|
||||||
|
} DomainMessageType;
|
||||||
|
|
||||||
|
/// IPC domain message header.
|
||||||
|
typedef struct {
|
||||||
|
u8 Type;
|
||||||
|
u8 NumObjectIds;
|
||||||
|
u16 Length;
|
||||||
|
u32 ThisObjectId;
|
||||||
|
u32 Pad[2];
|
||||||
|
} DomainMessageHeader;
|
||||||
|
|
||||||
|
/// IPC domain response header.
|
||||||
|
typedef struct {
|
||||||
|
u32 NumObjectIds;
|
||||||
|
u32 Pad[3];
|
||||||
|
} DomainResponseHeader;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
size_t NumSend; // A
|
||||||
|
size_t NumRecv; // B
|
||||||
|
size_t NumExch; // W
|
||||||
|
const void* Buffers[IPC_MAX_BUFFERS];
|
||||||
|
size_t BufferSizes[IPC_MAX_BUFFERS];
|
||||||
|
BufferType BufferTypes[IPC_MAX_BUFFERS];
|
||||||
|
|
||||||
|
size_t NumStaticIn; // X
|
||||||
|
size_t NumStaticOut; // C
|
||||||
|
const void* Statics[IPC_MAX_BUFFERS];
|
||||||
|
size_t StaticSizes[IPC_MAX_BUFFERS];
|
||||||
|
u8 StaticIndices[IPC_MAX_BUFFERS];
|
||||||
|
|
||||||
|
bool SendPid;
|
||||||
|
size_t NumHandlesCopy;
|
||||||
|
size_t NumHandlesMove;
|
||||||
|
Handle Handles[IPC_MAX_OBJECTS];
|
||||||
|
|
||||||
|
size_t NumObjectIds;
|
||||||
|
u32 ObjectIds[IPC_MAX_OBJECTS];
|
||||||
|
} IpcCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
*/
|
||||||
|
static inline void ipcInitialize(IpcCommand* cmd) {
|
||||||
|
*cmd = (IpcCommand){};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// IPC buffer descriptor.
|
||||||
|
typedef struct {
|
||||||
|
u32 Size; ///< Size of the buffer.
|
||||||
|
u32 Addr; ///< Lower 32-bits of the address of the buffer
|
||||||
|
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||||
|
} IpcBufferDescriptor;
|
||||||
|
|
||||||
|
/// IPC static send-buffer descriptor.
|
||||||
|
typedef struct {
|
||||||
|
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||||
|
u32 Addr; ///< Lower 32-bits of the address
|
||||||
|
} IpcStaticSendDescriptor;
|
||||||
|
|
||||||
|
/// IPC static receive-buffer descriptor.
|
||||||
|
typedef struct {
|
||||||
|
u32 Addr; ///< Lower 32-bits of the address of the buffer
|
||||||
|
u32 Packed; ///< Packed data (including higher bits of the address)
|
||||||
|
} IpcStaticRecvDescriptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a buffer to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param type Buffer type.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type) {
|
||||||
|
size_t off = cmd->NumSend;
|
||||||
|
cmd->Buffers[off] = buffer;
|
||||||
|
cmd->BufferSizes[off] = size;
|
||||||
|
cmd->BufferTypes[off] = type;
|
||||||
|
cmd->NumSend++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a receive-buffer to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param type Buffer type.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) {
|
||||||
|
size_t off = cmd->NumSend + cmd->NumRecv;
|
||||||
|
cmd->Buffers[off] = buffer;
|
||||||
|
cmd->BufferSizes[off] = size;
|
||||||
|
cmd->BufferTypes[off] = type;
|
||||||
|
cmd->NumRecv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds an exchange-buffer to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param type Buffer type.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) {
|
||||||
|
size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch;
|
||||||
|
cmd->Buffers[off] = buffer;
|
||||||
|
cmd->BufferSizes[off] = size;
|
||||||
|
cmd->BufferTypes[off] = type;
|
||||||
|
cmd->NumExch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a static-buffer to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param index Index of buffer.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) {
|
||||||
|
size_t off = cmd->NumStaticIn;
|
||||||
|
cmd->Statics[off] = buffer;
|
||||||
|
cmd->StaticSizes[off] = size;
|
||||||
|
cmd->StaticIndices[off] = index;
|
||||||
|
cmd->NumStaticIn++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a static-receive-buffer to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param index Index of buffer.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) {
|
||||||
|
size_t off = cmd->NumStaticIn + cmd->NumStaticOut;
|
||||||
|
cmd->Statics[off] = buffer;
|
||||||
|
cmd->StaticSizes[off] = size;
|
||||||
|
cmd->StaticIndices[off] = index;
|
||||||
|
cmd->NumStaticOut++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param pointer_buffer_size Pointer buffer size.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param index Index of buffer.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddSendSmart(IpcCommand* cmd, size_t pointer_buffer_size, const void* buffer, size_t size, u8 index) {
|
||||||
|
if (pointer_buffer_size != 0 && size <= pointer_buffer_size) {
|
||||||
|
ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal);
|
||||||
|
ipcAddSendStatic(cmd, buffer, size, index);
|
||||||
|
} else {
|
||||||
|
ipcAddSendBuffer(cmd, buffer, size, BufferType_Normal);
|
||||||
|
ipcAddSendStatic(cmd, NULL, 0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param pointer_buffer_size Pointer buffer size.
|
||||||
|
* @param buffer Address of the buffer.
|
||||||
|
* @param size Size of the buffer.
|
||||||
|
* @param index Index of buffer.
|
||||||
|
*/
|
||||||
|
static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t pointer_buffer_size, void* buffer, size_t size, u8 index) {
|
||||||
|
if (pointer_buffer_size != 0 && size <= pointer_buffer_size) {
|
||||||
|
ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal);
|
||||||
|
ipcAddRecvStatic(cmd, buffer, size, index);
|
||||||
|
} else {
|
||||||
|
ipcAddRecvBuffer(cmd, buffer, size, BufferType_Normal);
|
||||||
|
ipcAddRecvStatic(cmd, NULL, 0, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tags an IPC command structure to send the PID.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
*/
|
||||||
|
static inline void ipcSendPid(IpcCommand* cmd) {
|
||||||
|
cmd->SendPid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a copy-handle to be sent through an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param h Handle to send.
|
||||||
|
* @remark The receiving process gets a copy of the handle.
|
||||||
|
*/
|
||||||
|
static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) {
|
||||||
|
cmd->Handles[cmd->NumHandlesCopy++] = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds a move-handle to be sent through an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param h Handle to send.
|
||||||
|
* @remark The sending process loses ownership of the handle, which is transferred to the receiving process.
|
||||||
|
*/
|
||||||
|
static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) {
|
||||||
|
cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares the header of an IPC command structure.
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
|
||||||
|
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
|
||||||
|
*/
|
||||||
|
static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
size_t i;
|
||||||
|
*buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28);
|
||||||
|
|
||||||
|
u32* fill_in_size_later = buf;
|
||||||
|
|
||||||
|
if (cmd->NumStaticOut > 0) {
|
||||||
|
*buf = (cmd->NumStaticOut + 2) << 10;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*buf = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) {
|
||||||
|
*buf++ |= 0x80000000;
|
||||||
|
*buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5);
|
||||||
|
|
||||||
|
if (cmd->SendPid)
|
||||||
|
buf += 2;
|
||||||
|
|
||||||
|
for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++)
|
||||||
|
*buf++ = cmd->Handles[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<cmd->NumStaticIn; i++, buf+=2) {
|
||||||
|
IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf;
|
||||||
|
|
||||||
|
uintptr_t ptr = (uintptr_t) cmd->Statics[i];
|
||||||
|
desc->Addr = ptr;
|
||||||
|
desc->Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) |
|
||||||
|
(((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) {
|
||||||
|
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
||||||
|
desc->Size = cmd->BufferSizes[i];
|
||||||
|
|
||||||
|
uintptr_t ptr = (uintptr_t) cmd->Buffers[i];
|
||||||
|
desc->Addr = ptr;
|
||||||
|
desc->Packed = cmd->BufferTypes[i] |
|
||||||
|
(((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4;
|
||||||
|
u32* raw = (u32*) (buf + padding);
|
||||||
|
|
||||||
|
size_t raw_size = (sizeof_raw/4) + 4;
|
||||||
|
buf += raw_size;
|
||||||
|
|
||||||
|
u16* buf_u16 = (u16*) buf;
|
||||||
|
|
||||||
|
for (i=0; i<cmd->NumStaticOut; i++) {
|
||||||
|
size_t off = cmd->NumStaticIn + i;
|
||||||
|
size_t sz = (uintptr_t) cmd->StaticSizes[off];
|
||||||
|
|
||||||
|
buf_u16[i] = (sz > 0xFFFF) ? 0 : sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4;
|
||||||
|
buf += u16s_size;
|
||||||
|
raw_size += u16s_size;
|
||||||
|
|
||||||
|
*fill_in_size_later |= raw_size;
|
||||||
|
|
||||||
|
for (i=0; i<cmd->NumStaticOut; i++, buf+=2) {
|
||||||
|
IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf;
|
||||||
|
size_t off = cmd->NumStaticIn + i;
|
||||||
|
|
||||||
|
uintptr_t ptr = (uintptr_t) cmd->Statics[off];
|
||||||
|
desc->Addr = ptr;
|
||||||
|
desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void*) raw;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dispatches an IPC request.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcDispatch(Handle session) {
|
||||||
|
return svcSendSyncRequest(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
///@name IPC response parsing
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/// IPC parsed command (response) structure.
|
||||||
|
typedef struct {
|
||||||
|
IpcCommandType CommandType; ///< Type of the command
|
||||||
|
|
||||||
|
bool HasPid; ///< true if the 'Pid' field is filled out.
|
||||||
|
u64 Pid; ///< PID included in the response (only if HasPid is true)
|
||||||
|
|
||||||
|
size_t NumHandles; ///< Number of handles copied.
|
||||||
|
Handle Handles[IPC_MAX_OBJECTS]; ///< Handles.
|
||||||
|
bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied.
|
||||||
|
|
||||||
|
bool IsDomainRequest; ///< true if the the message is a Domain message.
|
||||||
|
DomainMessageType InMessageType; ///< Type of the domain message.
|
||||||
|
u32 InMessageLength; ///< Size of rawdata (for domain messages).
|
||||||
|
u32 InThisObjectId; ///< Object ID to call the command on (for domain messages).
|
||||||
|
size_t InNumObjectIds; ///< Number of object IDs (for domain messages).
|
||||||
|
u32 InObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages).
|
||||||
|
|
||||||
|
bool IsDomainResponse; ///< true if the the message is a Domain response.
|
||||||
|
size_t OutNumObjectIds; ///< Number of object IDs (for domain responses).
|
||||||
|
u32 OutObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain responses).
|
||||||
|
|
||||||
|
size_t NumBuffers; ///< Number of buffers in the response.
|
||||||
|
void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers.
|
||||||
|
size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers.
|
||||||
|
BufferType BufferTypes[IPC_MAX_BUFFERS]; ///< Types of the buffers.
|
||||||
|
BufferDirection BufferDirections[IPC_MAX_BUFFERS]; ///< Direction of each buffer.
|
||||||
|
|
||||||
|
size_t NumStatics; ///< Number of statics in the response.
|
||||||
|
void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics.
|
||||||
|
size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics.
|
||||||
|
u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics.
|
||||||
|
|
||||||
|
size_t NumStaticsOut; ///< Number of output statics available in the response.
|
||||||
|
|
||||||
|
void* Raw; ///< Pointer to the raw embedded data structure in the response.
|
||||||
|
void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding.
|
||||||
|
size_t RawSize; ///< Size of the raw embedded data.
|
||||||
|
} IpcParsedCommand;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse an IPC command response into an IPC parsed command structure.
|
||||||
|
* @param r IPC parsed command structure to fill in.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcParse(IpcParsedCommand* r) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
u32 ctrl0 = *buf++;
|
||||||
|
u32 ctrl1 = *buf++;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
r->IsDomainRequest = false;
|
||||||
|
r->IsDomainResponse = false;
|
||||||
|
|
||||||
|
r->CommandType = (IpcCommandType) (ctrl0 & 0xffff);
|
||||||
|
r->HasPid = false;
|
||||||
|
r->RawSize = (ctrl1 & 0x1ff) * 4;
|
||||||
|
r->NumHandles = 0;
|
||||||
|
|
||||||
|
r->NumStaticsOut = (ctrl1 >> 10) & 15;
|
||||||
|
if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor
|
||||||
|
if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors
|
||||||
|
|
||||||
|
if (ctrl1 & 0x80000000) {
|
||||||
|
u32 ctrl2 = *buf++;
|
||||||
|
|
||||||
|
if (ctrl2 & 1) {
|
||||||
|
r->HasPid = true;
|
||||||
|
r->Pid = *buf++;
|
||||||
|
r->Pid |= ((u64)(*buf++)) << 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_handles_copy = ((ctrl2 >> 1) & 15);
|
||||||
|
size_t num_handles_move = ((ctrl2 >> 5) & 15);
|
||||||
|
|
||||||
|
size_t num_handles = num_handles_copy + num_handles_move;
|
||||||
|
u32* buf_after_handles = buf + num_handles;
|
||||||
|
|
||||||
|
if (num_handles > IPC_MAX_OBJECTS)
|
||||||
|
num_handles = IPC_MAX_OBJECTS;
|
||||||
|
|
||||||
|
for (i=0; i<num_handles; i++)
|
||||||
|
{
|
||||||
|
r->Handles[i] = *(buf+i);
|
||||||
|
r->WasHandleCopied[i] = (i < num_handles_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
r->NumHandles = num_handles;
|
||||||
|
buf = buf_after_handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_statics = (ctrl0 >> 16) & 15;
|
||||||
|
u32* buf_after_statics = buf + num_statics*2;
|
||||||
|
|
||||||
|
if (num_statics > IPC_MAX_BUFFERS)
|
||||||
|
num_statics = IPC_MAX_BUFFERS;
|
||||||
|
|
||||||
|
for (i=0; i<num_statics; i++, buf+=2) {
|
||||||
|
IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf;
|
||||||
|
u64 packed = (u64) desc->Packed;
|
||||||
|
|
||||||
|
r->Statics[i] = (void*) (desc->Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36));
|
||||||
|
r->StaticSizes[i] = packed >> 16;
|
||||||
|
r->StaticIndices[i] = packed & 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->NumStatics = num_statics;
|
||||||
|
buf = buf_after_statics;
|
||||||
|
|
||||||
|
size_t num_bufs_send = (ctrl0 >> 20) & 15;
|
||||||
|
size_t num_bufs_recv = (ctrl0 >> 24) & 15;
|
||||||
|
size_t num_bufs_exch = (ctrl0 >> 28) & 15;
|
||||||
|
|
||||||
|
size_t num_bufs = num_bufs_send + num_bufs_recv + num_bufs_exch;
|
||||||
|
r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15);
|
||||||
|
r->RawWithoutPadding = (void*)((uintptr_t)(buf + num_bufs*3));
|
||||||
|
|
||||||
|
if (num_bufs > IPC_MAX_BUFFERS)
|
||||||
|
num_bufs = IPC_MAX_BUFFERS;
|
||||||
|
|
||||||
|
for (i=0; i<num_bufs; i++, buf+=3) {
|
||||||
|
IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf;
|
||||||
|
u64 packed = (u64) desc->Packed;
|
||||||
|
|
||||||
|
r->Buffers[i] = (void*) (desc->Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36));
|
||||||
|
r->BufferSizes[i] = desc->Size;
|
||||||
|
r->BufferTypes[i] = (BufferType) (packed & 3);
|
||||||
|
|
||||||
|
if (i < num_bufs_send)
|
||||||
|
r->BufferDirections[i] = BufferDirection_Send;
|
||||||
|
else if (i < (num_bufs_send + num_bufs_recv))
|
||||||
|
r->BufferDirections[i] = BufferDirection_Recv;
|
||||||
|
else
|
||||||
|
r->BufferDirections[i] = BufferDirection_Exch;
|
||||||
|
}
|
||||||
|
|
||||||
|
r->NumBuffers = num_bufs;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries the size of an IPC pointer buffer.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @param size Output variable in which to store the size.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
|
||||||
|
buf[0] = IpcCommandType_Control;
|
||||||
|
buf[1] = 8;
|
||||||
|
buf[2] = 0;
|
||||||
|
buf[3] = 0;
|
||||||
|
buf[4] = SFCI_MAGIC;
|
||||||
|
buf[5] = 0;
|
||||||
|
buf[6] = 3;
|
||||||
|
buf[7] = 0;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(session);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct ipcQueryPointerBufferSizeResponse {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u32 size;
|
||||||
|
} *raw = (struct ipcQueryPointerBufferSizeResponse*)r.Raw;
|
||||||
|
|
||||||
|
rc = raw->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*size = raw->size & 0xffff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes the IPC session with proper clean up.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcCloseSession(Handle session) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
buf[0] = IpcCommandType_Close;
|
||||||
|
buf[1] = 0;
|
||||||
|
return ipcDispatch(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clones an IPC session.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @param unk Unknown.
|
||||||
|
* @param new_session_out Output cloned IPC session handle.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcCloneSession(Handle session, u32 unk, Handle* new_session_out) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
|
||||||
|
buf[0] = IpcCommandType_Control;
|
||||||
|
buf[1] = 9;
|
||||||
|
buf[2] = 0;
|
||||||
|
buf[3] = 0;
|
||||||
|
buf[4] = SFCI_MAGIC;
|
||||||
|
buf[5] = 0;
|
||||||
|
buf[6] = 4;
|
||||||
|
buf[7] = 0;
|
||||||
|
buf[8] = unk;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(session);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct ipcCloneSessionResponse {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
} *raw = (struct ipcCloneSessionResponse*)r.Raw;
|
||||||
|
|
||||||
|
rc = raw->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc) && new_session_out) {
|
||||||
|
*new_session_out = r.Handles[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
///@}
|
||||||
|
|
||||||
|
///@name IPC domain handling
|
||||||
|
///@{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts an IPC session handle into a domain.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @param object_id_out Output variable in which to store the object ID.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) {
|
||||||
|
u32* buf = (u32*)armGetTls();
|
||||||
|
|
||||||
|
buf[0] = IpcCommandType_Control;
|
||||||
|
buf[1] = 8;
|
||||||
|
buf[4] = SFCI_MAGIC;
|
||||||
|
buf[5] = 0;
|
||||||
|
buf[6] = 0;
|
||||||
|
buf[7] = 0;
|
||||||
|
|
||||||
|
Result rc = ipcDispatch(session);
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
IpcParsedCommand r;
|
||||||
|
ipcParse(&r);
|
||||||
|
|
||||||
|
struct ipcConvertSessionToDomainResponse {
|
||||||
|
u64 magic;
|
||||||
|
u64 result;
|
||||||
|
u32 object_id;
|
||||||
|
} *raw = (struct ipcConvertSessionToDomainResponse*)r.Raw;
|
||||||
|
|
||||||
|
rc = raw->result;
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*object_id_out = raw->object_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Adds an object ID to be sent through an IPC domain command structure.
|
||||||
|
* @param cmd IPC domain command structure.
|
||||||
|
* @param object_id Object ID to send.
|
||||||
|
*/
|
||||||
|
static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) {
|
||||||
|
cmd->ObjectIds[cmd->NumObjectIds++] = object_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Prepares the header of an IPC command structure (domain version).
|
||||||
|
* @param cmd IPC command structure.
|
||||||
|
* @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request
|
||||||
|
* @param object_id Domain object ID.
|
||||||
|
* @return Pointer to the raw embedded data structure in the request, ready to be filled out.
|
||||||
|
*/
|
||||||
|
static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) {
|
||||||
|
void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader) + cmd->NumObjectIds*sizeof(u32));
|
||||||
|
DomainMessageHeader* hdr = (DomainMessageHeader*) raw;
|
||||||
|
u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw);
|
||||||
|
|
||||||
|
hdr->Type = DomainMessageType_SendMessage;
|
||||||
|
hdr->NumObjectIds = (u8)cmd->NumObjectIds;
|
||||||
|
hdr->Length = sizeof_raw;
|
||||||
|
hdr->ThisObjectId = object_id;
|
||||||
|
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < cmd->NumObjectIds; i++)
|
||||||
|
object_ids[i] = cmd->ObjectIds[i];
|
||||||
|
return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse an IPC command request into an IPC parsed command structure (domain version).
|
||||||
|
* @param r IPC parsed command structure to fill in.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcParseDomainRequest(IpcParsedCommand* r) {
|
||||||
|
Result rc = ipcParse(r);
|
||||||
|
DomainMessageHeader *hdr;
|
||||||
|
u32 *object_ids;
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
hdr = (DomainMessageHeader*) r->Raw;
|
||||||
|
object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length);
|
||||||
|
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader));
|
||||||
|
|
||||||
|
r->IsDomainRequest = true;
|
||||||
|
r->InMessageType = (DomainMessageType)(hdr->Type);
|
||||||
|
switch (r->InMessageType) {
|
||||||
|
case DomainMessageType_SendMessage:
|
||||||
|
case DomainMessageType_Close:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType);
|
||||||
|
}
|
||||||
|
|
||||||
|
r->InThisObjectId = hdr->ThisObjectId;
|
||||||
|
r->InNumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
|
||||||
|
if ((uintptr_t)object_ids + sizeof(u32) * r->InNumObjectIds - (uintptr_t)armGetTls() >= 0x100) {
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds);
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < r->InNumObjectIds; i++)
|
||||||
|
r->InObjectIds[i] = object_ids[i];
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse an IPC command response into an IPC parsed command structure (domain version).
|
||||||
|
* @param r IPC parsed command structure to fill in.
|
||||||
|
* @param sizeof_raw Size in bytes of the raw data structure.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcParseDomainResponse(IpcParsedCommand* r, size_t sizeof_raw) {
|
||||||
|
Result rc = ipcParse(r);
|
||||||
|
DomainResponseHeader *hdr;
|
||||||
|
u32 *object_ids;
|
||||||
|
if(R_FAILED(rc))
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
hdr = (DomainResponseHeader*) r->Raw;
|
||||||
|
r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainResponseHeader));
|
||||||
|
object_ids = (u32*)(((uintptr_t) r->Raw) + sizeof_raw);//Official sw doesn't align this.
|
||||||
|
|
||||||
|
r->IsDomainResponse = true;
|
||||||
|
|
||||||
|
r->OutNumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds;
|
||||||
|
if ((uintptr_t)object_ids + sizeof(u32) * r->OutNumObjectIds - (uintptr_t)armGetTls() >= 0x100) {
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds);
|
||||||
|
}
|
||||||
|
for(size_t i = 0; i < r->OutNumObjectIds; i++)
|
||||||
|
r->OutObjectIds[i] = object_ids[i];
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Closes a domain object by ID.
|
||||||
|
* @param session IPC session handle.
|
||||||
|
* @param object_id ID of the object to close.
|
||||||
|
* @return Result code.
|
||||||
|
*/
|
||||||
|
static inline Result ipcCloseObjectById(Handle session, u32 object_id) {
|
||||||
|
IpcCommand c;
|
||||||
|
DomainMessageHeader* hdr;
|
||||||
|
|
||||||
|
ipcInitialize(&c);
|
||||||
|
hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader));
|
||||||
|
|
||||||
|
hdr->Type = DomainMessageType_Close;
|
||||||
|
hdr->NumObjectIds = 0;
|
||||||
|
hdr->Length = 0;
|
||||||
|
hdr->ThisObjectId = object_id;
|
||||||
|
hdr->Pad[0] = hdr->Pad[1] = 0;
|
||||||
|
|
||||||
|
return ipcDispatch(session); // this command has no associated response
|
||||||
|
}
|
||||||
|
|
||||||
|
///@}
|
||||||
41
Source/sys-clk/common/include/memmem.h
Normal file
41
Source/sys-clk/common/include/memmem.h
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Roy Merkel
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MEMMEM_IMPL_H
|
||||||
|
#define MEMMEM_IMPL_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void *memmem_impl(const void *haystack, size_t haystacklen,
|
||||||
|
const void *needle, size_t needlelen);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||||
*
|
*
|
||||||
|
* Copyright (c) Linux 4 Tegra & Linux 4 Switch contributors
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
* version 2, as published by the Free Software Foundation.
|
* version 2, as published by the Free Software Foundation.
|
||||||
@@ -12,9 +14,8 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
@@ -310,6 +311,9 @@
|
|||||||
#define EMC_PMACRO_CMD_CTRL_1_0 0x784
|
#define EMC_PMACRO_CMD_CTRL_1_0 0x784
|
||||||
#define EMC_PMACRO_CMD_CTRL_2_0 0x788
|
#define EMC_PMACRO_CMD_CTRL_2_0 0x788
|
||||||
|
|
||||||
|
#define MC_REGISTER_BASE 0x70019000
|
||||||
|
#define MC_REGISTER_REGION_SIZE 0x1000
|
||||||
|
|
||||||
#define MC_INTSTATUS_0 0x000
|
#define MC_INTSTATUS_0 0x000
|
||||||
#define MC_INTMASK_0 0x004
|
#define MC_INTMASK_0 0x004
|
||||||
#define MC_ERR_STATUS_0 0x008
|
#define MC_ERR_STATUS_0 0x008
|
||||||
@@ -489,4 +493,35 @@
|
|||||||
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xBEC
|
#define MC_EMEM_ARB_DHYST_TIMEOUT_UTIL_7 0xBEC
|
||||||
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_0 0xC00
|
#define MC_ERR_GENERALIZED_CARVEOUT_STATUS_0 0xC00
|
||||||
#define MC_SECURITY_CARVEOUT2_BOM_0 0xC5C
|
#define MC_SECURITY_CARVEOUT2_BOM_0 0xC5C
|
||||||
#define MC_SECURITY_CARVEOUT3_BOM_0 0xCAC
|
#define MC_SECURITY_CARVEOUT3_BOM_0 0xCAC
|
||||||
|
|
||||||
|
#define CLDVFS_REGION_BASE 0x70110000
|
||||||
|
#define CLDVFS_REGION_SIZE 0x1000
|
||||||
|
#define CL_DVFS_CTRL_0 0x0
|
||||||
|
#define CL_DVFS_CONFIG_0 0x4
|
||||||
|
#define CL_DVFS_PARAMS_0 0x8
|
||||||
|
#define CL_DVFS_TUNE0_0 0xC
|
||||||
|
#define CL_DVFS_TUNE1_0 0x10
|
||||||
|
#define CL_DVFS_FREQ_REQ_0 0x14
|
||||||
|
#define CL_DVFS_SCALE_RAMP_0 0x18
|
||||||
|
#define CL_DVFS_DROOP_CTRL_0 0x1C
|
||||||
|
#define CL_DVFS_OUTPUT_CFG_0 0x20
|
||||||
|
#define CL_DVFS_OUTPUT_FORCE_0 0x24
|
||||||
|
#define CL_DVFS_MONITOR_CTRL_0 0x28
|
||||||
|
#define CL_DVFS_MONITOR_DATA_0 0x2C
|
||||||
|
#define CL_DVFS_I2C_CFG_0 0x40
|
||||||
|
#define CL_DVFS_I2C_VDD_REG_ADDR_0 0x44
|
||||||
|
#define CL_DVFS_I2C_STS_0 0x48
|
||||||
|
#define CL_DVFS_INTR_STS_0 0x5C
|
||||||
|
#define CL_DVFS_INTR_EN_0 0x60
|
||||||
|
#define DVFS_DFLL_THROTTLE_CTRL_0 0x64
|
||||||
|
#define DVFS_DFLL_THROTTLE_LIGHT_0 0x68
|
||||||
|
#define DVFS_DFLL_THROTTLE_MEDIUM_0 0x6C
|
||||||
|
#define DVFS_DFLL_THROTTLE_HEAVY_0 0x70
|
||||||
|
#define DVFS_CC4_HVC_0 0x74
|
||||||
|
#define CL_DVFS_MONITOR_DATA_0 0x2C
|
||||||
|
#define CL_DVFS_I2C_CFG_0 0x40
|
||||||
|
#define CL_DVFS_I2C_VDD_REG_ADDR_0 0x44
|
||||||
|
#define CL_DVFS_I2C_STS_0 0x48
|
||||||
|
#define CL_DVFS_INTR_STS_0 0x5C
|
||||||
|
#define CL_DVFS_I2C_CLK_DIVISOR_REGISTER_0 0x16C
|
||||||
|
|||||||
@@ -34,3 +34,5 @@ void rgltrCloseSession(RgltrSession* session);
|
|||||||
Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt);
|
Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt);
|
||||||
Result rgltrGetPowerModuleNumLimit(u32 *out);
|
Result rgltrGetPowerModuleNumLimit(u32 *out);
|
||||||
Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out);
|
Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out);
|
||||||
|
Result rgltrRequestVoltage(RgltrSession* session, u32 microvolt);
|
||||||
|
Result rgltrCancelVoltageRequest(RgltrSession* session);
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -102,22 +102,12 @@ typedef enum
|
|||||||
SysClkPartLoad_EMC = 0,
|
SysClkPartLoad_EMC = 0,
|
||||||
SysClkPartLoad_EMCCpu,
|
SysClkPartLoad_EMCCpu,
|
||||||
HocClkPartLoad_GPU,
|
HocClkPartLoad_GPU,
|
||||||
HocClkPartLoad_CPUAvg,
|
HocClkPartLoad_CPUMax,
|
||||||
HocClkPartLoad_BAT,
|
HocClkPartLoad_BAT,
|
||||||
HocClkPartLoad_FAN,
|
HocClkPartLoad_FAN,
|
||||||
SysClkPartLoad_EnumMax
|
SysClkPartLoad_EnumMax
|
||||||
} SysClkPartLoad;
|
} SysClkPartLoad;
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
ReverseNX_NotFound = 0,
|
|
||||||
ReverseNX_SystemDefault = 0,
|
|
||||||
ReverseNX_Handheld,
|
|
||||||
ReverseNX_Docked,
|
|
||||||
} ReverseNXMode;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
HorizonOCSpeedo_CPU = 0,
|
HorizonOCSpeedo_CPU = 0,
|
||||||
HorizonOCSpeedo_GPU,
|
HorizonOCSpeedo_GPU,
|
||||||
@@ -132,6 +122,46 @@ typedef enum {
|
|||||||
GPUUVLevel_EnumMax,
|
GPUUVLevel_EnumMax,
|
||||||
} GPUUndervoltLevel;
|
} GPUUndervoltLevel;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DVFSMode_Disabled = 0,
|
||||||
|
DVFSMode_Hijack,
|
||||||
|
// DVFSMode_OfficialService,
|
||||||
|
// DVFSMode_Hack,
|
||||||
|
DVFSMode_EnumMax,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GpuSchedulingMode_DoNotOverride = 0,
|
||||||
|
GpuSchedulingMode_Enabled,
|
||||||
|
GpuSchedulingMode_Disabled,
|
||||||
|
GpuSchedulingMode_EnumMax,
|
||||||
|
} GpuSchedulingMode;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GpuSchedulingOverrideMethod_Ini = 0,
|
||||||
|
GpuSchedulingOverrideMethod_NvService,
|
||||||
|
GpuSchedulingOverrideMethod_EnumMax,
|
||||||
|
} GpuSchedulingOverrideMethod;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GovernorState_DoNotOverride = 0,
|
||||||
|
GovernorState_Disabled,
|
||||||
|
GovernorState_Enabled_CpuGpuVrr,
|
||||||
|
GovernorState_Enabled_CpuVrr,
|
||||||
|
GovernorState_Enabled_GpuVrr,
|
||||||
|
GovernorState_Enabled_CpuGpu,
|
||||||
|
GovernorState_Enabled_Cpu,
|
||||||
|
GovernorState_Enabled_Gpu,
|
||||||
|
GovernorState_Enabled_Vrr,
|
||||||
|
GovernorState_EnumMax,
|
||||||
|
} GovernorState;
|
||||||
|
typedef enum {
|
||||||
|
RamDisplayMode_VDD2VDDQ = 0,
|
||||||
|
RamDisplayMode_VDD2Usage,
|
||||||
|
RamDisplayMode_VDDQUsage,
|
||||||
|
RamDisplayMode_EnumMax,
|
||||||
|
} RamDisplayMode;
|
||||||
|
|
||||||
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
|
#define SYSCLK_ENUM_VALID(n, v) ((v) < n##_EnumMax)
|
||||||
|
|
||||||
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
|
static inline const char* sysclkFormatModule(SysClkModule module, bool pretty)
|
||||||
|
|||||||
@@ -48,11 +48,8 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles);
|
|||||||
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues);
|
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues);
|
||||||
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues);
|
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues);
|
||||||
Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* outCount);
|
Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* outCount);
|
||||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode);
|
|
||||||
Result hocClkIpcSetKipData();
|
Result hocClkIpcSetKipData();
|
||||||
Result hocClkIpcGetKipData();
|
Result hocClkIpcGetKipData();
|
||||||
Result hocClkIpcUpdateEmcRegs();
|
|
||||||
Result hocClkIpcCalculateGpuVmin();
|
|
||||||
|
|
||||||
static inline Result sysclkIpcRemoveOverride(SysClkModule module)
|
static inline Result sysclkIpcRemoveOverride(SysClkModule module)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,10 +43,13 @@ typedef struct
|
|||||||
uint32_t voltages[HocClkVoltage_EnumMax];
|
uint32_t voltages[HocClkVoltage_EnumMax];
|
||||||
u16 speedos[HorizonOCSpeedo_EnumMax];
|
u16 speedos[HorizonOCSpeedo_EnumMax];
|
||||||
u16 iddq[HorizonOCSpeedo_EnumMax];
|
u16 iddq[HorizonOCSpeedo_EnumMax];
|
||||||
|
GpuSchedulingMode gpuSchedulingMode;
|
||||||
|
bool isSysDockInstalled;
|
||||||
|
bool isSaltyNXInstalled;
|
||||||
u8 maxDisplayFreq;
|
u8 maxDisplayFreq;
|
||||||
u8 fps;
|
|
||||||
u8 dramID;
|
u8 dramID;
|
||||||
bool isDram8GB;
|
bool isDram8GB;
|
||||||
|
u8 fps;
|
||||||
} SysClkContext;
|
} SysClkContext;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -51,13 +51,21 @@ typedef enum {
|
|||||||
|
|
||||||
HocClkConfigValue_LiteTDPLimit,
|
HocClkConfigValue_LiteTDPLimit,
|
||||||
|
|
||||||
HocClkConfigValue_EnforceBoardLimit,
|
|
||||||
|
|
||||||
HorizonOCConfigValue_BatteryChargeCurrent,
|
HorizonOCConfigValue_BatteryChargeCurrent,
|
||||||
|
|
||||||
HorizonOCConfigValue_OverwriteRefreshRate,
|
HorizonOCConfigValue_OverwriteRefreshRate,
|
||||||
HorizonOCConfigValue_EnableUnsafeDisplayFreqs,
|
HorizonOCConfigValue_EnableUnsafeDisplayFreqs,
|
||||||
HocClkConfigValue_FixCpuVoltBug,
|
|
||||||
|
HorizonOCConfigValue_DVFSMode,
|
||||||
|
HorizonOCConfigValue_DVFSOffset,
|
||||||
|
HorizonOCConfigValue_LiveCpuUv,
|
||||||
|
HorizonOCConfigValue_EnableExperimentalSettings,
|
||||||
|
|
||||||
|
HorizonOCConfigValue_GPUScheduling,
|
||||||
|
HorizonOCConfigValue_GPUSchedulingMethod,
|
||||||
|
|
||||||
|
HorizonOCConfigValue_RAMVoltUsageDisplayMode,
|
||||||
|
HorizonOCConfigValue_CpuGovernorMinimumFreq,
|
||||||
|
|
||||||
KipConfigValue_custRev,
|
KipConfigValue_custRev,
|
||||||
// KipConfigValue_mtcConf,
|
// KipConfigValue_mtcConf,
|
||||||
@@ -65,6 +73,8 @@ typedef enum {
|
|||||||
|
|
||||||
KipConfigValue_commonEmcMemVolt,
|
KipConfigValue_commonEmcMemVolt,
|
||||||
KipConfigValue_eristaEmcMaxClock,
|
KipConfigValue_eristaEmcMaxClock,
|
||||||
|
KipConfigValue_eristaEmcMaxClock1,
|
||||||
|
KipConfigValue_eristaEmcMaxClock2,
|
||||||
KipConfigValue_marikoEmcMaxClock,
|
KipConfigValue_marikoEmcMaxClock,
|
||||||
KipConfigValue_marikoEmcVddqVolt,
|
KipConfigValue_marikoEmcVddqVolt,
|
||||||
KipConfigValue_emcDvbShift,
|
KipConfigValue_emcDvbShift,
|
||||||
@@ -158,6 +168,9 @@ typedef enum {
|
|||||||
KipConfigValue_g_volt_e_1036800,
|
KipConfigValue_g_volt_e_1036800,
|
||||||
KipConfigValue_g_volt_e_1075200,
|
KipConfigValue_g_volt_e_1075200,
|
||||||
|
|
||||||
|
KipConfigValue_t6_tRTW_fine_tune,
|
||||||
|
KipConfigValue_t7_tWTR_fine_tune,
|
||||||
|
|
||||||
KipCrc32,
|
KipCrc32,
|
||||||
HocClkConfigValue_IsFirstLoad,
|
HocClkConfigValue_IsFirstLoad,
|
||||||
SysClkConfigValue_EnumMax,
|
SysClkConfigValue_EnumMax,
|
||||||
@@ -188,7 +201,7 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
|||||||
return pretty ? "Overwrite Boost Mode" : "ow_boost";
|
return pretty ? "Overwrite Boost Mode" : "ow_boost";
|
||||||
|
|
||||||
case HocClkConfigValue_EristaMaxCpuClock:
|
case HocClkConfigValue_EristaMaxCpuClock:
|
||||||
return pretty ? "CPU Max Display Clock" : "cpu_max_e";
|
return pretty ? "CPU Max Clock" : "cpu_max_e";
|
||||||
|
|
||||||
case HocClkConfigValue_MarikoMaxCpuClock:
|
case HocClkConfigValue_MarikoMaxCpuClock:
|
||||||
return pretty ? "CPU Max Display Clock" : "cpu_max_m";
|
return pretty ? "CPU Max Display Clock" : "cpu_max_m";
|
||||||
@@ -208,21 +221,37 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
|||||||
case HocClkConfigValue_LiteTDPLimit:
|
case HocClkConfigValue_LiteTDPLimit:
|
||||||
return pretty ? "Handheld TDP Limit" : "tdp_limit_l";
|
return pretty ? "Handheld TDP Limit" : "tdp_limit_l";
|
||||||
|
|
||||||
case HocClkConfigValue_EnforceBoardLimit:
|
|
||||||
return pretty ? "Enforce Board Limit" : "enforce_board_limit";
|
|
||||||
|
|
||||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||||
return pretty ? "Battery Charge Current" : "bat_charge_current";
|
return pretty ? "Battery Charge Current" : "bat_charge_current";
|
||||||
|
|
||||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||||
return pretty ? "Display Refresh Rate Changing" : "drr_changing";
|
return pretty ? "Display Refresh Rate Changing" : "drr_changing";
|
||||||
|
|
||||||
case HocClkConfigValue_FixCpuVoltBug:
|
|
||||||
return pretty ? "Fix CPU Volt Bug" : "cpu_volt_bugfix";
|
|
||||||
|
|
||||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||||
return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe";
|
return pretty ? "Enable Unsafe Display Frequencies" : "drr_unsafe";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_DVFSMode:
|
||||||
|
return pretty ? "DVFS Mode" : "dvfs_mode";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_DVFSOffset:
|
||||||
|
return pretty ? "DVFS Offset" : "dvfs_offset";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_GPUScheduling:
|
||||||
|
return pretty ? "GPU Scheduling" : "gpu_scheduling";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||||
|
return pretty ? "GPU Scheduling Method" : "gpu_sched_method";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_LiveCpuUv:
|
||||||
|
return pretty ? "Live CPU Undervolt" : "live_cpu_uv";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_EnableExperimentalSettings:
|
||||||
|
return pretty ? "Enable Experimental Settings" : "enable_experimental_settings";
|
||||||
|
|
||||||
|
case HorizonOCConfigValue_RAMVoltUsageDisplayMode:
|
||||||
|
return pretty ? "RAM Voltage / Usage Display Mode" : "ram_volt_usage_display_mode";
|
||||||
|
case HorizonOCConfigValue_CpuGovernorMinimumFreq:
|
||||||
|
return pretty ? "CPU Governor Minimum Frequency" : "cpu_gov_min_freq";
|
||||||
// KIP config values
|
// KIP config values
|
||||||
case KipConfigValue_custRev:
|
case KipConfigValue_custRev:
|
||||||
return pretty ? "Custom Revision" : "kip_cust_rev";
|
return pretty ? "Custom Revision" : "kip_cust_rev";
|
||||||
@@ -235,7 +264,11 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
|||||||
case KipConfigValue_commonEmcMemVolt:
|
case KipConfigValue_commonEmcMemVolt:
|
||||||
return pretty ? "Common EMC/MEM Voltage" : "common_emc_mem_volt";
|
return pretty ? "Common EMC/MEM Voltage" : "common_emc_mem_volt";
|
||||||
case KipConfigValue_eristaEmcMaxClock:
|
case KipConfigValue_eristaEmcMaxClock:
|
||||||
return pretty ? "Erista EMC Max Clock" : "erista_emc_max_clock";
|
return pretty ? "Erista EMC Max Clock 1" : "erista_emc_max_clock";
|
||||||
|
case KipConfigValue_eristaEmcMaxClock1:
|
||||||
|
return pretty ? "Erista EMC Max Clock 2" : "erista_emc_max_clock1";
|
||||||
|
case KipConfigValue_eristaEmcMaxClock2:
|
||||||
|
return pretty ? "Erista EMC Max Clock 3" : "erista_emc_max_clock2";
|
||||||
case KipConfigValue_marikoEmcMaxClock:
|
case KipConfigValue_marikoEmcMaxClock:
|
||||||
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
|
return pretty ? "Mariko EMC Max Clock" : "mariko_emc_max_clock";
|
||||||
case KipConfigValue_marikoEmcVddqVolt:
|
case KipConfigValue_marikoEmcVddqVolt:
|
||||||
@@ -370,6 +403,8 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
|||||||
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
|
case KipConfigValue_g_volt_e_998400: return pretty ? "Erista GPU Volt 998 MHz" : "g_volt_e_998400";
|
||||||
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
|
case KipConfigValue_g_volt_e_1036800: return pretty ? "Erista GPU Volt 1036 MHz" : "g_volt_e_1036800";
|
||||||
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
|
case KipConfigValue_g_volt_e_1075200: return pretty ? "Erista GPU Volt 1075 MHz" : "g_volt_e_1075200";
|
||||||
|
case KipConfigValue_t6_tRTW_fine_tune: return pretty ? "t6 - tRTW Fine Tune" : "t6_tRTW_fine_fune";
|
||||||
|
case KipConfigValue_t7_tWTR_fine_tune: return pretty ? "t7 - tWTR Fine Tune" : "t7_tWTR_fine_tune";
|
||||||
case KipCrc32:
|
case KipCrc32:
|
||||||
return pretty ? "CRC32" : "crc32";
|
return pretty ? "CRC32" : "crc32";
|
||||||
case HocClkConfigValue_IsFirstLoad:
|
case HocClkConfigValue_IsFirstLoad:
|
||||||
@@ -394,6 +429,9 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
|||||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||||
|
case HorizonOCConfigValue_GPUScheduling:
|
||||||
|
case HorizonOCConfigValue_LiveCpuUv:
|
||||||
|
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||||
return 0ULL;
|
return 0ULL;
|
||||||
case HocClkConfigValue_EristaMaxCpuClock:
|
case HocClkConfigValue_EristaMaxCpuClock:
|
||||||
return 1785ULL;
|
return 1785ULL;
|
||||||
@@ -403,9 +441,8 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
|||||||
|
|
||||||
case HocClkConfigValue_ThermalThrottle:
|
case HocClkConfigValue_ThermalThrottle:
|
||||||
case HocClkConfigValue_HandheldTDP:
|
case HocClkConfigValue_HandheldTDP:
|
||||||
case HocClkConfigValue_EnforceBoardLimit:
|
|
||||||
case HocClkConfigValue_FixCpuVoltBug:
|
|
||||||
case HocClkConfigValue_IsFirstLoad:
|
case HocClkConfigValue_IsFirstLoad:
|
||||||
|
case HorizonOCConfigValue_DVFSMode:
|
||||||
return 1ULL;
|
return 1ULL;
|
||||||
case HocClkConfigValue_ThermalThrottleThreshold:
|
case HocClkConfigValue_ThermalThrottleThreshold:
|
||||||
return 70ULL;
|
return 70ULL;
|
||||||
@@ -413,6 +450,8 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
|||||||
return 9600ULL; // 8600mW will trigger on erista stock, so raise it a bit
|
return 9600ULL; // 8600mW will trigger on erista stock, so raise it a bit
|
||||||
case HocClkConfigValue_LiteTDPLimit:
|
case HocClkConfigValue_LiteTDPLimit:
|
||||||
return 6400ULL; // 0.5C
|
return 6400ULL; // 0.5C
|
||||||
|
case HorizonOCConfigValue_CpuGovernorMinimumFreq:
|
||||||
|
return 612ULL; // 612MHz
|
||||||
default:
|
default:
|
||||||
return 0ULL;
|
return 0ULL;
|
||||||
}
|
}
|
||||||
@@ -429,7 +468,7 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
|||||||
case HocClkConfigValue_LiteTDPLimit:
|
case HocClkConfigValue_LiteTDPLimit:
|
||||||
case SysClkConfigValue_PollingIntervalMs:
|
case SysClkConfigValue_PollingIntervalMs:
|
||||||
return input > 0;
|
return input > 0;
|
||||||
|
|
||||||
case SysClkConfigValue_TempLogIntervalMs:
|
case SysClkConfigValue_TempLogIntervalMs:
|
||||||
case SysClkConfigValue_FreqLogIntervalMs:
|
case SysClkConfigValue_FreqLogIntervalMs:
|
||||||
case SysClkConfigValue_PowerLogIntervalMs:
|
case SysClkConfigValue_PowerLogIntervalMs:
|
||||||
@@ -438,18 +477,21 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
|||||||
case HocClkConfigValue_OverwriteBoostMode:
|
case HocClkConfigValue_OverwriteBoostMode:
|
||||||
case HocClkConfigValue_ThermalThrottle:
|
case HocClkConfigValue_ThermalThrottle:
|
||||||
case HocClkConfigValue_HandheldTDP:
|
case HocClkConfigValue_HandheldTDP:
|
||||||
case HocClkConfigValue_EnforceBoardLimit:
|
|
||||||
case HorizonOCConfigValue_OverwriteRefreshRate:
|
case HorizonOCConfigValue_OverwriteRefreshRate:
|
||||||
case HocClkConfigValue_FixCpuVoltBug:
|
|
||||||
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
case HorizonOCConfigValue_EnableUnsafeDisplayFreqs:
|
||||||
case HocClkConfigValue_IsFirstLoad:
|
case HocClkConfigValue_IsFirstLoad:
|
||||||
|
case HorizonOCConfigValue_EnableExperimentalSettings:
|
||||||
|
case HorizonOCConfigValue_LiveCpuUv:
|
||||||
|
case HorizonOCConfigValue_GPUSchedulingMethod:
|
||||||
return (input & 0x1) == input;
|
return (input & 0x1) == input;
|
||||||
|
|
||||||
case KipConfigValue_custRev:
|
case KipConfigValue_custRev:
|
||||||
// case KipConfigValue_mtcConf:
|
// case KipConfigValue_mtcConf:
|
||||||
case KipConfigValue_hpMode:
|
case KipConfigValue_hpMode:
|
||||||
case KipConfigValue_commonEmcMemVolt:
|
case KipConfigValue_commonEmcMemVolt:
|
||||||
case KipConfigValue_eristaEmcMaxClock:
|
case KipConfigValue_eristaEmcMaxClock:
|
||||||
|
case KipConfigValue_eristaEmcMaxClock1:
|
||||||
|
case KipConfigValue_eristaEmcMaxClock2:
|
||||||
case KipConfigValue_marikoEmcMaxClock:
|
case KipConfigValue_marikoEmcMaxClock:
|
||||||
case KipConfigValue_marikoEmcVddqVolt:
|
case KipConfigValue_marikoEmcVddqVolt:
|
||||||
case KipConfigValue_emcDvbShift:
|
case KipConfigValue_emcDvbShift:
|
||||||
@@ -534,7 +576,14 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
|||||||
case KipConfigValue_g_volt_e_1075200:
|
case KipConfigValue_g_volt_e_1075200:
|
||||||
case KipConfigValue_eristaCpuVmin:
|
case KipConfigValue_eristaCpuVmin:
|
||||||
case KipConfigValue_eristaCpuUnlock:
|
case KipConfigValue_eristaCpuUnlock:
|
||||||
|
case KipConfigValue_t6_tRTW_fine_tune:
|
||||||
|
case KipConfigValue_t7_tWTR_fine_tune:
|
||||||
case KipCrc32:
|
case KipCrc32:
|
||||||
|
case HorizonOCConfigValue_DVFSMode:
|
||||||
|
case HorizonOCConfigValue_DVFSOffset:
|
||||||
|
case HorizonOCConfigValue_GPUScheduling:
|
||||||
|
case HorizonOCConfigValue_RAMVoltUsageDisplayMode:
|
||||||
|
case HorizonOCConfigValue_CpuGovernorMinimumFreq:
|
||||||
return true;
|
return true;
|
||||||
case HorizonOCConfigValue_BatteryChargeCurrent:
|
case HorizonOCConfigValue_BatteryChargeCurrent:
|
||||||
return ((input >= 1024) && (input <= 3072)) || !input;
|
return ((input >= 1024) && (input <= 3072)) || !input;
|
||||||
|
|||||||
@@ -48,11 +48,8 @@ enum SysClkIpcCmd
|
|||||||
SysClkIpcCmd_GetConfigValues = 9,
|
SysClkIpcCmd_GetConfigValues = 9,
|
||||||
SysClkIpcCmd_SetConfigValues = 10,
|
SysClkIpcCmd_SetConfigValues = 10,
|
||||||
SysClkIpcCmd_GetFreqList = 11,
|
SysClkIpcCmd_GetFreqList = 11,
|
||||||
SysClkIpcCmd_SetReverseNXRTMode = 12,
|
HocClkIpcCmd_SetKipData = 12,
|
||||||
HocClkIpcCmd_SetKipData = 13,
|
HocClkIpcCmd_GetKipData = 13,
|
||||||
HocClkIpcCmd_GetKipData = 14,
|
|
||||||
HocClkIpcCmd_UpdateEmcRegs = 15,
|
|
||||||
HocClkIpcCmd_CalculateGpuVmin = 16,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -79,14 +79,17 @@ Result sysclkIpcGetAPIVersion(u32* out_ver)
|
|||||||
Result sysclkIpcGetVersionString(char* out, size_t len)
|
Result sysclkIpcGetVersionString(char* out, size_t len)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetVersionString,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetVersionString,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out, len}},
|
.buffers = {{out, len}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcGetCurrentContext(SysClkContext* out_context)
|
Result sysclkIpcGetCurrentContext(SysClkContext* out_context)
|
||||||
{
|
{
|
||||||
return serviceDispatchOut(&g_sysclkSrv, SysClkIpcCmd_GetCurrentContext, *out_context);
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetCurrentContext,
|
||||||
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
|
.buffers = {{out_context, sizeof(SysClkContext)}},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcGetProfileCount(u64 tid, u8* out_count)
|
Result sysclkIpcGetProfileCount(u64 tid, u8* out_count)
|
||||||
@@ -112,7 +115,7 @@ Result sysclkIpcSetOverride(SysClkModule module, u32 hz)
|
|||||||
Result sysclkIpcGetProfiles(u64 tid, SysClkTitleProfileList* out_profiles)
|
Result sysclkIpcGetProfiles(u64 tid, SysClkTitleProfileList* out_profiles)
|
||||||
{
|
{
|
||||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_GetProfiles, tid,
|
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_GetProfiles, tid,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out_profiles, sizeof(SysClkTitleProfileList)}},
|
.buffers = {{out_profiles, sizeof(SysClkTitleProfileList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -128,7 +131,7 @@ Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles)
|
|||||||
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetConfigValues,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_GetConfigValues,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_Out },
|
||||||
.buffers = {{out_configValues, sizeof(SysClkConfigValueList)}},
|
.buffers = {{out_configValues, sizeof(SysClkConfigValueList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -136,7 +139,7 @@ Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
|
|||||||
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues)
|
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues)
|
||||||
{
|
{
|
||||||
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_SetConfigValues,
|
return serviceDispatch(&g_sysclkSrv, SysClkIpcCmd_SetConfigValues,
|
||||||
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_In },
|
.buffer_attrs = { SfBufferAttr_HipcAutoSelect | SfBufferAttr_In },
|
||||||
.buffers = {{configValues, sizeof(SysClkConfigValueList)}},
|
.buffers = {{configValues, sizeof(SysClkConfigValueList)}},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -153,12 +156,6 @@ Result sysclkIpcGetFreqList(SysClkModule module, u32* list, u32 maxCount, u32* o
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result sysclkIpcSetReverseNXRTMode(ReverseNXMode mode)
|
|
||||||
{
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, SysClkIpcCmd_SetReverseNXRTMode, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Result hocClkIpcSetKipData()
|
Result hocClkIpcSetKipData()
|
||||||
{
|
{
|
||||||
u32 temp = 0;
|
u32 temp = 0;
|
||||||
@@ -169,15 +166,4 @@ Result hocClkIpcGetKipData()
|
|||||||
{
|
{
|
||||||
u32 temp = 0;
|
u32 temp = 0;
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_GetKipData, temp);
|
||||||
}
|
|
||||||
|
|
||||||
Result hocClkIpcUpdateEmcRegs()
|
|
||||||
{
|
|
||||||
u32 temp = 0;
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_UpdateEmcRegs, temp);
|
|
||||||
}
|
|
||||||
Result hocClkIpcCalculateGpuVmin()
|
|
||||||
{
|
|
||||||
u32 temp = 0;
|
|
||||||
return serviceDispatchIn(&g_sysclkSrv, HocClkIpcCmd_CalculateGpuVmin, temp);
|
|
||||||
}
|
}
|
||||||
@@ -29,11 +29,9 @@
|
|||||||
|
|
||||||
#define MAX_REFRESH_RATE 72
|
#define MAX_REFRESH_RATE 72
|
||||||
|
|
||||||
// Configuration
|
|
||||||
static DisplayRefreshConfig g_config = {0};
|
static DisplayRefreshConfig g_config = {0};
|
||||||
static bool g_initialized = false;
|
static bool g_initialized = false;
|
||||||
|
|
||||||
// State
|
|
||||||
static uint8_t g_dockedHighestRefreshRate = 60;
|
static uint8_t g_dockedHighestRefreshRate = 60;
|
||||||
static uint8_t g_dockedLinkRate = 10;
|
static uint8_t g_dockedLinkRate = 10;
|
||||||
static bool g_wasRetroSuperTurnedOff = false;
|
static bool g_wasRetroSuperTurnedOff = false;
|
||||||
@@ -41,11 +39,23 @@ static uint32_t g_lastVActive = 1080;
|
|||||||
static bool g_canChangeRefreshRateDocked = false;
|
static bool g_canChangeRefreshRateDocked = false;
|
||||||
static uint8_t g_lastVActiveSet = 0;
|
static uint8_t g_lastVActiveSet = 0;
|
||||||
|
|
||||||
// Refresh rate tables
|
static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120, 130, 140, 144, 150, 160, 165, 170, 180, 190, 200, 210, 220, 230, 240};
|
||||||
static const uint8_t g_dockedRefreshRates[] = {40, 45, 50, 55, 60, 70, 72, 75, 80, 90, 95, 100, 110, 120};
|
// Calculate with this tool:
|
||||||
static bool g_dockedAllowed[14] = {0};
|
|
||||||
static bool g_dockedAllowed720p[14] = {0};
|
|
||||||
|
|
||||||
|
// https://tomverbeure.github.io/video_timings_calculator?horiz_pixels=1920&vert_pixels=1080&refresh_rate=240&margins=false&interlaced=false&bpc=8&color_fmt=rgb444&video_opt=false&custom_hblank=80&custom_vblank=6
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct {
|
||||||
|
uint16_t hFrontPorch;
|
||||||
|
uint8_t hSyncWidth;
|
||||||
|
uint8_t hBackPorch;
|
||||||
|
uint8_t vFrontPorch;
|
||||||
|
uint8_t vSyncWidth;
|
||||||
|
uint8_t vBackPorch;
|
||||||
|
uint8_t VIC;
|
||||||
|
uint32_t pixelClock_kHz;
|
||||||
|
} DockedTimings;
|
||||||
|
*/
|
||||||
static const DockedTimings g_dockedTimings1080p[] = {
|
static const DockedTimings g_dockedTimings1080p[] = {
|
||||||
{8, 32, 40, 7, 8, 6, 0, 88080}, // 40Hz
|
{8, 32, 40, 7, 8, 6, 0, 88080}, // 40Hz
|
||||||
{8, 32, 40, 9, 8, 6, 0, 99270}, // 45Hz
|
{8, 32, 40, 9, 8, 6, 0, 99270}, // 45Hz
|
||||||
@@ -60,7 +70,22 @@ static const DockedTimings g_dockedTimings1080p[] = {
|
|||||||
{8, 32, 40, 36, 8, 6, 0, 214700}, // 95Hz
|
{8, 32, 40, 36, 8, 6, 0, 214700}, // 95Hz
|
||||||
{528, 44, 148, 4, 5, 36, 64, 297000}, // 100Hz
|
{528, 44, 148, 4, 5, 36, 64, 297000}, // 100Hz
|
||||||
{8, 32, 40, 44, 8, 6, 0, 250360}, // 110Hz
|
{8, 32, 40, 44, 8, 6, 0, 250360}, // 110Hz
|
||||||
{88, 44, 148, 4, 5, 36, 63, 297000} // 120Hz
|
{88, 44, 148, 4, 5, 36, 63, 297000}, // 120Hz
|
||||||
|
{8, 32, 40, 55, 8, 6, 0, 298750}, //130Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 61, 8, 6, 0, 323400}, //140Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 63, 8, 6, 0, 333216}, //144Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 67, 8, 6, 0, 348300}, //150Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 72, 8, 6, 0, 373120}, //160Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 75, 8, 6, 0, 385770}, //165Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 78, 8, 6, 0, 398480}, //170Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 84, 8, 6, 0, 424080}, //180Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 90, 8, 6, 0, 449920}, //190Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 96, 8, 6, 0, 476000}, //200Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 102, 8, 6, 0, 502320}, //210Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 108, 8, 6, 0, 528880}, //220Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 114, 8, 6, 0, 555680}, //230Hz CVT-RBv2
|
||||||
|
{8, 32, 40, 121, 8, 6, 0, 583200}, //240Hz CVT-RBv2
|
||||||
|
// technically you can go to 476hz, but in practice, why would you?
|
||||||
};
|
};
|
||||||
|
|
||||||
static const HandheldTimings g_handheldTimingsRETRO[] = {
|
static const HandheldTimings g_handheldTimingsRETRO[] = {
|
||||||
@@ -73,7 +98,6 @@ static const HandheldTimings g_handheldTimingsRETRO[] = {
|
|||||||
|
|
||||||
static const MinMaxRefreshRate g_handheldModeRefreshRate = {40, 80};
|
static const MinMaxRefreshRate g_handheldModeRefreshRate = {40, 80};
|
||||||
|
|
||||||
// Utility functions
|
|
||||||
static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) {
|
static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) {
|
||||||
for (size_t i = 0; i < sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); i++) {
|
for (size_t i = 0; i < sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]); i++) {
|
||||||
if (g_dockedRefreshRates[i] == refreshRate) return i;
|
if (g_dockedRefreshRates[i] == refreshRate) return i;
|
||||||
@@ -81,15 +105,6 @@ static uint8_t _getDockedRefreshRateIterator(uint32_t refreshRate) {
|
|||||||
return 0xFF;
|
return 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _setDefaultDockedSettings(void) {
|
|
||||||
memset(g_dockedAllowed, 0, sizeof(g_dockedAllowed));
|
|
||||||
g_dockedAllowed[_getDockedRefreshRateIterator(50)] = true;
|
|
||||||
g_dockedAllowed[_getDockedRefreshRateIterator(60)] = true;
|
|
||||||
memset(g_dockedAllowed720p, 0, sizeof(g_dockedAllowed720p));
|
|
||||||
g_dockedAllowed720p[_getDockedRefreshRateIterator(50)] = true;
|
|
||||||
g_dockedAllowed720p[_getDockedRefreshRateIterator(60)] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* value, uint32_t size, uint32_t start) {
|
static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* value, uint32_t size, uint32_t start) {
|
||||||
if (!g_config.dsiVirtAddr || !value || !size) return;
|
if (!g_config.dsiVirtAddr || !value || !size) return;
|
||||||
|
|
||||||
@@ -126,13 +141,14 @@ static void _changeOledElvssSettings(const uint32_t* offsets, const uint32_t* va
|
|||||||
dsi[DSI_VIDEO_MODE_CONTROL] = false;
|
dsi[DSI_VIDEO_MODE_CONTROL] = false;
|
||||||
svcSleepThread(20000000);
|
svcSleepThread(20000000);
|
||||||
}
|
}
|
||||||
|
void DisplayRefresh_SetDockedState(bool isDocked) {
|
||||||
|
g_config.isDocked = isDocked;
|
||||||
|
}
|
||||||
|
|
||||||
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config) {
|
bool DisplayRefresh_Initialize(const DisplayRefreshConfig* config) {
|
||||||
if (!config) return false;
|
if (!config) return false;
|
||||||
|
|
||||||
g_config = *config;
|
g_config = *config;
|
||||||
_setDefaultDockedSettings();
|
|
||||||
g_initialized = true;
|
g_initialized = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -180,69 +196,20 @@ void DisplayRefresh_CorrectOledGamma(uint32_t refresh_rate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p) {
|
void DisplayRefresh_SetAllowedDockedRatesIPC(uint32_t refreshRates, bool is720p) {
|
||||||
struct {
|
// Function kept for API compatibility but does nothing
|
||||||
unsigned int Hz_40: 1;
|
(void)refreshRates;
|
||||||
unsigned int Hz_45: 1;
|
(void)is720p;
|
||||||
unsigned int Hz_50: 1;
|
|
||||||
unsigned int Hz_55: 1;
|
|
||||||
unsigned int Hz_60: 1;
|
|
||||||
unsigned int Hz_70: 1;
|
|
||||||
unsigned int Hz_72: 1;
|
|
||||||
unsigned int Hz_75: 1;
|
|
||||||
unsigned int Hz_80: 1;
|
|
||||||
unsigned int Hz_90: 1;
|
|
||||||
unsigned int Hz_95: 1;
|
|
||||||
unsigned int Hz_100: 1;
|
|
||||||
unsigned int Hz_110: 1;
|
|
||||||
unsigned int Hz_120: 1;
|
|
||||||
unsigned int reserved: 18;
|
|
||||||
} rates;
|
|
||||||
|
|
||||||
memcpy(&rates, &refreshRates, 4);
|
|
||||||
|
|
||||||
bool* target = is720p ? g_dockedAllowed720p : g_dockedAllowed;
|
|
||||||
target[_getDockedRefreshRateIterator(40)] = rates.Hz_40;
|
|
||||||
target[_getDockedRefreshRateIterator(45)] = rates.Hz_45;
|
|
||||||
target[_getDockedRefreshRateIterator(50)] = rates.Hz_50;
|
|
||||||
target[_getDockedRefreshRateIterator(55)] = rates.Hz_55;
|
|
||||||
target[_getDockedRefreshRateIterator(60)] = true;
|
|
||||||
target[_getDockedRefreshRateIterator(70)] = rates.Hz_70;
|
|
||||||
target[_getDockedRefreshRateIterator(72)] = rates.Hz_72;
|
|
||||||
target[_getDockedRefreshRateIterator(75)] = rates.Hz_75;
|
|
||||||
target[_getDockedRefreshRateIterator(80)] = rates.Hz_80;
|
|
||||||
target[_getDockedRefreshRateIterator(90)] = rates.Hz_90;
|
|
||||||
target[_getDockedRefreshRateIterator(95)] = rates.Hz_95;
|
|
||||||
target[_getDockedRefreshRateIterator(100)] = rates.Hz_100;
|
|
||||||
target[_getDockedRefreshRateIterator(110)] = rates.Hz_110;
|
|
||||||
target[_getDockedRefreshRateIterator(120)] = rates.Hz_120;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t DisplayRefresh_GetDockedHighestAllowed(void) {
|
uint8_t DisplayRefresh_GetDockedHighestAllowed(void) {
|
||||||
const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]);
|
return (g_dockedHighestRefreshRate > 60) ? g_dockedHighestRefreshRate : 60;
|
||||||
|
|
||||||
if (g_lastVActive == 1080) {
|
|
||||||
for (int i = numRates - 1; g_dockedRefreshRates[i] > 60; i--) {
|
|
||||||
if (g_dockedAllowed[i])
|
|
||||||
return (g_dockedRefreshRates[i] > g_dockedHighestRefreshRate) ? g_dockedHighestRefreshRate : g_dockedRefreshRates[i];
|
|
||||||
}
|
|
||||||
} else if (g_lastVActive == 720) {
|
|
||||||
for (int i = numRates - 1; g_dockedRefreshRates[i] > 60; i--) {
|
|
||||||
if (g_dockedAllowed720p[i])
|
|
||||||
return (g_dockedRefreshRates[i] > g_dockedHighestRefreshRate) ? g_dockedHighestRefreshRate : g_dockedRefreshRates[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 60;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _getDockedHighestRefreshRate(uint32_t fd_in) {
|
static void _getDockedHighestRefreshRate(uint32_t fd_in) {
|
||||||
uint8_t highestRefreshRate = 60;
|
uint8_t highestRefreshRate = 60;
|
||||||
uint32_t fd = fd_in;
|
uint32_t fd = fd_in;
|
||||||
|
|
||||||
if (!fd && nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
if(!fd) nvOpen(&fd, "/dev/nvdisp-disp1");
|
||||||
g_dockedHighestRefreshRate = 60;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NvdcModeDB2 db2 = {0};
|
NvdcModeDB2 db2 = {0};
|
||||||
int rc = nvIoctl(fd, NVDISP_GET_MODE_DB2, &db2);
|
int rc = nvIoctl(fd, NVDISP_GET_MODE_DB2, &db2);
|
||||||
|
|
||||||
@@ -288,8 +255,8 @@ static void _getDockedHighestRefreshRate(uint32_t fd_in) {
|
|||||||
rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux);
|
rc = nvIoctl(fd, NVDISP_GET_PANEL_DATA, &dpaux);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
g_dockedLinkRate = dpaux.set.link_rate;
|
g_dockedLinkRate = dpaux.set.link_rate;
|
||||||
if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20)
|
// if (display_b.hActive == 1920 && display_b.vActive == 1080 && highestRefreshRate > 75 && dpaux.set.link_rate < 20 && )
|
||||||
highestRefreshRate = 75;
|
// highestRefreshRate = 75;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fd_in) nvClose(fd);
|
if (!fd_in) nvClose(fd);
|
||||||
@@ -403,10 +370,6 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
|||||||
|
|
||||||
if (display_b.vActive != g_lastVActiveSet) {
|
if (display_b.vActive != g_lastVActiveSet) {
|
||||||
g_lastVActiveSet = display_b.vActive;
|
g_lastVActiveSet = display_b.vActive;
|
||||||
if (display_b.vActive != 720 && display_b.vActive != 1080) {
|
|
||||||
memset(g_dockedAllowed, 0, sizeof(g_dockedAllowed));
|
|
||||||
g_dockedAllowed[_getDockedRefreshRateIterator(60)] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch;
|
uint32_t h_total = display_b.hActive + display_b.hFrontPorch + display_b.hSyncWidth + display_b.hBackPorch;
|
||||||
@@ -416,15 +379,13 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
|||||||
int8_t itr = -1;
|
int8_t itr = -1;
|
||||||
const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]);
|
const size_t numRates = sizeof(g_dockedRefreshRates) / sizeof(g_dockedRefreshRates[0]);
|
||||||
|
|
||||||
|
// Find closest matching refresh rate
|
||||||
if ((new_refreshRate <= 60) && ((60 % new_refreshRate) == 0)) {
|
if ((new_refreshRate <= 60) && ((60 % new_refreshRate) == 0)) {
|
||||||
itr = _getDockedRefreshRateIterator(60);
|
itr = _getDockedRefreshRateIterator(60);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itr == -1) {
|
if (itr == -1) {
|
||||||
for (size_t i = 0; i < numRates; i++) {
|
for (size_t i = 0; i < numRates; i++) {
|
||||||
bool* allowed = (display_b.vActive == 720) ? g_dockedAllowed720p : g_dockedAllowed;
|
|
||||||
if (allowed[i] != true) continue;
|
|
||||||
|
|
||||||
uint8_t val = g_dockedRefreshRates[i];
|
uint8_t val = g_dockedRefreshRates[i];
|
||||||
if ((val % new_refreshRate) == 0) {
|
if ((val % new_refreshRate) == 0) {
|
||||||
itr = i;
|
itr = i;
|
||||||
@@ -437,9 +398,8 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
|||||||
if (!g_config.matchLowestDocked) {
|
if (!g_config.matchLowestDocked) {
|
||||||
itr = _getDockedRefreshRateIterator(60);
|
itr = _getDockedRefreshRateIterator(60);
|
||||||
} else {
|
} else {
|
||||||
bool* allowed = (display_b.vActive == 1080) ? g_dockedAllowed : g_dockedAllowed720p;
|
|
||||||
for (size_t i = 0; i < numRates; i++) {
|
for (size_t i = 0; i < numRates; i++) {
|
||||||
if ((allowed[i] == true) && (new_refreshRate < g_dockedRefreshRates[i])) {
|
if (new_refreshRate < g_dockedRefreshRates[i]) {
|
||||||
itr = i;
|
itr = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -449,15 +409,13 @@ static bool _setNvDispDockedRefreshRate(uint32_t new_refreshRate) {
|
|||||||
|
|
||||||
if (itr == -1) itr = _getDockedRefreshRateIterator(60);
|
if (itr == -1) itr = _getDockedRefreshRateIterator(60);
|
||||||
|
|
||||||
bool increase = refreshRateNow < g_dockedRefreshRates[itr];
|
// Clamp to highest allowed refresh rate
|
||||||
bool* allowed = (display_b.vActive == 720) ? g_dockedAllowed720p : g_dockedAllowed;
|
if (g_dockedRefreshRates[itr] > g_dockedHighestRefreshRate) {
|
||||||
|
for (int8_t i = itr; i >= 0; i--) {
|
||||||
while(itr >= 0 && itr < (int8_t)numRates && allowed[itr] != true) {
|
if (g_dockedRefreshRates[i] <= g_dockedHighestRefreshRate) {
|
||||||
if (!g_config.displaySyncDocked) {
|
itr = i;
|
||||||
if (increase) itr++;
|
break;
|
||||||
else itr--;
|
}
|
||||||
} else {
|
|
||||||
itr++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -592,9 +550,10 @@ bool DisplayRefresh_SetRate(uint32_t new_refreshRate) {
|
|||||||
if (g_config.isRetroSUPER && !g_config.isDocked) {
|
if (g_config.isRetroSUPER && !g_config.isDocked) {
|
||||||
return _setNvDispHandheldRefreshRate(new_refreshRate);
|
return _setNvDispHandheldRefreshRate(new_refreshRate);
|
||||||
}
|
}
|
||||||
else if ((!g_config.isRetroSUPER && g_config.isLite) ||
|
|
||||||
nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
else if ((!g_config.isRetroSUPER && g_config.isLite) || R_FAILED(nvOpen(&fd, "/dev/nvdisp-disp1"))) {
|
||||||
return _setPLLDHandheldRefreshRate(new_refreshRate);
|
if (_setPLLDHandheldRefreshRate(new_refreshRate) == false)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct dpaux_read {
|
struct dpaux_read {
|
||||||
@@ -616,21 +575,24 @@ bool DisplayRefresh_SetRate(uint32_t new_refreshRate) {
|
|||||||
nvClose(fd);
|
nvClose(fd);
|
||||||
|
|
||||||
if (rc != 0) {
|
if (rc != 0) {
|
||||||
if (!g_config.isRetroSUPER) {
|
if (!g_config.isRetroSUPER) {
|
||||||
return _setPLLDHandheldRefreshRate(new_refreshRate);
|
return _setPLLDHandheldRefreshRate(new_refreshRate);
|
||||||
} else {
|
} else {
|
||||||
return _setNvDispHandheldRefreshRate(new_refreshRate);
|
return _setNvDispHandheldRefreshRate(new_refreshRate);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return _setNvDispDockedRefreshRate(new_refreshRate);
|
if(g_config.isDocked)
|
||||||
|
return _setNvDispDockedRefreshRate(new_refreshRate);
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) {
|
bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) {
|
||||||
if (!out_refreshRate || !g_initialized || !g_config.clkVirtAddr) return false;
|
if (!out_refreshRate || !g_initialized || !g_config.clkVirtAddr) return false;
|
||||||
|
static uint32_t value = 60;
|
||||||
uint32_t value = 60;
|
|
||||||
|
|
||||||
if (g_config.isRetroSUPER && !g_config.isDocked) {
|
if (g_config.isRetroSUPER && !g_config.isDocked) {
|
||||||
uint32_t fd = 0;
|
uint32_t fd = 0;
|
||||||
@@ -705,7 +667,10 @@ bool DisplayRefresh_GetRate(uint32_t* out_refreshRate, bool internal) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(internal) {
|
||||||
|
*out_refreshRate = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
uint32_t fd = 0;
|
uint32_t fd = 0;
|
||||||
if (!nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
if (!nvOpen(&fd, "/dev/nvdisp-disp1")) {
|
||||||
NvdcMode2 display_b = {0};
|
NvdcMode2 display_b = {0};
|
||||||
|
|||||||
83
Source/sys-clk/common/src/memmem.c
Normal file
83
Source/sys-clk/common/src/memmem.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Roy Merkel
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "memmem.h"
|
||||||
|
|
||||||
|
void *memmem_impl(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)
|
||||||
|
{
|
||||||
|
const unsigned char *cmpp;
|
||||||
|
const unsigned char *p;
|
||||||
|
const unsigned char *endp;
|
||||||
|
const unsigned char *q;
|
||||||
|
const unsigned char *endq;
|
||||||
|
unsigned char found;
|
||||||
|
|
||||||
|
if(haystack == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(needle == NULL)
|
||||||
|
{
|
||||||
|
return (void*)haystack;
|
||||||
|
}
|
||||||
|
if(haystacklen == 0)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if(needlelen == 0)
|
||||||
|
{
|
||||||
|
return (void*)haystack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(needlelen > haystacklen)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
endp = haystack + haystacklen - needlelen;
|
||||||
|
endq = needle + needlelen;
|
||||||
|
for(p = haystack; p <= endp; p++)
|
||||||
|
{
|
||||||
|
found = 1;
|
||||||
|
cmpp = p;
|
||||||
|
for(q = needle; q < endq; q++)
|
||||||
|
{
|
||||||
|
if(*cmpp != *q)
|
||||||
|
{
|
||||||
|
found = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmpp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found)
|
||||||
|
{
|
||||||
|
return (void*)p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
@@ -53,6 +53,14 @@ Result rgltrGetVoltage(RgltrSession* session, u32* out_volt) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result rgltrRequestVoltage(RgltrSession* session, u32 microvolt) {
|
||||||
|
return serviceDispatchIn(&session->s, 5, microvolt);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rgltrCancelVoltageRequest(RgltrSession* session) {
|
||||||
|
return serviceDispatch(&session->s, 6);
|
||||||
|
}
|
||||||
|
|
||||||
void rgltrCloseSession(RgltrSession* session) {
|
void rgltrCloseSession(RgltrSession* session) {
|
||||||
serviceClose(&session->s);
|
serviceClose(&session->s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ include ${TOPDIR}/lib/libultrahand/ultrahand.mk
|
|||||||
# version control constants
|
# version control constants
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
#TARGET_VERSION := $(shell git describe --dirty --always --tags)
|
#TARGET_VERSION := $(shell git describe --dirty --always --tags)
|
||||||
APP_VERSION := 0.35
|
APP_VERSION := 1.0.2
|
||||||
TARGET_VERSION := $(APP_VERSION)
|
TARGET_VERSION := $(APP_VERSION)
|
||||||
|
|
||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
@@ -49,13 +49,13 @@ DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_V
|
|||||||
|
|
||||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||||
|
|
||||||
CFLAGS := -Os -Wall -flto -fdata-sections -ffunction-sections -fno-rtti -fno-common \
|
CFLAGS := -O2 -Wall -flto -fdata-sections -ffunction-sections -fno-rtti -fno-common \
|
||||||
$(ARCH) $(DEFINES)
|
$(ARCH) $(DEFINES)
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||||
|
|
||||||
# Enable appearance overriding
|
# Enable appearance overriding
|
||||||
UI_OVERRIDE_PATH := /config/sys-clk/
|
UI_OVERRIDE_PATH := /config/horizon-oc/
|
||||||
CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\""
|
CFLAGS += -DUI_OVERRIDE_PATH="\"$(UI_OVERRIDE_PATH)\""
|
||||||
|
|
||||||
# Disable fstream
|
# Disable fstream
|
||||||
|
|||||||
132
Source/sys-clk/overlay/lang/zh-tw.json
Normal file
132
Source/sys-clk/overlay/lang/zh-tw.json
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "編輯應用配置",
|
||||||
|
"Advanced": "高級",
|
||||||
|
"Edit Global Profile": "編輯全局配置",
|
||||||
|
"Temporary Overrides": "臨時覆蓋",
|
||||||
|
"Temporary Overrides Reset": "臨時覆蓋 重設",
|
||||||
|
"Settings": "設置",
|
||||||
|
"Information": "資訊",
|
||||||
|
"Enable": "啟用",
|
||||||
|
"Uncapped Clocks": "解除頻率上限",
|
||||||
|
"Override Boost Mode": "覆蓋加速模式",
|
||||||
|
"CPU Max Display Clock": "CPU 最大顯示頻率",
|
||||||
|
"Thermal Throttle": "溫度節流",
|
||||||
|
"Thermal Throttle Threshold": "溫度節流閾值",
|
||||||
|
"Handheld TDP": "掌機模式 TDP",
|
||||||
|
"Handheld TDP Limit": "掌機模式 TDP 限制",
|
||||||
|
"Lite TDP Limit": "Lite TDP 限制",
|
||||||
|
"Enforce Board Limit": "強制主板限制",
|
||||||
|
"Battery Charge Current": "電池充電電流",
|
||||||
|
"Display Refresh Rate Changing": "顯示刷新率變更",
|
||||||
|
"Fix CPU Volt Bug": "修復 CPU 電壓錯誤",
|
||||||
|
"[cfg] no enum format string": "[cfg] 無枚舉格式字串",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "保存 KIP 設置",
|
||||||
|
"RAM Settings": "記憶體設定",
|
||||||
|
"CPU Settings": "CPU 設置",
|
||||||
|
"GPU Settings": "GPU 設置",
|
||||||
|
"Experimental": "實驗性功能",
|
||||||
|
"Charge Current Override": "充電電流覆蓋",
|
||||||
|
"Disabled": "禁用",
|
||||||
|
"HP Mode": "高性能模式",
|
||||||
|
"EMC Max Clock": "EMC 最大頻率",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 電壓",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ 電壓",
|
||||||
|
"DVB Shift": "DVB 偏移",
|
||||||
|
"Memory Timings": "記憶體時序",
|
||||||
|
"Memory Latencies": "記憶體延遲",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "更新記憶體時序",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 此功能為實驗性功能",
|
||||||
|
"and should only be used for testing!": "僅應用於測試!",
|
||||||
|
"Read Latency": "讀取延遲",
|
||||||
|
"Write Latency": "寫入延遲",
|
||||||
|
"CPU UV": "CPU 降壓",
|
||||||
|
"CPU Unlock": "CPU 解鎖",
|
||||||
|
"CPU VMIN": "CPU 最低電壓",
|
||||||
|
"CPU Max Voltage": "CPU 最大電壓",
|
||||||
|
"CPU UV Table": "CPU 降壓表",
|
||||||
|
"CPU Low UV": "CPU 低頻降壓",
|
||||||
|
"CPU High UV": "CPU 高頻降壓",
|
||||||
|
"CPU Max Clock": "CPU 最大頻率",
|
||||||
|
"CPU Low VMIN": "CPU 低頻最低電壓",
|
||||||
|
"CPU High VMIN": "CPU 高頻最低電壓",
|
||||||
|
"GPU Undervolt Table": "GPU 降壓表",
|
||||||
|
"Calculate GPU Vmin": "計算 GPU 最低電壓",
|
||||||
|
"GPU VMIN": "GPU 最低電壓",
|
||||||
|
"GPU VMAX": "GPU 最大電壓",
|
||||||
|
"GPU Volt Offset": "GPU 電壓偏移",
|
||||||
|
"GPU Custom Table": "GPU 自訂表",
|
||||||
|
"GPU Custom Table (mV)": "GPU 自訂表 (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 將 GPU 頻率設置超過",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "無降壓時的 1075MHz、SLT 時的 1152MHz 或",
|
||||||
|
"1228MHz on HiOPT can cause ": "HiOPT 時的 1228MHz 可能會造成",
|
||||||
|
"permanent damage to your Switch!": "對您的 Switch 造成永久性損壞!",
|
||||||
|
"Proceed at your own risk!": "風險自負!",
|
||||||
|
"921MHz without UV and 960MHz on": "無降壓時的 921MHz 和",
|
||||||
|
"SLT or HiOPT can cause ": "SLT 或 HiOPT 時的 960MHz 可能會造成",
|
||||||
|
"Auto": "自動",
|
||||||
|
"Sleep Mode": "休眠模式",
|
||||||
|
"Stock": "默認",
|
||||||
|
"Dev OC": "開發超頻",
|
||||||
|
"Boost Mode": "加速模式",
|
||||||
|
"Safe Max": "安全最大值",
|
||||||
|
"Unsafe Max": "不安全最大值",
|
||||||
|
"Absolute Max": "絕對最大值",
|
||||||
|
"Boost Mode & Safe Max": "加速模式 & 安全最大值",
|
||||||
|
"Official Rating": "官方額定值",
|
||||||
|
"Default (Mariko)": "默認 (Mariko)",
|
||||||
|
"Default (Erista)": "默認 (Erista)",
|
||||||
|
"Rating": "額定值",
|
||||||
|
"Safe Max (Mariko)": "安全最大值 (Mariko)",
|
||||||
|
"Safe Max (Erista)": "安全最大值 (Erista)",
|
||||||
|
"Default": "默認",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "極限降壓表",
|
||||||
|
"No UV": "不降壓",
|
||||||
|
"SLT Table": "SLT 表",
|
||||||
|
"HiOPT Table": "HiOPT 表",
|
||||||
|
"Power": "功耗",
|
||||||
|
"Temp": "溫度",
|
||||||
|
"Voltage": "電壓",
|
||||||
|
"TDP Threshold": "TDP 閾值",
|
||||||
|
"Lite TDP Threshold": "Lite TDP 閾值",
|
||||||
|
"Thermal Throttle Limit": "溫度節流限制",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "電池",
|
||||||
|
"FAN": "風扇",
|
||||||
|
"DISP": "顯示",
|
||||||
|
"Board": "主板",
|
||||||
|
"Skin": "外殼",
|
||||||
|
"Now": "當前",
|
||||||
|
"Avg": "平均",
|
||||||
|
"App ID": "應用 ID",
|
||||||
|
"Profile": "配置",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "記憶體",
|
||||||
|
"Display": "顯示",
|
||||||
|
"Governor": "調速器",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "底座模式",
|
||||||
|
"Handheld": "掌機模式",
|
||||||
|
"Charging": "充電中",
|
||||||
|
"USB Charger": "USB 充電器",
|
||||||
|
"PD Charger": "PD 充電器",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
@@ -24,6 +24,10 @@
|
|||||||
|
|
||||||
tsl::elm::ListItem* SpeedoItem = NULL;
|
tsl::elm::ListItem* SpeedoItem = NULL;
|
||||||
tsl::elm::ListItem* IddqItem = NULL;
|
tsl::elm::ListItem* IddqItem = NULL;
|
||||||
|
tsl::elm::ListItem* DramModule = NULL;
|
||||||
|
tsl::elm::ListItem* sysdockStatusItem = NULL;
|
||||||
|
tsl::elm::ListItem* saltyNXStatusItem = NULL;
|
||||||
|
|
||||||
ImageElement* CatImage = NULL;
|
ImageElement* CatImage = NULL;
|
||||||
HideableCategoryHeader* CatHeader = NULL;
|
HideableCategoryHeader* CatHeader = NULL;
|
||||||
HideableCustomDrawer* CatSpacer = NULL;
|
HideableCustomDrawer* CatSpacer = NULL;
|
||||||
@@ -41,17 +45,29 @@ AboutGui::~AboutGui()
|
|||||||
void AboutGui::listUI()
|
void AboutGui::listUI()
|
||||||
{
|
{
|
||||||
this->listElement->addItem(
|
this->listElement->addItem(
|
||||||
new tsl::elm::CategoryHeader("Speedo/IDDQ")
|
new tsl::elm::CategoryHeader("Information")
|
||||||
);
|
);
|
||||||
|
|
||||||
SpeedoItem =
|
SpeedoItem =
|
||||||
new tsl::elm::ListItem("Speedos:");
|
new tsl::elm::ListItem("Speedo:");
|
||||||
this->listElement->addItem(SpeedoItem);
|
this->listElement->addItem(SpeedoItem);
|
||||||
|
|
||||||
IddqItem =
|
IddqItem =
|
||||||
new tsl::elm::ListItem("IDDQ:");
|
new tsl::elm::ListItem("IDDQ:");
|
||||||
this->listElement->addItem(IddqItem);
|
this->listElement->addItem(IddqItem);
|
||||||
|
|
||||||
|
DramModule =
|
||||||
|
new tsl::elm::ListItem("Module: ");
|
||||||
|
this->listElement->addItem(DramModule);
|
||||||
|
|
||||||
|
sysdockStatusItem =
|
||||||
|
new tsl::elm::ListItem("sys-dock status:");
|
||||||
|
this->listElement->addItem(sysdockStatusItem);
|
||||||
|
|
||||||
|
saltyNXStatusItem =
|
||||||
|
new tsl::elm::ListItem("SaltyNX status:");
|
||||||
|
this->listElement->addItem(saltyNXStatusItem);
|
||||||
|
|
||||||
this->listElement->addItem(
|
this->listElement->addItem(
|
||||||
new tsl::elm::CategoryHeader("Credits")
|
new tsl::elm::CategoryHeader("Credits")
|
||||||
);
|
);
|
||||||
@@ -117,7 +133,7 @@ void AboutGui::listUI()
|
|||||||
this->listElement->addItem(
|
this->listElement->addItem(
|
||||||
new tsl::elm::ListItem("Happy")
|
new tsl::elm::ListItem("Happy")
|
||||||
);
|
);
|
||||||
|
|
||||||
this->listElement->addItem(
|
this->listElement->addItem(
|
||||||
new tsl::elm::ListItem("Flopsider")
|
new tsl::elm::ListItem("Flopsider")
|
||||||
);
|
);
|
||||||
@@ -195,7 +211,7 @@ void AboutGui::listUI()
|
|||||||
CatHeader = new HideableCategoryHeader("Cat");
|
CatHeader = new HideableCategoryHeader("Cat");
|
||||||
CatHeader->setVisible(false);
|
CatHeader->setVisible(false);
|
||||||
this->listElement->addItem(CatHeader);
|
this->listElement->addItem(CatHeader);
|
||||||
|
|
||||||
CatImage = new ImageElement(CAT_DATA, CAT_WIDTH, CAT_HEIGHT);
|
CatImage = new ImageElement(CAT_DATA, CAT_WIDTH, CAT_HEIGHT);
|
||||||
CatImage->setVisible(false);
|
CatImage->setVisible(false);
|
||||||
this->listElement->addItem(CatImage);
|
this->listElement->addItem(CatImage);
|
||||||
@@ -205,6 +221,49 @@ void AboutGui::listUI()
|
|||||||
this->listElement->addItem(CatSpacer);
|
this->listElement->addItem(CatSpacer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string AboutGui::formatRamModule() {
|
||||||
|
switch (this->context->dramID) {
|
||||||
|
case 0: return "HB-MGCH 4GB";
|
||||||
|
case 4: return "HM-MGCH 6GB";
|
||||||
|
case 7: return "HM-MGXX 8GB";
|
||||||
|
|
||||||
|
case 1: return "NLE";
|
||||||
|
case 2: return "WT:C";
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
case 5 ... 6: return "NEE";
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
case 12: return "AM-MGCJ 4GB";
|
||||||
|
case 9:
|
||||||
|
case 13: return "AM-MGCJ 8GB";
|
||||||
|
|
||||||
|
case 10:
|
||||||
|
case 14: return "NME";
|
||||||
|
|
||||||
|
case 11:
|
||||||
|
case 15: return "WT:E";
|
||||||
|
|
||||||
|
case 17:
|
||||||
|
case 19:
|
||||||
|
case 24: return "AA-MGCL 4GB";
|
||||||
|
|
||||||
|
case 18:
|
||||||
|
case 23:
|
||||||
|
case 28: return "AA-MGCL 8GB";
|
||||||
|
|
||||||
|
case 20 ... 22: return "AB-MGCL 4GB";
|
||||||
|
|
||||||
|
case 25 ... 27: return "WT:F";
|
||||||
|
|
||||||
|
case 29 ... 31: return "x267";
|
||||||
|
|
||||||
|
case 32 ... 34: return "WT:B";
|
||||||
|
|
||||||
|
default: return "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AboutGui::update()
|
void AboutGui::update()
|
||||||
{
|
{
|
||||||
BaseMenuGui::update();
|
BaseMenuGui::update();
|
||||||
@@ -213,7 +272,8 @@ void AboutGui::update()
|
|||||||
void AboutGui::refresh()
|
void AboutGui::refresh()
|
||||||
{
|
{
|
||||||
BaseMenuGui::refresh();
|
BaseMenuGui::refresh();
|
||||||
|
std::string ramModule = formatRamModule();
|
||||||
|
|
||||||
if (!this->context)
|
if (!this->context)
|
||||||
return;
|
return;
|
||||||
// Format strings once per refresh
|
// Format strings once per refresh
|
||||||
@@ -221,4 +281,7 @@ void AboutGui::refresh()
|
|||||||
sprintf(strings[1], "%u/%u/%u", this->context->iddq[HorizonOCSpeedo_CPU], this->context->iddq[HorizonOCSpeedo_GPU], this->context->iddq[HorizonOCSpeedo_SOC]);
|
sprintf(strings[1], "%u/%u/%u", this->context->iddq[HorizonOCSpeedo_CPU], this->context->iddq[HorizonOCSpeedo_GPU], this->context->iddq[HorizonOCSpeedo_SOC]);
|
||||||
SpeedoItem->setValue(strings[0]);
|
SpeedoItem->setValue(strings[0]);
|
||||||
IddqItem->setValue(strings[1]);
|
IddqItem->setValue(strings[1]);
|
||||||
}
|
DramModule->setValue(formatRamModule());
|
||||||
|
sysdockStatusItem->setValue(this->context->isSysDockInstalled ? "Installed" : "Not Installed");
|
||||||
|
saltyNXStatusItem->setValue(this->context->isSaltyNXInstalled ? "Installed" : "Not Installed");
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,12 +27,15 @@ class AboutGui : public BaseMenuGui
|
|||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
char strings[32][32]; // Pre-formatted strings
|
char strings[32][32]; // Pre-formatted strings
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AboutGui();
|
AboutGui();
|
||||||
~AboutGui();
|
~AboutGui();
|
||||||
|
|
||||||
void listUI() override;
|
void listUI() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
void refresh() override;
|
void refresh() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string formatRamModule();
|
||||||
};
|
};
|
||||||
@@ -95,7 +95,8 @@ void AppProfileGui::openValueChoiceGui(
|
|||||||
enableThresholds,
|
enableThresholds,
|
||||||
labels,
|
labels,
|
||||||
namedValues,
|
namedValues,
|
||||||
showDefaultValue
|
showDefaultValue,
|
||||||
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,6 +149,36 @@ void AppProfileGui::addModuleListItemToggle(SysClkProfile profile, SysClkModule
|
|||||||
this->listElement->addItem(toggle);
|
this->listElement->addItem(toggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string AppProfileGui::formatValueDisplay(
|
||||||
|
std::uint32_t value,
|
||||||
|
const std::vector<NamedValue>& namedValues,
|
||||||
|
const std::string& suffix,
|
||||||
|
std::uint32_t divisor,
|
||||||
|
int decimalPlaces
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (value == 0) {
|
||||||
|
return FREQ_DEFAULT_TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!namedValues.empty()) {
|
||||||
|
for (const auto& namedValue : namedValues) {
|
||||||
|
if (namedValue.value == value) {
|
||||||
|
return namedValue.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char buf[32];
|
||||||
|
if (decimalPlaces > 0) {
|
||||||
|
double displayValue = (double)value / divisor;
|
||||||
|
snprintf(buf, sizeof(buf), "%.*f%s", decimalPlaces, displayValue, suffix.c_str());
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof(buf), "%u%s", value / divisor, suffix.c_str());
|
||||||
|
}
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
void AppProfileGui::addModuleListItemValue(
|
void AppProfileGui::addModuleListItemValue(
|
||||||
SysClkProfile profile,
|
SysClkProfile profile,
|
||||||
SysClkModule module,
|
SysClkModule module,
|
||||||
@@ -158,26 +189,17 @@ void AppProfileGui::addModuleListItemValue(
|
|||||||
const std::string& suffix,
|
const std::string& suffix,
|
||||||
std::uint32_t divisor,
|
std::uint32_t divisor,
|
||||||
int decimalPlaces,
|
int decimalPlaces,
|
||||||
ValueThresholds thresholds
|
ValueThresholds thresholds,
|
||||||
|
std::vector<NamedValue> namedValues,
|
||||||
|
bool showDefaultValue
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
tsl::elm::ListItem* listItem =
|
tsl::elm::ListItem* listItem =
|
||||||
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||||
|
|
||||||
std::uint32_t storedValue = this->profileList->mhzMap[profile][module];
|
std::uint32_t storedValue = this->profileList->mhzMap[profile][module];
|
||||||
if (storedValue == 0) {
|
|
||||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
listItem->setValue(this->formatValueDisplay(storedValue, namedValues, suffix, divisor, decimalPlaces));
|
||||||
} else {
|
|
||||||
char buf[32];
|
|
||||||
if (decimalPlaces > 0) {
|
|
||||||
double displayValue = (double)storedValue / divisor;
|
|
||||||
snprintf(buf, sizeof(buf), "%.*f%s", decimalPlaces, displayValue, suffix.c_str());
|
|
||||||
} else {
|
|
||||||
snprintf(buf, sizeof(buf), "%u%s", storedValue / divisor, suffix.c_str());
|
|
||||||
}
|
|
||||||
listItem->setValue(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
listItem->setClickListener(
|
listItem->setClickListener(
|
||||||
[this,
|
[this,
|
||||||
listItem,
|
listItem,
|
||||||
@@ -190,13 +212,14 @@ void AppProfileGui::addModuleListItemValue(
|
|||||||
suffix,
|
suffix,
|
||||||
divisor,
|
divisor,
|
||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
thresholds](u64 keys)
|
thresholds,
|
||||||
|
namedValues,
|
||||||
|
showDefaultValue](u64 keys)
|
||||||
{
|
{
|
||||||
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||||
{
|
{
|
||||||
std::uint32_t currentValue =
|
std::uint32_t currentValue =
|
||||||
this->profileList->mhzMap[profile][module] * divisor;
|
this->profileList->mhzMap[profile][module] * divisor;
|
||||||
|
|
||||||
ValueRange range(
|
ValueRange range(
|
||||||
min,
|
min,
|
||||||
max,
|
max,
|
||||||
@@ -205,36 +228,19 @@ void AppProfileGui::addModuleListItemValue(
|
|||||||
divisor,
|
divisor,
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
);
|
);
|
||||||
|
|
||||||
this->openValueChoiceGui(
|
this->openValueChoiceGui(
|
||||||
listItem,
|
listItem,
|
||||||
currentValue,
|
currentValue,
|
||||||
range,
|
range,
|
||||||
categoryName,
|
categoryName,
|
||||||
|
[this, listItem, profile, module, divisor, suffix, decimalPlaces, thresholds, namedValues](std::uint32_t value) -> bool
|
||||||
[this, listItem, profile, module, divisor, suffix, decimalPlaces, thresholds](std::uint32_t value) -> bool
|
|
||||||
{
|
{
|
||||||
this->profileList->mhzMap[profile][module] = value / divisor;
|
this->profileList->mhzMap[profile][module] = value / divisor;
|
||||||
|
listItem->setValue(this->formatValueDisplay(value / divisor, namedValues, suffix, divisor, decimalPlaces));
|
||||||
if (value == 0) {
|
|
||||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
|
||||||
} else {
|
|
||||||
char buf[32];
|
|
||||||
if (decimalPlaces > 0) {
|
|
||||||
double displayValue = (double)value / divisor;
|
|
||||||
snprintf(buf, sizeof(buf), "%.*f%s",
|
|
||||||
decimalPlaces, displayValue, suffix.c_str());
|
|
||||||
} else {
|
|
||||||
snprintf(buf, sizeof(buf), "%u%s",
|
|
||||||
value / divisor, suffix.c_str());
|
|
||||||
}
|
|
||||||
listItem->setValue(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result rc =
|
Result rc =
|
||||||
sysclkIpcSetProfiles(this->applicationId,
|
sysclkIpcSetProfiles(this->applicationId,
|
||||||
this->profileList);
|
this->profileList);
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
FatalGui::openWithResultCode(
|
FatalGui::openWithResultCode(
|
||||||
@@ -243,58 +249,144 @@ void AppProfileGui::addModuleListItemValue(
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
thresholds,
|
thresholds,
|
||||||
false
|
false,
|
||||||
|
{},
|
||||||
|
namedValues,
|
||||||
|
showDefaultValue
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ((keys & HidNpadButton_Y) == HidNpadButton_Y)
|
else if ((keys & HidNpadButton_Y) == HidNpadButton_Y)
|
||||||
{
|
{
|
||||||
this->profileList->mhzMap[profile][module] = 0;
|
this->profileList->mhzMap[profile][module] = 0;
|
||||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||||
|
|
||||||
Result rc =
|
Result rc =
|
||||||
sysclkIpcSetProfiles(this->applicationId,
|
sysclkIpcSetProfiles(this->applicationId,
|
||||||
this->profileList);
|
this->profileList);
|
||||||
|
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
{
|
{
|
||||||
FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
|
FatalGui::openWithResultCode("sysclkIpcSetProfiles", rc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this->listElement->addItem(listItem);
|
this->listElement->addItem(listItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppProfileGui::addProfileUI(SysClkProfile profile)
|
void AppProfileGui::addProfileUI(SysClkProfile profile)
|
||||||
{
|
{
|
||||||
Result rc = sysclkIpcGetConfigValues(&configList); // idk why this is needed, probably some refreshing issue
|
BaseMenuGui::refresh();
|
||||||
|
if(!this->context)
|
||||||
|
return;
|
||||||
|
Result rc = sysclkIpcGetConfigValues(&configList);
|
||||||
if (R_FAILED(rc)) [[unlikely]] {
|
if (R_FAILED(rc)) [[unlikely]] {
|
||||||
FatalGui::openWithResultCode("sysclkIpcGetConfigValues", rc);
|
FatalGui::openWithResultCode("sysclkIpcGetConfigValues", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " Reset"));
|
this->listElement->addItem(new tsl::elm::CategoryHeader(sysclkFormatProfile(profile, true) + std::string(" ") + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||||
this->addModuleListItem(profile, SysClkModule_CPU);
|
this->addModuleListItem(profile, SysClkModule_CPU);
|
||||||
this->addModuleListItem(profile, SysClkModule_GPU);
|
this->addModuleListItem(profile, SysClkModule_GPU);
|
||||||
this->addModuleListItem(profile, SysClkModule_MEM);
|
this->addModuleListItem(profile, SysClkModule_MEM);
|
||||||
#if IS_MINIMAL == 0
|
#if IS_MINIMAL == 0
|
||||||
ValueThresholds lcdThresholds(60, 65);
|
ValueThresholds lcdThresholds(60, 65);
|
||||||
if(!IsHoag() && configList.values[HorizonOCConfigValue_OverwriteRefreshRate]) {
|
if(configList.values[HorizonOCConfigValue_OverwriteRefreshRate]) {
|
||||||
if(profile != SysClkProfile_Docked)
|
if(profile != SysClkProfile_Docked) {
|
||||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||||
else
|
} else {
|
||||||
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 120, 5, " Hz", 1, 0);
|
if(IsAula() && this->context->isSysDockInstalled) {
|
||||||
|
std::vector<NamedValue> dockedFreqs = {
|
||||||
|
NamedValue("40 Hz", 40),
|
||||||
|
NamedValue("45 Hz", 45),
|
||||||
|
NamedValue("50 Hz", 50),
|
||||||
|
NamedValue("55 Hz", 55),
|
||||||
|
NamedValue("60 Hz", 60),
|
||||||
|
NamedValue("70 Hz", 70),
|
||||||
|
NamedValue("72 Hz", 72),
|
||||||
|
NamedValue("75 Hz", 75),
|
||||||
|
NamedValue("80 Hz", 80),
|
||||||
|
NamedValue("90 Hz", 90),
|
||||||
|
NamedValue("95 Hz", 95),
|
||||||
|
NamedValue("100 Hz", 100),
|
||||||
|
NamedValue("110 Hz", 110),
|
||||||
|
NamedValue("120 Hz", 120),
|
||||||
|
NamedValue("130 Hz", 130),
|
||||||
|
NamedValue("140 Hz", 140),
|
||||||
|
NamedValue("144 Hz", 144),
|
||||||
|
NamedValue("150 Hz", 150),
|
||||||
|
NamedValue("160 Hz", 160),
|
||||||
|
NamedValue("165 Hz", 165),
|
||||||
|
NamedValue("170 Hz", 170),
|
||||||
|
NamedValue("180 Hz", 180),
|
||||||
|
NamedValue("190 Hz", 190),
|
||||||
|
NamedValue("200 Hz", 200),
|
||||||
|
NamedValue("210 Hz", 210),
|
||||||
|
NamedValue("220 Hz", 220),
|
||||||
|
NamedValue("230 Hz", 230),
|
||||||
|
NamedValue("240 Hz", 240)
|
||||||
|
};
|
||||||
|
|
||||||
|
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 40, 240, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqs);
|
||||||
|
} else if (IsAula() && !this->context->isSysDockInstalled) {
|
||||||
|
std::vector<NamedValue> dockedFreqsLimited = {
|
||||||
|
NamedValue("50 Hz", 50),
|
||||||
|
NamedValue("55 Hz", 55),
|
||||||
|
NamedValue("60 Hz", 60),
|
||||||
|
NamedValue("65 Hz", 65),
|
||||||
|
NamedValue("70 Hz", 70),
|
||||||
|
NamedValue("72 Hz", 72),
|
||||||
|
NamedValue("75 Hz", 75)
|
||||||
|
};
|
||||||
|
|
||||||
|
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 75, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqsLimited);
|
||||||
|
} else {
|
||||||
|
std::vector<NamedValue> dockedFreqsStandard = {
|
||||||
|
NamedValue("50 Hz", 50),
|
||||||
|
NamedValue("55 Hz", 55),
|
||||||
|
NamedValue("60 Hz", 60),
|
||||||
|
NamedValue("65 Hz", 65),
|
||||||
|
NamedValue("70 Hz", 70),
|
||||||
|
NamedValue("72 Hz", 72),
|
||||||
|
NamedValue("75 Hz", 75),
|
||||||
|
NamedValue("80 Hz", 80),
|
||||||
|
NamedValue("85 Hz", 85),
|
||||||
|
NamedValue("90 Hz", 90),
|
||||||
|
NamedValue("95 Hz", 95),
|
||||||
|
NamedValue("100 Hz", 100),
|
||||||
|
NamedValue("105 Hz", 105),
|
||||||
|
NamedValue("110 Hz", 110),
|
||||||
|
NamedValue("115 Hz", 115),
|
||||||
|
NamedValue("120 Hz", 120)
|
||||||
|
};
|
||||||
|
if(configList.values[HorizonOCConfigValue_OverwriteRefreshRate] && !IsHoag())
|
||||||
|
this->addModuleListItemValue(profile, HorizonOCModule_Display, "Display", 50, 120, 1, " Hz", 1, 0, ValueThresholds(), dockedFreqsStandard);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
this->addModuleListItemToggle(profile, HorizonOCModule_Governor);
|
std::vector<NamedValue> governorSettingsE = {
|
||||||
|
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||||
|
NamedValue("Disabled", GovernorState_Disabled),
|
||||||
|
NamedValue("CPU + GPU + VRR", GovernorState_Enabled_CpuGpuVrr),
|
||||||
|
NamedValue("CPU + VRR", GovernorState_Enabled_CpuVrr),
|
||||||
|
NamedValue("GPU + VRR", GovernorState_Enabled_GpuVrr),
|
||||||
|
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||||
|
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||||
|
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||||
|
NamedValue("VRR", GovernorState_Enabled_Vrr),
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<NamedValue> governorSettingsH = {
|
||||||
|
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||||
|
NamedValue("Disabled", GovernorState_Disabled),
|
||||||
|
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||||
|
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||||
|
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||||
|
};
|
||||||
|
|
||||||
|
this->addModuleListItemValue(profile, HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), IsHoag() ? governorSettingsH : governorSettingsE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppProfileGui::listUI()
|
void AppProfileGui::listUI()
|
||||||
@@ -334,4 +426,4 @@ void AppProfileGui::update()
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,22 +23,17 @@
|
|||||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../ipc.h"
|
#include "../../ipc.h"
|
||||||
#include "base_menu_gui.h"
|
#include "base_menu_gui.h"
|
||||||
#include "freq_choice_gui.h"
|
#include "freq_choice_gui.h"
|
||||||
#include "value_choice_gui.h"
|
#include "value_choice_gui.h"
|
||||||
#define SYSCLK_GLOBAL_PROFILE_TID 0xA111111111111111
|
#define SYSCLK_GLOBAL_PROFILE_TID 0xA111111111111111
|
||||||
|
|
||||||
class AppProfileGui : public BaseMenuGui
|
class AppProfileGui : public BaseMenuGui
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
std::uint64_t applicationId;
|
std::uint64_t applicationId;
|
||||||
SysClkTitleProfileList* profileList;
|
SysClkTitleProfileList* profileList;
|
||||||
|
|
||||||
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module);
|
void openFreqChoiceGui(tsl::elm::ListItem* listItem, SysClkProfile profile, SysClkModule module);
|
||||||
void addModuleListItem(SysClkProfile profile, SysClkModule module);
|
void addModuleListItem(SysClkProfile profile, SysClkModule module);
|
||||||
void addModuleListItemToggle(SysClkProfile profile, SysClkModule module);
|
void addModuleListItemToggle(SysClkProfile profile, SysClkModule module);
|
||||||
@@ -54,6 +49,13 @@ class AppProfileGui : public BaseMenuGui
|
|||||||
const std::vector<NamedValue>& namedValues = {},
|
const std::vector<NamedValue>& namedValues = {},
|
||||||
bool showDefaultValue = true
|
bool showDefaultValue = true
|
||||||
);
|
);
|
||||||
|
std::string formatValueDisplay(
|
||||||
|
std::uint32_t value,
|
||||||
|
const std::vector<NamedValue>& namedValues,
|
||||||
|
const std::string& suffix,
|
||||||
|
std::uint32_t divisor,
|
||||||
|
int decimalPlaces
|
||||||
|
);
|
||||||
void addModuleListItemValue(
|
void addModuleListItemValue(
|
||||||
SysClkProfile profile,
|
SysClkProfile profile,
|
||||||
SysClkModule module,
|
SysClkModule module,
|
||||||
@@ -64,14 +66,15 @@ class AppProfileGui : public BaseMenuGui
|
|||||||
const std::string& suffix,
|
const std::string& suffix,
|
||||||
std::uint32_t divisor,
|
std::uint32_t divisor,
|
||||||
int decimalPlaces,
|
int decimalPlaces,
|
||||||
ValueThresholds thresholds = {}
|
ValueThresholds thresholds,
|
||||||
|
std::vector<NamedValue> namedValues = {},
|
||||||
|
bool showDefaultValue = true
|
||||||
);
|
);
|
||||||
void addProfileUI(SysClkProfile profile);
|
void addProfileUI(SysClkProfile profile);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList);
|
AppProfileGui(std::uint64_t applicationId, SysClkTitleProfileList* profileList);
|
||||||
~AppProfileGui();
|
~AppProfileGui();
|
||||||
void listUI() override;
|
void listUI() override;
|
||||||
static void changeTo(std::uint64_t applicationId);
|
static void changeTo(std::uint64_t applicationId);
|
||||||
void update() override;
|
void update() override;
|
||||||
};
|
};
|
||||||
@@ -48,16 +48,11 @@ std::string getVersionString() {
|
|||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 4, 8, 15);
|
||||||
// AQUATIC BLUE COLORS (4-bit color space)
|
static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(7, 15, 15, 15);
|
||||||
// ---------------------------------------------
|
static constexpr tsl::Color STATIC_AQUA = tsl::Color(2, 10, 12, 15);
|
||||||
static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 4, 8, 15); // Deep ocean blue
|
const std::string name = "Horizon OC Zeus";
|
||||||
static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(7, 15, 15, 15); // Bright aqua cyan
|
|
||||||
static constexpr tsl::Color STATIC_AQUA = tsl::Color(2, 10, 12, 15); // Mid aqua
|
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// FULLY ENHANCED ANIMATED LOGO EFFECT
|
|
||||||
// ---------------------------------------------
|
|
||||||
static s32 drawDynamicUltraText(
|
static s32 drawDynamicUltraText(
|
||||||
tsl::gfx::Renderer* renderer,
|
tsl::gfx::Renderer* renderer,
|
||||||
s32 startX,
|
s32 startX,
|
||||||
@@ -68,7 +63,6 @@ static s32 drawDynamicUltraText(
|
|||||||
{
|
{
|
||||||
static constexpr double cycleDuration = 1.6;
|
static constexpr double cycleDuration = 1.6;
|
||||||
|
|
||||||
const std::string name = "Horizon OC Zeus";
|
|
||||||
s32 currentX = startX;
|
s32 currentX = startX;
|
||||||
|
|
||||||
const u64 currentTime_ns = armTicksToNs(armGetSystemTick());
|
const u64 currentTime_ns = armTicksToNs(armGetSystemTick());
|
||||||
@@ -89,15 +83,9 @@ static s32 drawDynamicUltraText(
|
|||||||
double s1 = n * n * (3.0 - 2.0 * n);
|
double s1 = n * n * (3.0 - 2.0 * n);
|
||||||
double blend = std::clamp(s1, 0.0, 1.0);
|
double blend = std::clamp(s1, 0.0, 1.0);
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// Glow Pulse (brightness modulation)
|
|
||||||
// ---------------------------------------------
|
|
||||||
double glow = (cos(phase * 1.5) + 1.0) * 0.5;
|
double glow = (cos(phase * 1.5) + 1.0) * 0.5;
|
||||||
double brightness = 0.75 + glow * 0.25;
|
double brightness = 0.75 + glow * 0.25;
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// Color interpolation (4-bit!)
|
|
||||||
// ---------------------------------------------
|
|
||||||
u8 r = static_cast<u8>(
|
u8 r = static_cast<u8>(
|
||||||
(dynamicLogoRGB1.r + (dynamicLogoRGB2.r - dynamicLogoRGB1.r) * blend) * brightness
|
(dynamicLogoRGB1.r + (dynamicLogoRGB2.r - dynamicLogoRGB1.r) * blend) * brightness
|
||||||
);
|
);
|
||||||
@@ -112,21 +100,15 @@ static s32 drawDynamicUltraText(
|
|||||||
g = std::clamp<u8>(g, 0, 15);
|
g = std::clamp<u8>(g, 0, 15);
|
||||||
b = std::clamp<u8>(b, 0, 15);
|
b = std::clamp<u8>(b, 0, 15);
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// ZEUS Lightning Flash
|
|
||||||
// ---------------------------------------------
|
|
||||||
bool lightning = (fmod(timeNow, 5.0) < 0.15);
|
bool lightning = (fmod(timeNow, 5.0) < 0.15);
|
||||||
if (lightning) {
|
if (lightning) {
|
||||||
r = std::min<u8>(r + 4, 15);
|
r = std::min<u8>(r + 4, 15);
|
||||||
g = std::min<u8>(g + 4, 15);
|
g = std::min<u8>(g + 4, 15);
|
||||||
b = std::min<u8>(b + 15, 15); // strong blue spike
|
b = std::min<u8>(b + 15, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
tsl::Color color(r, g, b, 15);
|
tsl::Color color(r, g, b, 15);
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// Static Position (no vertical wobble)
|
|
||||||
// ---------------------------------------------
|
|
||||||
std::string ls(1, letter);
|
std::string ls(1, letter);
|
||||||
|
|
||||||
if (useNotificationMethod)
|
if (useNotificationMethod)
|
||||||
@@ -138,11 +120,7 @@ static s32 drawDynamicUltraText(
|
|||||||
return currentX;
|
return currentX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
void BaseGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||||
// PRE-DRAW HOOK
|
|
||||||
// ---------------------------------------------
|
|
||||||
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
|
||||||
{
|
|
||||||
drawDynamicUltraText(
|
drawDynamicUltraText(
|
||||||
renderer,
|
renderer,
|
||||||
LOGO_X,
|
LOGO_X,
|
||||||
@@ -153,9 +131,6 @@ void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// UI SETUP
|
|
||||||
// ---------------------------------------------
|
|
||||||
tsl::elm::Element* BaseGui::createUI()
|
tsl::elm::Element* BaseGui::createUI()
|
||||||
{
|
{
|
||||||
BaseFrame* rootFrame = new BaseFrame(this);
|
BaseFrame* rootFrame = new BaseFrame(this);
|
||||||
@@ -163,9 +138,6 @@ tsl::elm::Element* BaseGui::createUI()
|
|||||||
return rootFrame;
|
return rootFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------
|
|
||||||
// LIVE UPDATE
|
|
||||||
// ---------------------------------------------
|
|
||||||
void BaseGui::update()
|
void BaseGui::update()
|
||||||
{
|
{
|
||||||
this->refresh();
|
this->refresh();
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -36,13 +36,13 @@ BaseMenuGui::BaseMenuGui() : tempColors{ tsl::Color(0), tsl::Color(0), tsl::Colo
|
|||||||
this->context = nullptr;
|
this->context = nullptr;
|
||||||
this->lastContextUpdate = 0;
|
this->lastContextUpdate = 0;
|
||||||
this->listElement = nullptr;
|
this->listElement = nullptr;
|
||||||
|
|
||||||
|
|
||||||
// Pre-cache hardware model during initialization
|
// Pre-cache hardware model during initialization
|
||||||
IsAula();
|
IsAula();
|
||||||
IsMariko();
|
IsMariko();
|
||||||
IsHoag();
|
IsHoag();
|
||||||
|
|
||||||
// Initialize display strings
|
// Initialize display strings
|
||||||
memset(displayStrings, 0, sizeof(displayStrings));
|
memset(displayStrings, 0, sizeof(displayStrings));
|
||||||
}
|
}
|
||||||
@@ -55,14 +55,14 @@ BaseMenuGui::~BaseMenuGui() {
|
|||||||
void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
||||||
BaseGui::preDraw(renderer);
|
BaseGui::preDraw(renderer);
|
||||||
if(!this->context) [[unlikely]] return;
|
if(!this->context) [[unlikely]] return;
|
||||||
|
|
||||||
// All constants pre-calculated and cached
|
// All constants pre-calculated and cached
|
||||||
static constexpr const char* const labels[] = {
|
static constexpr const char* const labels[] = {
|
||||||
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP"
|
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP", "FPS"
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
|
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
|
||||||
|
|
||||||
static u32 labelWidths[10];
|
static u32 labelWidths[10];
|
||||||
static bool positionsInitialized = false;
|
static bool positionsInitialized = false;
|
||||||
|
|
||||||
@@ -74,90 +74,91 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
}
|
}
|
||||||
static u32 positions[10] = {24-1, 310-labelWidths[1], 24-1, 192-labelWidths[3], 332-labelWidths[4], 24-1, 192 - labelWidths[6], 332-labelWidths[7], 192 - labelWidths[8], 332-labelWidths[9]};
|
static u32 positions[10] = {24-1, 310-labelWidths[1], 24-1, 192-labelWidths[3], 332-labelWidths[4], 24-1, 192 - labelWidths[6], 332-labelWidths[7], 192 - labelWidths[8], 332-labelWidths[9]};
|
||||||
|
|
||||||
static u32 maxProfileValueWidth = renderer->getTextDimensions("PD Charger", false, SMALL_TEXT_SIZE).first; // longest word
|
static u32 maxProfileValueWidth = renderer->getTextDimensions("USB Charger", false, SMALL_TEXT_SIZE).first; // longest word
|
||||||
|
|
||||||
u32 y = 91;
|
u32 y = 91;
|
||||||
|
|
||||||
// === TOP SECTION ===
|
// === TOP SECTION ===
|
||||||
renderer->drawRoundedRect(14, 70-1, 420, 30+2, 15.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
renderer->drawRoundedRect(14, 70-1, 420, 30+2, 12.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
||||||
|
|
||||||
// App ID - use pre-formatted string
|
// App ID - use pre-formatted string
|
||||||
renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||||
|
|
||||||
// Profile - use pre-formatted string
|
// Profile - use pre-formatted string
|
||||||
renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||||
|
|
||||||
y = 129; // Direct assignment instead of += 38
|
y += 38; // Direct assignment instead of += 38
|
||||||
|
|
||||||
// === MAIN DATA SECTION ===
|
// === MAIN DATA SECTION ===
|
||||||
renderer->drawRoundedRect(14, 106, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
// renderer->drawRoundedRect(14, 106, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
||||||
|
renderer->drawRoundedRect(14, 106, 420, 136, 12.0f, renderer->aWithOpacity(tsl::tableBGColor));
|
||||||
// === FREQUENCY SECTION ===
|
// === FREQUENCY SECTION ===
|
||||||
// Labels first (better cache locality)
|
// Labels first (better cache locality)
|
||||||
renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
|
|
||||||
// Current frequencies - use pre-formatted strings
|
|
||||||
renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
|
|
||||||
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
|
|
||||||
renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
|
|
||||||
|
|
||||||
y = 149; // Direct assignment (129 + 20)
|
|
||||||
|
|
||||||
// renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage
|
|
||||||
renderer->drawString(displayStrings[17], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU Usage
|
|
||||||
renderer->drawString(displayStrings[18], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // RAM Usage
|
|
||||||
|
|
||||||
// === REAL FREQUENCIES ===
|
|
||||||
renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
|
renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
|
||||||
renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
|
renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
|
||||||
renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
|
renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real
|
||||||
|
|
||||||
y = 169; // Direct assignment (149 + 20)
|
// Current frequencies - use pre-formatted strings
|
||||||
|
// renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
|
||||||
|
// renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
|
||||||
|
// renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
|
||||||
|
|
||||||
|
y += 20; // Direct assignment (129 + 20)
|
||||||
|
|
||||||
|
renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage
|
||||||
|
renderer->drawString(displayStrings[17], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU Usage
|
||||||
|
if(configList.values[HorizonOCConfigValue_RAMVoltUsageDisplayMode] == RamDisplayMode_VDD2Usage || configList.values[HorizonOCConfigValue_RAMVoltUsageDisplayMode] == RamDisplayMode_VDDQUsage)
|
||||||
|
renderer->drawString(displayStrings[18], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // RAM Usage
|
||||||
|
// === REAL FREQUENCIES ===
|
||||||
|
|
||||||
|
// y += 20; // Direct assignment (149 + 20)
|
||||||
|
|
||||||
// === VOLTAGES ===
|
// === VOLTAGES ===
|
||||||
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
|
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
|
||||||
renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
|
renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
|
||||||
|
|
||||||
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, configList.values[HorizonOCConfigValue_RAMVoltUsageDisplayMode] == RamDisplayMode_VDD2VDDQ ? dataPositions[5]-16 : dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
||||||
|
|
||||||
y = 191; // Direct assignment (169 + 22)
|
y += 22; // Direct assignment (169 + 22)
|
||||||
|
|
||||||
// === TEMPERATURE SECTION ===
|
// === TEMPERATURE SECTION ===
|
||||||
// Labels
|
// Labels
|
||||||
renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
|
|
||||||
// Temperatures with color - use pre-computed colors
|
// Temperatures with color - use pre-computed colors
|
||||||
renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_SOC]); // SOC
|
renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_SOC]); // SOC
|
||||||
renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_PCB]); // PCB
|
renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_PCB]); // PCB
|
||||||
renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_Skin]); // Skin
|
renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_Skin]); // Skin
|
||||||
|
|
||||||
y = 211; // Direct assignment (191 + 20)
|
y += 20; // Direct assignment (191 + 20)
|
||||||
|
|
||||||
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||||
|
|
||||||
// Power labels and values
|
// Power labels and values
|
||||||
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
|
|
||||||
renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now
|
renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now
|
||||||
renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg
|
renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg
|
||||||
|
|
||||||
y+=20;
|
y+=20;
|
||||||
|
|
||||||
renderer->drawString(labels[10], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[10], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
|
|
||||||
renderer->drawString(displayStrings[20], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[HorizonOCThermalSensor_Battery]); // Battery
|
renderer->drawString(displayStrings[20], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[HorizonOCThermalSensor_Battery]); // Battery
|
||||||
|
if(!IsHoag()) {
|
||||||
|
renderer->drawString(labels[13], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // disp label
|
||||||
|
|
||||||
renderer->drawString(labels[13], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // disp label
|
renderer->drawString(displayStrings[25], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // disp freq
|
||||||
|
}
|
||||||
renderer->drawString(displayStrings[25], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // disp freq
|
|
||||||
|
|
||||||
renderer->drawString(labels[12], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // fan label
|
renderer->drawString(labels[12], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // fan label
|
||||||
|
|
||||||
renderer->drawString(displayStrings[24], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // fan speed
|
renderer->drawString(displayStrings[24], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // fan speed
|
||||||
@@ -167,8 +168,10 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
renderer->drawString(displayStrings[21], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat voltage
|
renderer->drawString(displayStrings[21], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat voltage
|
||||||
renderer->drawString(displayStrings[23], false, positions[2] - 2, y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat Age
|
renderer->drawString(displayStrings[23], false, positions[2] - 2, y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat Age
|
||||||
|
|
||||||
|
if(this->context->isSaltyNXInstalled) {
|
||||||
renderer->drawString(displayStrings[26], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // disp volt
|
renderer->drawString(labels[14], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // FPS label
|
||||||
|
renderer->drawString(displayStrings[26], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // FPS
|
||||||
|
}
|
||||||
|
|
||||||
y+=20;
|
y+=20;
|
||||||
}
|
}
|
||||||
@@ -181,9 +184,9 @@ void BaseMenuGui::refresh()
|
|||||||
if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
|
if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] {
|
||||||
return; // Early exit for most calls
|
return; // Early exit for most calls
|
||||||
}
|
}
|
||||||
|
|
||||||
this->lastContextUpdate = ticks;
|
this->lastContextUpdate = ticks;
|
||||||
|
|
||||||
// Lazy context allocation
|
// Lazy context allocation
|
||||||
if (!this->context) [[unlikely]] {
|
if (!this->context) [[unlikely]] {
|
||||||
this->context = new SysClkContext;
|
this->context = new SysClkContext;
|
||||||
@@ -206,68 +209,72 @@ void BaseMenuGui::refresh()
|
|||||||
// === FORMAT ALL DISPLAY STRINGS (once per second) ===
|
// === FORMAT ALL DISPLAY STRINGS (once per second) ===
|
||||||
// App ID (hex conversion)
|
// App ID (hex conversion)
|
||||||
sprintf(displayStrings[0], "%016lX", context->applicationId);
|
sprintf(displayStrings[0], "%016lX", context->applicationId);
|
||||||
|
|
||||||
// Profile
|
// Profile
|
||||||
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
||||||
|
|
||||||
// Current frequencies
|
// Current frequencies
|
||||||
u32 hz = context->freqs[SysClkModule_CPU]; // CPU
|
u32 hz = context->freqs[SysClkModule_CPU]; // CPU
|
||||||
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->freqs[SysClkModule_GPU]; // GPU
|
hz = context->freqs[SysClkModule_GPU]; // GPU
|
||||||
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->freqs[SysClkModule_MEM]; // MEM
|
hz = context->freqs[SysClkModule_MEM]; // MEM
|
||||||
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
// Real frequencies
|
// Real frequencies
|
||||||
hz = context->realFreqs[SysClkModule_CPU]; // CPU
|
hz = context->realFreqs[SysClkModule_CPU]; // CPU
|
||||||
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->realFreqs[SysClkModule_GPU]; // GPU
|
hz = context->realFreqs[SysClkModule_GPU]; // GPU
|
||||||
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->realFreqs[SysClkModule_MEM]; // MEM
|
hz = context->realFreqs[SysClkModule_MEM]; // MEM
|
||||||
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
// Voltages
|
// Voltages
|
||||||
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);
|
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);
|
||||||
sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0);
|
sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0);
|
||||||
|
|
||||||
// Memory voltage (handle VDD case)
|
switch(configList.values[HorizonOCConfigValue_RAMVoltUsageDisplayMode]) {
|
||||||
if (IsMariko()) {
|
case RamDisplayMode_VDD2VDDQ:
|
||||||
//sprintf(displayStrings[10], "%u%u mV", vddVoltageUv / 1000U, emcVoltageUv / 1000U);
|
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] / 1000U);
|
||||||
//sprintf(displayStrings[10], "%u%.1f mV", vddVoltageUv / 1000U, emcVoltageUv / 1000.0f);
|
break;
|
||||||
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] / 1000U);
|
case RamDisplayMode_VDD2Usage:
|
||||||
} else {
|
sprintf(displayStrings[10], "%u.%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U);
|
||||||
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U);
|
break;
|
||||||
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDD2] / 1000U);
|
case RamDisplayMode_VDDQUsage:
|
||||||
|
sprintf(displayStrings[10], "%u.%u mV", context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] / 1000U, (context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] % 1000U) / 100U);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
strcpy(displayStrings[10], "N/A");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperatures and pre-compute colors
|
// Temperatures and pre-compute colors
|
||||||
u32 millis = context->temps[SysClkThermalSensor_SOC]; // SOC
|
u32 millis = context->temps[SysClkThermalSensor_SOC]; // SOC
|
||||||
sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||||
tempColors[SysClkThermalSensor_SOC] = tsl::GradientColor(millis * 0.001f);
|
tempColors[SysClkThermalSensor_SOC] = tsl::GradientColor(millis * 0.001f);
|
||||||
|
|
||||||
millis = context->temps[SysClkThermalSensor_PCB]; // PCB
|
millis = context->temps[SysClkThermalSensor_PCB]; // PCB
|
||||||
sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||||
tempColors[SysClkThermalSensor_PCB] = tsl::GradientColor(millis * 0.001f);
|
tempColors[SysClkThermalSensor_PCB] = tsl::GradientColor(millis * 0.001f);
|
||||||
|
|
||||||
millis = context->temps[SysClkThermalSensor_Skin]; // Skin
|
millis = context->temps[SysClkThermalSensor_Skin]; // Skin
|
||||||
sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||||
tempColors[SysClkThermalSensor_Skin] = tsl::GradientColor(millis * 0.001f);
|
tempColors[SysClkThermalSensor_Skin] = tsl::GradientColor(millis * 0.001f);
|
||||||
|
|
||||||
// SOC voltage (if available)
|
// SOC voltage (if available)
|
||||||
sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U);
|
sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U);
|
||||||
|
|
||||||
// Power
|
// Power
|
||||||
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
||||||
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
|
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
|
||||||
|
|
||||||
|
|
||||||
sprintf(displayStrings[17], "%u%%", context->partLoad[HocClkPartLoad_GPU] / 10);
|
sprintf(displayStrings[17], "%u%%", context->partLoad[HocClkPartLoad_GPU] / 10);
|
||||||
sprintf(displayStrings[18], "%u%%", context->partLoad[SysClkPartLoad_EMC] / 10);
|
sprintf(displayStrings[18], "%u%%", context->partLoad[SysClkPartLoad_EMC] / 10);
|
||||||
// sprintf(displayStrings[19], "%u", context->partLoad[HocClkPartLoad_CPUAvg]);
|
sprintf(displayStrings[19], "%u%%", context->partLoad[HocClkPartLoad_CPUMax] / 10);
|
||||||
|
|
||||||
millis = context->temps[HorizonOCThermalSensor_Battery]; // Battery
|
millis = context->temps[HorizonOCThermalSensor_Battery]; // Battery
|
||||||
sprintf(displayStrings[20], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
sprintf(displayStrings[20], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U);
|
||||||
@@ -280,15 +287,20 @@ void BaseMenuGui::refresh()
|
|||||||
sprintf(displayStrings[24], "%u%%", context->partLoad[HocClkPartLoad_FAN]);
|
sprintf(displayStrings[24], "%u%%", context->partLoad[HocClkPartLoad_FAN]);
|
||||||
|
|
||||||
sprintf(displayStrings[25], "%u Hz", context->realFreqs[HorizonOCModule_Display]);
|
sprintf(displayStrings[25], "%u Hz", context->realFreqs[HorizonOCModule_Display]);
|
||||||
|
if(this->context->isSaltyNXInstalled) {
|
||||||
//sprintf(displayStrings[26], "%u", context->speedos[HorizonOCSpeedo_CPU]);
|
if(context->fps == 254) {
|
||||||
|
strcpy(displayStrings[26], "N/A");
|
||||||
|
} else {
|
||||||
|
memset(displayStrings[26], 0, sizeof(displayStrings[26]));
|
||||||
|
sprintf(displayStrings[26], "%u", context->fps);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tsl::elm::Element* BaseMenuGui::baseUI()
|
tsl::elm::Element* BaseMenuGui::baseUI()
|
||||||
{
|
{
|
||||||
auto* list = new tsl::elm::List();
|
auto* list = new tsl::elm::List();
|
||||||
list->addItem(new tsl::elm::CustomDrawer([](tsl::gfx::Renderer*, s32, s32, s32, s32) {}), 50); // add a bit of space
|
list->addItem(new tsl::elm::CustomDrawer([](tsl::gfx::Renderer*, s32, s32, s32, s32) {}), 10); // add a bit of space
|
||||||
this->listElement = list;
|
this->listElement = list;
|
||||||
this->listUI();
|
this->listUI();
|
||||||
|
|
||||||
|
|||||||
@@ -118,32 +118,31 @@ void FreqChoiceGui::listUI()
|
|||||||
std::uint32_t hz = this->hzList[i];
|
std::uint32_t hz = this->hzList[i];
|
||||||
uint32_t mhz = hz / 1000000;
|
uint32_t mhz = hz / 1000000;
|
||||||
|
|
||||||
if (checkMax && IsMariko()) {
|
// if (checkMax && IsMariko()) {
|
||||||
if (moduleName == "cpu" &&
|
// if (moduleName == "cpu" &&
|
||||||
this->configList->values[HocClkConfigValue_MarikoMaxCpuClock] < mhz)
|
// this->configList->values[HocClkConfigValue_MarikoMaxCpuClock] < mhz)
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
// // if (moduleName == "gpu" &&
|
||||||
|
// // this->configList->values[HocClkConfigValue_MarikoMaxGpuClock] < mhz)
|
||||||
|
// // continue;
|
||||||
|
|
||||||
|
// // if (moduleName == "mem" &&
|
||||||
|
// // this->configList->values[HocClkConfigValue_MarikoMaxMemClock] < mhz)
|
||||||
|
// // continue;
|
||||||
|
|
||||||
|
if (checkMax && IsErista())
|
||||||
|
if (moduleName == "cpu" && this->configList->values[HocClkConfigValue_EristaMaxCpuClock] < mhz)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// if (moduleName == "gpu" &&
|
// // if (moduleName == "gpu" &&
|
||||||
// this->configList->values[HocClkConfigValue_MarikoMaxGpuClock] < mhz)
|
// // this->configList->values[HocClkConfigValue_EristaMaxGpuClock] < mhz)
|
||||||
// continue;
|
// // continue;
|
||||||
|
|
||||||
// if (moduleName == "mem" &&
|
// // if (moduleName == "mem" &&
|
||||||
// this->configList->values[HocClkConfigValue_MarikoMaxMemClock] < mhz)
|
// // this->configList->values[HocClkConfigValue_EristaMaxMemClock] < mhz)
|
||||||
// continue;
|
// // continue;
|
||||||
|
// }
|
||||||
} else if (checkMax && IsErista()) {
|
|
||||||
if (moduleName == "cpu" &&
|
|
||||||
this->configList->values[HocClkConfigValue_EristaMaxCpuClock] < mhz)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// if (moduleName == "gpu" &&
|
|
||||||
// this->configList->values[HocClkConfigValue_EristaMaxGpuClock] < mhz)
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// if (moduleName == "mem" &&
|
|
||||||
// this->configList->values[HocClkConfigValue_EristaMaxMemClock] < mhz)
|
|
||||||
// continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (moduleName == "mem" && mhz <= 600)
|
if (moduleName == "mem" && mhz <= 600)
|
||||||
continue;
|
continue;
|
||||||
@@ -155,7 +154,7 @@ void FreqChoiceGui::listUI()
|
|||||||
|
|
||||||
if (IsMariko())
|
if (IsMariko())
|
||||||
{
|
{
|
||||||
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1963;
|
unsafe_cpu = this->configList->values[KipConfigValue_marikoCpuUVHigh] ? 2296 : 1964;
|
||||||
if(this->configList->values[KipConfigValue_marikoGpuUV] == 0) {
|
if(this->configList->values[KipConfigValue_marikoGpuUV] == 0) {
|
||||||
unsafe_gpu = 1076;
|
unsafe_gpu = 1076;
|
||||||
} else if (this->configList->values[KipConfigValue_marikoGpuUV] == 1) {
|
} else if (this->configList->values[KipConfigValue_marikoGpuUV] == 1) {
|
||||||
|
|||||||
@@ -99,11 +99,16 @@ void GlobalOverrideGui::addModuleListItemValue(
|
|||||||
const std::string& suffix,
|
const std::string& suffix,
|
||||||
std::uint32_t divisor,
|
std::uint32_t divisor,
|
||||||
int decimalPlaces,
|
int decimalPlaces,
|
||||||
ValueThresholds thresholds
|
ValueThresholds thresholds,
|
||||||
|
const std::vector<NamedValue>& namedValues,
|
||||||
|
bool showDefaultValue
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
bool hasNamedValues = !namedValues.empty();
|
||||||
|
|
||||||
this->customFormatModules[module] = std::make_tuple(suffix, divisor, decimalPlaces);
|
if (!hasNamedValues) {
|
||||||
|
this->customFormatModules[module] = std::make_tuple(suffix, divisor, decimalPlaces);
|
||||||
|
}
|
||||||
|
|
||||||
tsl::elm::ListItem* listItem =
|
tsl::elm::ListItem* listItem =
|
||||||
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
new tsl::elm::ListItem(sysclkFormatModule(module, true));
|
||||||
@@ -121,7 +126,10 @@ void GlobalOverrideGui::addModuleListItemValue(
|
|||||||
suffix,
|
suffix,
|
||||||
divisor,
|
divisor,
|
||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
thresholds](u64 keys)
|
thresholds,
|
||||||
|
namedValues,
|
||||||
|
hasNamedValues,
|
||||||
|
showDefaultValue](u64 keys)
|
||||||
{
|
{
|
||||||
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
if ((keys & HidNpadButton_A) == HidNpadButton_A)
|
||||||
{
|
{
|
||||||
@@ -147,7 +155,7 @@ void GlobalOverrideGui::addModuleListItemValue(
|
|||||||
range,
|
range,
|
||||||
categoryName,
|
categoryName,
|
||||||
|
|
||||||
[this, listItem, module, divisor, suffix, decimalPlaces, thresholds](std::uint32_t value) -> bool
|
[this, listItem, module, divisor, suffix, decimalPlaces, thresholds, namedValues, hasNamedValues, showDefaultValue](std::uint32_t value) -> bool
|
||||||
{
|
{
|
||||||
if (!this->context) {
|
if (!this->context) {
|
||||||
return false;
|
return false;
|
||||||
@@ -158,6 +166,13 @@ void GlobalOverrideGui::addModuleListItemValue(
|
|||||||
|
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
listItem->setValue(FREQ_DEFAULT_TEXT);
|
listItem->setValue(FREQ_DEFAULT_TEXT);
|
||||||
|
} else if (hasNamedValues) {
|
||||||
|
for (const auto& namedValue : namedValues) {
|
||||||
|
if (namedValue.value == value / divisor) {
|
||||||
|
listItem->setValue(namedValue.name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
char buf[32];
|
char buf[32];
|
||||||
if (decimalPlaces > 0) {
|
if (decimalPlaces > 0) {
|
||||||
@@ -188,8 +203,8 @@ void GlobalOverrideGui::addModuleListItemValue(
|
|||||||
thresholds,
|
thresholds,
|
||||||
false,
|
false,
|
||||||
std::map<std::uint32_t, std::string>(),
|
std::map<std::uint32_t, std::string>(),
|
||||||
std::vector<NamedValue>(),
|
namedValues,
|
||||||
true
|
showDefaultValue
|
||||||
);
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -275,6 +290,25 @@ void GlobalOverrideGui::addModuleToggleItem(SysClkModule module)
|
|||||||
this->listItems[module] = toggle;
|
this->listItems[module] = toggle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<NamedValue> governorSettingsE = {
|
||||||
|
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||||
|
NamedValue("Disabled", GovernorState_Disabled),
|
||||||
|
NamedValue("CPU + GPU + VRR", GovernorState_Enabled_CpuGpuVrr),
|
||||||
|
NamedValue("CPU + VRR", GovernorState_Enabled_CpuVrr),
|
||||||
|
NamedValue("GPU + VRR", GovernorState_Enabled_GpuVrr),
|
||||||
|
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||||
|
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||||
|
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||||
|
NamedValue("VRR", GovernorState_Enabled_Vrr),
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<NamedValue> governorSettingsH = {
|
||||||
|
NamedValue("Do Not Override", GovernorState_DoNotOverride),
|
||||||
|
NamedValue("Disabled", GovernorState_Disabled),
|
||||||
|
NamedValue("CPU + GPU", GovernorState_Enabled_CpuGpu),
|
||||||
|
NamedValue("CPU", GovernorState_Enabled_Cpu),
|
||||||
|
NamedValue("GPU", GovernorState_Enabled_Gpu),
|
||||||
|
};
|
||||||
|
|
||||||
void GlobalOverrideGui::listUI()
|
void GlobalOverrideGui::listUI()
|
||||||
{
|
{
|
||||||
@@ -285,16 +319,17 @@ void GlobalOverrideGui::listUI()
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->listElement->addItem(new tsl::elm::CategoryHeader(
|
this->listElement->addItem(new tsl::elm::CategoryHeader(
|
||||||
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " Reset"));
|
"Temporary Overrides " + ult::DIVIDER_SYMBOL + " \ue0e3 Reset"));
|
||||||
this->addModuleListItem(SysClkModule_CPU);
|
this->addModuleListItem(SysClkModule_CPU);
|
||||||
this->addModuleListItem(SysClkModule_GPU);
|
this->addModuleListItem(SysClkModule_GPU);
|
||||||
this->addModuleListItem(SysClkModule_MEM);
|
this->addModuleListItem(SysClkModule_MEM);
|
||||||
#if IS_MINIMAL == 0
|
#if IS_MINIMAL == 0
|
||||||
ValueThresholds lcdThresholds(60, 65);
|
ValueThresholds lcdThresholds(60, 65);
|
||||||
if(!IsHoag() && configList.values[HorizonOCConfigValue_OverwriteRefreshRate])
|
if(configList.values[HorizonOCConfigValue_OverwriteRefreshRate] && !IsHoag())
|
||||||
this->addModuleListItemValue(HorizonOCModule_Display, "Display", 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
this->addModuleListItemValue(HorizonOCModule_Display, "Display", IsAula() ? 45 : 40, configList.values[HorizonOCConfigValue_EnableUnsafeDisplayFreqs] ? IsAula() ? 65 : 72 : 60, 1, " Hz", 1, 0, lcdThresholds);
|
||||||
#endif
|
#endif
|
||||||
this->addModuleToggleItem(HorizonOCModule_Governor);
|
|
||||||
|
this->addModuleListItemValue(HorizonOCModule_Governor, "Governor", 0, 0, 1, "", 1, 0, ValueThresholds(), IsHoag() ? governorSettingsH : governorSettingsE, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GlobalOverrideGui::refresh()
|
void GlobalOverrideGui::refresh()
|
||||||
@@ -306,17 +341,23 @@ void GlobalOverrideGui::refresh()
|
|||||||
|
|
||||||
for (std::uint16_t m = 0; m < SysClkModule_EnumMax; m++) {
|
for (std::uint16_t m = 0; m < SysClkModule_EnumMax; m++) {
|
||||||
if (m == HorizonOCModule_Governor) {
|
if (m == HorizonOCModule_Governor) {
|
||||||
auto *toggle =
|
if (this->listItems[m] != nullptr &&
|
||||||
static_cast<tsl::elm::ToggleListItem *>(this->listItems[m]);
|
this->listHz[m] != this->context->overrideFreqs[m]) {
|
||||||
if (!toggle)
|
|
||||||
continue;
|
std::string displayText = FREQ_DEFAULT_TEXT;
|
||||||
|
std::uint32_t currentValue = this->context->overrideFreqs[m];
|
||||||
|
|
||||||
|
|
||||||
bool newState = this->context->overrideFreqs[m] != 0;
|
for (const auto& setting : governorSettingsE) {
|
||||||
|
if (setting.value == currentValue) {
|
||||||
if (toggle->getState() != newState) {
|
displayText = setting.name;
|
||||||
toggle->setState(newState);
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->listItems[m]->setValue(displayText);
|
||||||
|
this->listHz[m] = currentValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
*
|
||||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
@@ -23,10 +24,7 @@
|
|||||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../ipc.h"
|
#include "../../ipc.h"
|
||||||
#include "base_menu_gui.h"
|
#include "base_menu_gui.h"
|
||||||
#include "freq_choice_gui.h"
|
#include "freq_choice_gui.h"
|
||||||
@@ -63,7 +61,9 @@ class GlobalOverrideGui : public BaseMenuGui
|
|||||||
const std::string& suffix,
|
const std::string& suffix,
|
||||||
std::uint32_t divisor,
|
std::uint32_t divisor,
|
||||||
int decimalPlaces,
|
int decimalPlaces,
|
||||||
ValueThresholds thresholds = {}
|
ValueThresholds thresholds = {},
|
||||||
|
const std::vector<NamedValue>& namedValues = {},
|
||||||
|
bool showDefaultValue = true
|
||||||
);
|
);
|
||||||
public:
|
public:
|
||||||
GlobalOverrideGui();
|
GlobalOverrideGui();
|
||||||
@@ -71,4 +71,4 @@ class GlobalOverrideGui : public BaseMenuGui
|
|||||||
void listUI() override;
|
void listUI() override;
|
||||||
void refresh() override;
|
void refresh() override;
|
||||||
void setModuleCustomFormat(SysClkModule module, const std::string& suffix, std::uint32_t divisor, int decimalPlaces);
|
void setModuleCustomFormat(SysClkModule module, const std::string& suffix, std::uint32_t divisor, int decimalPlaces);
|
||||||
};
|
};
|
||||||
@@ -35,7 +35,7 @@ std::map<uint32_t, std::string> cpu_freq_label_e = {
|
|||||||
{1224000000, "Dev OC"},
|
{1224000000, "Dev OC"},
|
||||||
{1785000000, "Boost Mode & Safe Max"},
|
{1785000000, "Boost Mode & Safe Max"},
|
||||||
{2091000000, "Unsafe Max"},
|
{2091000000, "Unsafe Max"},
|
||||||
{2295000000, "Absolute Max"},
|
{2397000000, "Absolute Max"},
|
||||||
};
|
};
|
||||||
std::map<uint32_t, std::string> gpu_freq_label_e = {
|
std::map<uint32_t, std::string> gpu_freq_label_e = {
|
||||||
{76800000, "Boost Mode"},
|
{76800000, "Boost Mode"},
|
||||||
@@ -47,7 +47,7 @@ std::map<uint32_t, std::string> gpu_freq_label_e = {
|
|||||||
{768000000, "Docked"},
|
{768000000, "Docked"},
|
||||||
{921600000, "Safe Max"},
|
{921600000, "Safe Max"},
|
||||||
{960000000, "Unsafe Max"},
|
{960000000, "Unsafe Max"},
|
||||||
{1075200000, "Aboslute Max"},
|
{1075200000, "Absolute Max"},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<uint32_t, std::string> gpu_freq_label_m = {
|
std::map<uint32_t, std::string> gpu_freq_label_m = {
|
||||||
@@ -59,5 +59,6 @@ std::map<uint32_t, std::string> gpu_freq_label_m = {
|
|||||||
{768000000, "Docked"},
|
{768000000, "Docked"},
|
||||||
{1075200000, "Safe Max"},
|
{1075200000, "Safe Max"},
|
||||||
{1305600000, "Unsafe Max"},
|
{1305600000, "Unsafe Max"},
|
||||||
{1536000000, "Aboslute Max"},
|
{1536000000, "Absolute Max"},
|
||||||
};
|
|
||||||
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
*
|
*
|
||||||
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
* Copyright (c) Souldbminer, Lightos_ and Horizon OC Contributors
|
||||||
@@ -19,12 +18,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "../../ipc.h"
|
#include "../../ipc.h"
|
||||||
#include "base_menu_gui.h"
|
#include "base_menu_gui.h"
|
||||||
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "freq_choice_gui.h"
|
#include "freq_choice_gui.h"
|
||||||
#include "value_choice_gui.h"
|
#include "value_choice_gui.h"
|
||||||
|
|
||||||
class MiscGui : public BaseMenuGui
|
class MiscGui : public BaseMenuGui
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -40,6 +39,8 @@ protected:
|
|||||||
std::map<SysClkConfigValue, std::vector<NamedValue>> configNamedValues;
|
std::map<SysClkConfigValue, std::vector<NamedValue>> configNamedValues;
|
||||||
std::map<SysClkConfigValue, tsl::elm::ToggleListItem*> configToggles;
|
std::map<SysClkConfigValue, tsl::elm::ToggleListItem*> configToggles;
|
||||||
std::map<SysClkConfigValue, std::tuple<tsl::elm::TrackBar*, tsl::elm::ListItem*, std::vector<uint64_t>>> configTrackbars;
|
std::map<SysClkConfigValue, std::tuple<tsl::elm::TrackBar*, tsl::elm::ListItem*, std::vector<uint64_t>>> configTrackbars;
|
||||||
|
std::set<SysClkConfigValue> configButtonSKeys;
|
||||||
|
std::map<SysClkConfigValue, std::string> configButtonSSubtext;
|
||||||
|
|
||||||
void addConfigToggle(SysClkConfigValue configVal, const char* altName);
|
void addConfigToggle(SysClkConfigValue configVal, const char* altName);
|
||||||
void addConfigButton(SysClkConfigValue configVal,
|
void addConfigButton(SysClkConfigValue configVal,
|
||||||
@@ -50,6 +51,16 @@ protected:
|
|||||||
const std::map<uint32_t, std::string>& labels = {},
|
const std::map<uint32_t, std::string>& labels = {},
|
||||||
const std::vector<NamedValue>& namedValues = {},
|
const std::vector<NamedValue>& namedValues = {},
|
||||||
bool showDefaultValue = true);
|
bool showDefaultValue = true);
|
||||||
|
|
||||||
|
void addConfigButtonS(SysClkConfigValue configVal,
|
||||||
|
const char* altName,
|
||||||
|
const ValueRange& range,
|
||||||
|
const std::string& categoryName,
|
||||||
|
const ValueThresholds* thresholds,
|
||||||
|
const std::map<uint32_t, std::string>& labels = {},
|
||||||
|
const std::vector<NamedValue>& namedValues = {},
|
||||||
|
bool showDefaultValue = true,
|
||||||
|
const char* subText = nullptr);
|
||||||
void addFreqButton(SysClkConfigValue configVal,
|
void addFreqButton(SysClkConfigValue configVal,
|
||||||
const char* altName,
|
const char* altName,
|
||||||
SysClkModule module,
|
SysClkModule module,
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ ValueChoiceGui::ValueChoiceGui(std::uint32_t selectedValue,
|
|||||||
bool enableThresholds,
|
bool enableThresholds,
|
||||||
std::map<std::uint32_t, std::string> labels,
|
std::map<std::uint32_t, std::string> labels,
|
||||||
std::vector<NamedValue> namedValues,
|
std::vector<NamedValue> namedValues,
|
||||||
bool showDefaultValue)
|
bool showDefaultValue,
|
||||||
|
bool showDNO)
|
||||||
: selectedValue(selectedValue),
|
: selectedValue(selectedValue),
|
||||||
range(range),
|
range(range),
|
||||||
categoryName(categoryName),
|
categoryName(categoryName),
|
||||||
@@ -39,7 +40,8 @@ ValueChoiceGui::ValueChoiceGui(std::uint32_t selectedValue,
|
|||||||
enableThresholds(enableThresholds),
|
enableThresholds(enableThresholds),
|
||||||
labels(labels),
|
labels(labels),
|
||||||
namedValues(namedValues),
|
namedValues(namedValues),
|
||||||
showDefaultValue(showDefaultValue)
|
showDefaultValue(showDefaultValue),
|
||||||
|
showDNO(showDNO)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +54,7 @@ std::string ValueChoiceGui::formatValue(std::uint32_t value)
|
|||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
if(showDefaultValue) {
|
if(showDefaultValue) {
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
return VALUE_DEFAULT_TEXT;
|
return this->showDNO ? FREQ_DEFAULT_TEXT : VALUE_DEFAULT_TEXT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
double displayValue = static_cast<double>(value) / static_cast<double>(range.divisor);
|
double displayValue = static_cast<double>(value) / static_cast<double>(range.divisor);
|
||||||
@@ -164,17 +166,16 @@ void ValueChoiceGui::listUI()
|
|||||||
if (!categoryName.empty()) {
|
if (!categoryName.empty()) {
|
||||||
this->listElement->addItem(new tsl::elm::CategoryHeader(categoryName));
|
this->listElement->addItem(new tsl::elm::CategoryHeader(categoryName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showDefaultValue) {
|
||||||
|
this->listElement->addItem(this->createValueListItem(0, this->selectedValue == 0, 0));
|
||||||
|
}
|
||||||
for (const auto& namedValue : namedValues) {
|
for (const auto& namedValue : namedValues) {
|
||||||
int safety = enableThresholds ? getSafetyLevel(namedValue.value) : 0;
|
int safety = enableThresholds ? getSafetyLevel(namedValue.value) : 0;
|
||||||
bool selected = (namedValue.value == this->selectedValue);
|
bool selected = (namedValue.value == this->selectedValue);
|
||||||
this->listElement->addItem(this->createNamedValueListItem(namedValue, selected, safety));
|
this->listElement->addItem(this->createNamedValueListItem(namedValue, selected, safety));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (showDefaultValue) {
|
|
||||||
this->listElement->addItem(this->createValueListItem(0, this->selectedValue == 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namedValues.empty()) {
|
if (namedValues.empty()) {
|
||||||
for (std::uint32_t value = range.min; value <= range.max; value += range.step)
|
for (std::uint32_t value = range.min; value <= range.max; value += range.step)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ protected:
|
|||||||
|
|
||||||
std::vector<NamedValue> namedValues;
|
std::vector<NamedValue> namedValues;
|
||||||
bool showDefaultValue = true;
|
bool showDefaultValue = true;
|
||||||
|
bool showDNO = false;
|
||||||
tsl::elm::ListItem* createValueListItem(std::uint32_t value, bool selected, int safety);
|
tsl::elm::ListItem* createValueListItem(std::uint32_t value, bool selected, int safety);
|
||||||
tsl::elm::ListItem* createNamedValueListItem(const NamedValue& namedValue, bool selected, int safety);
|
tsl::elm::ListItem* createNamedValueListItem(const NamedValue& namedValue, bool selected, int safety);
|
||||||
std::string formatValue(std::uint32_t value);
|
std::string formatValue(std::uint32_t value);
|
||||||
@@ -86,7 +86,8 @@ public:
|
|||||||
bool enableThresholds = false,
|
bool enableThresholds = false,
|
||||||
std::map<std::uint32_t, std::string> labels = {},
|
std::map<std::uint32_t, std::string> labels = {},
|
||||||
std::vector<NamedValue> namedValues = {},
|
std::vector<NamedValue> namedValues = {},
|
||||||
bool showDefaultValue = true);
|
bool showDefaultValue = true,
|
||||||
|
bool showDNO = false);
|
||||||
~ValueChoiceGui();
|
~ValueChoiceGui();
|
||||||
|
|
||||||
void addNamedValue(const std::string& name, std::uint32_t value, const std::string& rightText = "")
|
void addNamedValue(const std::string& name, std::uint32_t value, const std::string& rightText = "")
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ DEFINES := -DDISABLE_IPC -DTARGET="\"$(TARGET)\"" -DTARGET_VERSION="\"$(TARGET_V
|
|||||||
|
|
||||||
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
|
||||||
|
|
||||||
CFLAGS := -g -Wall -O2 -ffunction-sections \
|
CFLAGS := -g -Wall -Os -ffunction-sections \
|
||||||
$(ARCH) $(DEFINES)
|
$(ARCH) $(DEFINES)
|
||||||
|
|
||||||
CFLAGS += $(INCLUDE) -D__SWITCH__
|
CFLAGS += $(INCLUDE) -D__SWITCH__
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2020-2023 CTCaer
|
* Copyright (c) 2020-2023 CTCaer
|
||||||
* Copyright (c) 2023 p-sam
|
* Copyright (c) 2023 p-sam
|
||||||
|
* Copyright (c) 2026 Souldbminer
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms and conditions of the GNU General Public License,
|
* under the terms and conditions of the GNU General Public License,
|
||||||
@@ -47,7 +48,7 @@
|
|||||||
|
|
||||||
#define PTO_CLK_CNT_BUSY BIT(31)
|
#define PTO_CLK_CNT_BUSY BIT(31)
|
||||||
#define PTO_CLK_CNT 0xFFFFFF
|
#define PTO_CLK_CNT 0xFFFFFF
|
||||||
#define CLK_PTO_CCLK_G 0x12
|
#define CLK_PTO_CCLK_G_DIV2 0x13
|
||||||
#define CLK_PTO_EMC 0x24
|
#define CLK_PTO_EMC 0x24
|
||||||
|
|
||||||
#define CLOCK(x) (*(volatile u32 *)(g_clk_base + (x)))
|
#define CLOCK(x) (*(volatile u32 *)(g_clk_base + (x)))
|
||||||
@@ -117,7 +118,7 @@ static u32 g_mem_freq = 0;
|
|||||||
static u32 g_emc_lall = 0;
|
static u32 g_emc_lall = 0;
|
||||||
static u32 g_emc_lcpu = 0;
|
static u32 g_emc_lcpu = 0;
|
||||||
|
|
||||||
static u32 _clock_get_dev_freq(u32 id)
|
static u32 _clock_get_dev_freq(u32 id, u32 multiplier)
|
||||||
{
|
{
|
||||||
const u32 pto_win = 16;
|
const u32 pto_win = 16;
|
||||||
const u32 pto_osc = 32768;
|
const u32 pto_osc = 32768;
|
||||||
@@ -148,7 +149,7 @@ static u32 _clock_get_dev_freq(u32 id)
|
|||||||
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
(void)CLOCK(CLK_RST_CONTROLLER_PTO_CLK_CNT_CNTL);
|
||||||
usleep(2);
|
usleep(2);
|
||||||
|
|
||||||
u32 freq_khz = (u64)cnt * pto_osc / pto_win / 1000;
|
u32 freq_khz = (u64)cnt * multiplier * pto_osc / pto_win;
|
||||||
|
|
||||||
return freq_khz;
|
return freq_khz;
|
||||||
}
|
}
|
||||||
@@ -203,8 +204,8 @@ static void _clock_update_freqs(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC) * 1000;
|
g_mem_freq = _clock_get_dev_freq(CLK_PTO_EMC, 1);
|
||||||
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G) * 1000;
|
g_cpu_freq = _clock_get_dev_freq(CLK_PTO_CCLK_G_DIV2, 2);
|
||||||
|
|
||||||
if (!g_gpu_base)
|
if (!g_gpu_base)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
"title_id": "0x00FF0000636C6BFF",
|
"title_id": "0x00FF0000636C6BFF",
|
||||||
"title_id_range_min": "0x00FF0000636C6BFF",
|
"title_id_range_min": "0x00FF0000636C6BFF",
|
||||||
"title_id_range_max": "0x00FF0000636C6BFF",
|
"title_id_range_max": "0x00FF0000636C6BFF",
|
||||||
"main_thread_stack_size": "0x00008000",
|
"main_thread_stack_size": "0x0000C000",
|
||||||
"main_thread_priority": 63,
|
"main_thread_priority": 16,
|
||||||
"default_cpu_id": 3,
|
"default_cpu_id": 3,
|
||||||
"process_category": 0,
|
"process_category": 1,
|
||||||
"is_retail": true,
|
"is_retail": true,
|
||||||
"pool_partition": 2,
|
"pool_partition": 2,
|
||||||
"is_64_bit": true,
|
"is_64_bit": true,
|
||||||
"address_space_type": 1,
|
"address_space_type": 3,
|
||||||
"filesystem_access": {
|
"filesystem_access": {
|
||||||
"permissions": "0xFFFFFFFFFFFFFFFF"
|
"permissions": "0xFFFFFFFFFFFFFFFF"
|
||||||
},
|
},
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"type": "kernel_flags",
|
"type": "kernel_flags",
|
||||||
"value": {
|
"value": {
|
||||||
"highest_thread_priority": 63,
|
"highest_thread_priority": 63,
|
||||||
"lowest_thread_priority": 41,
|
"lowest_thread_priority": 16,
|
||||||
"lowest_cpu_id": 0,
|
"lowest_cpu_id": 0,
|
||||||
"highest_cpu_id": 3
|
"highest_cpu_id": 3
|
||||||
}
|
}
|
||||||
@@ -57,6 +57,15 @@
|
|||||||
"is_io": true
|
"is_io": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "map",
|
||||||
|
"value": {
|
||||||
|
"address": "0x70110000",
|
||||||
|
"size": "0x1000",
|
||||||
|
"is_ro": false,
|
||||||
|
"is_io": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "syscalls",
|
"type": "syscalls",
|
||||||
"value": {
|
"value": {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -41,6 +41,8 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <registers.h>
|
#include <registers.h>
|
||||||
#include <notification.h>
|
#include <notification.h>
|
||||||
|
#include <memmem.h>
|
||||||
|
#include <minIni.h>
|
||||||
|
|
||||||
#define MAX(A, B) std::max(A, B)
|
#define MAX(A, B) std::max(A, B)
|
||||||
#define MIN(A, B) std::min(A, B)
|
#define MIN(A, B) std::min(A, B)
|
||||||
@@ -64,12 +66,16 @@
|
|||||||
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
||||||
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
|
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
|
||||||
#define NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD 0x80044715
|
#define NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD 0x80044715
|
||||||
|
#define NVSCHED_CTRL_ENABLE 0x00000601
|
||||||
|
#define NVSCHED_CTRL_DISABLE 0x00000602
|
||||||
|
|
||||||
#define systemtickfrequency 19200000
|
constexpr u64 CpuTimeOutNs = 500'000'000;
|
||||||
#define systemtickfrequencyF 19200000.0f
|
constexpr double Systemtickfrequency = 19200000.0 * (static_cast<double>(CpuTimeOutNs) / 1'000'000'000.0);
|
||||||
#define CPU_TICK_WAIT (1'000'000'000 / 60)
|
Result nvInitialize_rc;
|
||||||
Result nvCheck = 1;
|
Result nvCheck = 1;
|
||||||
|
Result nvCheck_sched = 1;
|
||||||
|
|
||||||
|
LEvent threadexit;
|
||||||
Thread gpuLThread;
|
Thread gpuLThread;
|
||||||
Thread cpuCore0Thread;
|
Thread cpuCore0Thread;
|
||||||
Thread cpuCore1Thread;
|
Thread cpuCore1Thread;
|
||||||
@@ -84,20 +90,37 @@ Result pwmDutyCycleCheck = 1;
|
|||||||
double Rotation_Duty = 0;
|
double Rotation_Duty = 0;
|
||||||
u8 fanLevel;
|
u8 fanLevel;
|
||||||
|
|
||||||
uint32_t GPU_Load_u = 0, fd = 0;
|
uint32_t GPU_Load_u = 0, fd = 0, fd2 = 0;
|
||||||
BatteryChargeInfo info;
|
BatteryChargeInfo info;
|
||||||
|
|
||||||
static SysClkSocType g_socType = SysClkSocType_Erista;
|
static SysClkSocType g_socType = SysClkSocType_Erista;
|
||||||
static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Iowa;
|
static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Iowa;
|
||||||
|
|
||||||
std::atomic<uint64_t> idletick0{systemtickfrequency};
|
u64 idletick0 = 0;
|
||||||
std::atomic<uint64_t> idletick1{systemtickfrequency};
|
u64 idletick1 = 0;
|
||||||
std::atomic<uint64_t> idletick2{systemtickfrequency};
|
u64 idletick2 = 0;
|
||||||
std::atomic<uint64_t> idletick3{systemtickfrequency};
|
// u64 idletick3 = 0;
|
||||||
|
|
||||||
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
||||||
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC
|
||||||
|
u32 speedoBracket;
|
||||||
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
u16 cpuIDDQ, gpuIDDQ, socIDDQ;
|
||||||
u8 g_dramID = 0;
|
u8 g_dramID = 0;
|
||||||
|
u64 cldvfs, cldvfs_temp;
|
||||||
|
u32 cachedEristaUvLowTune0 = 0, cachedEristaUvLowTune1 = 0, cachedMarikoUvHighTune0 = 0;
|
||||||
|
|
||||||
|
static const u32 ramBrackets[][22] = {
|
||||||
|
{ 2133, 2200, 2266, 2300, 2366, 2400, 2433, 2466, 2533, 2566, 2600, 2633, 2700, 2733, 2766, 2833, 2866, 2900, 2933, 3033, 3066, 3100, },
|
||||||
|
{ 2300, 2366, 2433, 2466, 2533, 2566, 2633, 2700, 2733, 2800, 2833, 2900, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3266, },
|
||||||
|
{ 2433, 2466, 2533, 2600, 2666, 2733, 2766, 2800, 2833, 2866, 2933, 2966, 3033, 3066, 3100, 3133, 3166, 3200, 3233, 3300, 3333, 3366, },
|
||||||
|
{ 2500, 2533, 2600, 2633, 2666, 2733, 2800, 2866, 2900, 2966, 3033, 3100, 3166, 3200, 3233, 3266, 3300, 3333, 3366, 3400, 3400, 3400, },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const u32 gpuDvfsArray[] = { 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800};
|
||||||
|
|
||||||
|
u32 dvfsTable[6][32] = {};
|
||||||
|
u64 dvfsAddress;
|
||||||
|
u32 ramVmin;
|
||||||
|
|
||||||
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
||||||
{
|
{
|
||||||
@@ -149,16 +172,16 @@ PcvModuleId Board::GetPcvModuleId(SysClkModule sysclkModule)
|
|||||||
return pcvModuleId;
|
return pcvModuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CheckCore(void* idletick_ptr) {
|
void CheckCore(void *idletickPtr) {
|
||||||
std::atomic<uint64_t>* idletick = (std::atomic<uint64_t>*)idletick_ptr;
|
u64* idletick = static_cast<u64 *>(idletickPtr);
|
||||||
while (true) {
|
while(true) {
|
||||||
uint64_t idletick_a;
|
u64 idletickA;
|
||||||
uint64_t idletick_b;
|
u64 idletickB;
|
||||||
svcGetInfo(&idletick_b, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
svcGetInfo(&idletickB, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||||
svcSleepThread(CPU_TICK_WAIT);
|
svcWaitForAddress(&threadexit, ArbitrationType_WaitIfEqual, 0, CpuTimeOutNs);
|
||||||
svcGetInfo(&idletick_a, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
svcGetInfo(&idletickA, InfoType_IdleTickCount, INVALID_HANDLE, -1);
|
||||||
idletick->store(idletick_a - idletick_b, std::memory_order_release);
|
*idletick = idletickA - idletickB;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void gpuLoadThread(void*) {
|
void gpuLoadThread(void*) {
|
||||||
@@ -190,7 +213,6 @@ void miscThreadFunc(void*) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Initialize()
|
void Board::Initialize()
|
||||||
{
|
{
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
@@ -222,8 +244,11 @@ void Board::Initialize()
|
|||||||
|
|
||||||
rc = tmp451Initialize();
|
rc = tmp451Initialize();
|
||||||
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
||||||
|
nvInitialize_rc = nvInitialize();
|
||||||
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
if (R_SUCCEEDED(nvInitialize_rc)) {
|
||||||
|
nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
||||||
|
nvCheck_sched = nvOpen(&fd2, "/dev/nvsched-ctrl");
|
||||||
|
}
|
||||||
|
|
||||||
rc = rgltrInitialize();
|
rc = rgltrInitialize();
|
||||||
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
||||||
@@ -238,24 +263,26 @@ void Board::Initialize()
|
|||||||
|
|
||||||
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
||||||
threadStart(&gpuLThread);
|
threadStart(&gpuLThread);
|
||||||
|
leventClear(&threadexit);
|
||||||
threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x500, 0x10, 0);
|
threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0);
|
||||||
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x500, 0x10, 1);
|
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1);
|
||||||
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x500, 0x10, 2);
|
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2);
|
||||||
threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x500, 0x10, 3);
|
// threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3);
|
||||||
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x3F, 3);
|
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x10, 3);
|
||||||
|
|
||||||
threadStart(&cpuCore0Thread);
|
threadStart(&cpuCore0Thread);
|
||||||
threadStart(&cpuCore1Thread);
|
threadStart(&cpuCore1Thread);
|
||||||
threadStart(&cpuCore2Thread);
|
threadStart(&cpuCore2Thread);
|
||||||
threadStart(&cpuCore3Thread);
|
// threadStart(&cpuCore3Thread);
|
||||||
threadStart(&miscThread);
|
threadStart(&miscThread);
|
||||||
batteryInfoInitialize();
|
batteryInfoInitialize();
|
||||||
|
FetchHardwareInfos();
|
||||||
|
|
||||||
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
|
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
|
||||||
pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001);
|
pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001);
|
||||||
}
|
}
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
|
||||||
|
if(!IsHoag()) {
|
||||||
u64 clkVirtAddr, dsiVirtAddr, outsize;
|
u64 clkVirtAddr, dsiVirtAddr, outsize;
|
||||||
rc = svcQueryMemoryMapping(&clkVirtAddr, &outsize, 0x60006000, 0x1000);
|
rc = svcQueryMemoryMapping(&clkVirtAddr, &outsize, 0x60006000, 0x1000);
|
||||||
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (clk)");
|
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (clk)");
|
||||||
@@ -267,7 +294,19 @@ void Board::Initialize()
|
|||||||
DisplayRefresh_Initialize(&cfg);
|
DisplayRefresh_Initialize(&cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
FetchHardwareInfos();
|
rc = svcQueryMemoryMapping(&cldvfs, &cldvfs_temp, CLDVFS_REGION_BASE, CLDVFS_REGION_SIZE);
|
||||||
|
ASSERT_RESULT_OK(rc, "svcQueryMemoryMapping (cldvfs)");
|
||||||
|
|
||||||
|
if(Board::GetSocType() == SysClkSocType_Erista) {
|
||||||
|
cachedEristaUvLowTune0 = *(u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||||
|
cachedEristaUvLowTune1 = *(u32*)(cldvfs + CL_DVFS_TUNE1_0);
|
||||||
|
} else {
|
||||||
|
Board::SetHz(SysClkModule_CPU, 1785000000);
|
||||||
|
cachedMarikoUvHighTune0 = *(u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||||
|
Board::ResetToStockCpu();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Board::fuseReadSpeedos() {
|
void Board::fuseReadSpeedos() {
|
||||||
@@ -311,7 +350,7 @@ void Board::fuseReadSpeedos() {
|
|||||||
cpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_CPU_IDDQ_CALIB);
|
cpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_CPU_IDDQ_CALIB);
|
||||||
gpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_SOC_IDDQ_CALIB);
|
gpuIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_SOC_IDDQ_CALIB);
|
||||||
socIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_GPU_IDDQ_CALIB);
|
socIDDQ = *reinterpret_cast<const u16*>(dump + FUSE_GPU_IDDQ_CALIB);
|
||||||
|
|
||||||
svcCloseHandle(debug);
|
svcCloseHandle(debug);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -378,7 +417,7 @@ void Board::Exit()
|
|||||||
threadClose(&cpuCore0Thread);
|
threadClose(&cpuCore0Thread);
|
||||||
threadClose(&cpuCore1Thread);
|
threadClose(&cpuCore1Thread);
|
||||||
threadClose(&cpuCore2Thread);
|
threadClose(&cpuCore2Thread);
|
||||||
threadClose(&cpuCore3Thread);
|
// threadClose(&cpuCore3Thread);
|
||||||
threadClose(&miscThread);
|
threadClose(&miscThread);
|
||||||
|
|
||||||
pwmChannelSessionClose(&g_ICon);
|
pwmChannelSessionClose(&g_ICon);
|
||||||
@@ -386,7 +425,8 @@ void Board::Exit()
|
|||||||
rgltrExit();
|
rgltrExit();
|
||||||
batteryInfoExit();
|
batteryInfoExit();
|
||||||
pmdmntExit();
|
pmdmntExit();
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
nvExit();
|
||||||
|
if(!IsHoag())
|
||||||
DisplayRefresh_Shutdown();
|
DisplayRefresh_Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,9 +461,9 @@ SysClkProfile Board::GetProfile()
|
|||||||
void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
||||||
{
|
{
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
|
if(module == HorizonOCModule_Display) {
|
||||||
if(module == HorizonOCModule_Display && Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
if(!IsHoag())
|
||||||
DisplayRefresh_SetRate(hz);
|
DisplayRefresh_SetRate(hz);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(module > SysClkModule_MEM)
|
if(module > SysClkModule_MEM)
|
||||||
@@ -436,13 +476,22 @@ void Board::SetHz(SysClkModule module, std::uint32_t hz)
|
|||||||
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
ASSERT_RESULT_OK(rc, "clkrstOpenSession");
|
||||||
rc = clkrstSetClockRate(&session, hz);
|
rc = clkrstSetClockRate(&session, hz);
|
||||||
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||||
|
if (module == SysClkModule_CPU) {
|
||||||
|
svcSleepThread(200'000);
|
||||||
|
rc = clkrstSetClockRate(&session, hz);
|
||||||
|
ASSERT_RESULT_OK(rc, "clkrstSetClockRate");
|
||||||
|
}
|
||||||
clkrstCloseSession(&session);
|
clkrstCloseSession(&session);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||||
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||||
|
if (module == SysClkModule_CPU) {
|
||||||
|
svcSleepThread(200'000);
|
||||||
|
rc = pcvSetClockRate(Board::GetPcvModule(module), hz);
|
||||||
|
ASSERT_RESULT_OK(rc, "pcvSetClockRate");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,13 +501,13 @@ std::uint32_t Board::GetHz(SysClkModule module)
|
|||||||
std::uint32_t hz = 0;
|
std::uint32_t hz = 0;
|
||||||
|
|
||||||
if(module == HorizonOCModule_Display) {
|
if(module == HorizonOCModule_Display) {
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
if(!IsHoag())
|
||||||
DisplayRefresh_GetRate(&hz, false);
|
DisplayRefresh_GetRate(&hz, false);
|
||||||
else
|
else
|
||||||
hz = 60;
|
hz = 60;
|
||||||
return hz;
|
return hz;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(HOSSVC_HAS_CLKRST)
|
if(HOSSVC_HAS_CLKRST)
|
||||||
{
|
{
|
||||||
ClkrstSession session = {0};
|
ClkrstSession session = {0};
|
||||||
@@ -492,7 +541,7 @@ std::uint32_t Board::GetRealHz(SysClkModule module)
|
|||||||
case SysClkModule_MEM:
|
case SysClkModule_MEM:
|
||||||
return t210ClkMemFreq();
|
return t210ClkMemFreq();
|
||||||
case HorizonOCModule_Display:
|
case HorizonOCModule_Display:
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
if(!IsHoag())
|
||||||
DisplayRefresh_GetRate(&hz, false);
|
DisplayRefresh_GetRate(&hz, false);
|
||||||
else
|
else
|
||||||
hz = 60;
|
hz = 60;
|
||||||
@@ -690,14 +739,14 @@ void Board::ResetToStockGpu()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Board::ResetToStockDisplay() {
|
void Board::ResetToStockDisplay() {
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
if(!IsHoag())
|
||||||
DisplayRefresh_SetRate(60);
|
DisplayRefresh_SetRate(60);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 Board::GetHighestDockedDisplayRate() {
|
u8 Board::GetHighestDockedDisplayRate() {
|
||||||
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag)
|
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||||
return DisplayRefresh_GetDockedHighestAllowed();
|
return DisplayRefresh_GetDockedHighestAllowed();
|
||||||
else
|
} else
|
||||||
return 60;
|
return 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,8 +801,17 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 GetMaxCpuLoad() {
|
||||||
|
float cpuUsage0 = std::clamp(((Systemtickfrequency - idletick0) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||||
|
float cpuUsage1 = std::clamp(((Systemtickfrequency - idletick1) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||||
|
float cpuUsage2 = std::clamp(((Systemtickfrequency - idletick2) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||||
|
// float cpuUsage3 = std::clamp(((Systemtickfrequency - idletick3) / static_cast<double>(Systemtickfrequency)) * 1000.0, 0.0, 1000.0);
|
||||||
|
|
||||||
|
return std::round(std::max({cpuUsage0, cpuUsage1, cpuUsage2}));
|
||||||
|
}
|
||||||
|
|
||||||
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
||||||
{
|
{
|
||||||
switch(loadSource)
|
switch(loadSource)
|
||||||
{
|
{
|
||||||
case SysClkPartLoad_EMC:
|
case SysClkPartLoad_EMC:
|
||||||
@@ -762,8 +820,8 @@ std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
|||||||
return t210EmcLoadCpu();
|
return t210EmcLoadCpu();
|
||||||
case HocClkPartLoad_GPU:
|
case HocClkPartLoad_GPU:
|
||||||
return GPU_Load_u;
|
return GPU_Load_u;
|
||||||
case HocClkPartLoad_CPUAvg:
|
case HocClkPartLoad_CPUMax:
|
||||||
return idletick0;
|
return GetMaxCpuLoad();
|
||||||
case HocClkPartLoad_BAT:
|
case HocClkPartLoad_BAT:
|
||||||
batteryInfoGetChargeInfo(&info);
|
batteryInfoGetChargeInfo(&info);
|
||||||
return info.RawBatteryCharge;
|
return info.RawBatteryCharge;
|
||||||
@@ -792,6 +850,7 @@ u8 Board::GetDramID() {
|
|||||||
void Board::FetchHardwareInfos()
|
void Board::FetchHardwareInfos()
|
||||||
{
|
{
|
||||||
fuseReadSpeedos();
|
fuseReadSpeedos();
|
||||||
|
SetSpeedoBracket();
|
||||||
u64 sku = 0, dramID = 0;
|
u64 sku = 0, dramID = 0;
|
||||||
Result rc = splInitialize();
|
Result rc = splInitialize();
|
||||||
ASSERT_RESULT_OK(rc, "splInitialize");
|
ASSERT_RESULT_OK(rc, "splInitialize");
|
||||||
@@ -801,7 +860,7 @@ void Board::FetchHardwareInfos()
|
|||||||
|
|
||||||
rc = splGetConfig(SplConfigItem_DramId, &dramID);
|
rc = splGetConfig(SplConfigItem_DramId, &dramID);
|
||||||
ASSERT_RESULT_OK(rc, "splGetConfig");
|
ASSERT_RESULT_OK(rc, "splGetConfig");
|
||||||
|
|
||||||
splExit();
|
splExit();
|
||||||
|
|
||||||
switch(sku)
|
switch(sku)
|
||||||
@@ -816,9 +875,12 @@ void Board::FetchHardwareInfos()
|
|||||||
g_socType = SysClkSocType_Erista;
|
g_socType = SysClkSocType_Erista;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_socType == SysClkSocType_Mariko) {
|
||||||
|
CacheDvfsTable();
|
||||||
|
}
|
||||||
|
|
||||||
g_consoleType = (HorizonOCConsoleType)sku;
|
g_consoleType = (HorizonOCConsoleType)sku;
|
||||||
g_dramID = (u8)dramID;
|
g_dramID = (u8)dramID;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -926,174 +988,341 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
|||||||
return out > 0 ? out : 0;
|
return out > 0 ? out : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MC_REGISTER_BASE 0x70019000
|
void Board::SetSpeedoBracket() {
|
||||||
#define MC_REGISTER_REGION_SIZE 0x1000
|
if (cpuSpeedo2 >= 1754) {
|
||||||
|
speedoBracket = 3;
|
||||||
|
} else if (cpuSpeedo2 >= 1690) {
|
||||||
|
speedoBracket = 2;
|
||||||
|
} else if (cpuSpeedo2 > 1625) {
|
||||||
|
speedoBracket = 1;
|
||||||
|
} else {
|
||||||
|
speedoBracket = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define EMC_REGISTER_BASE 0x7001b000
|
u32 Board::GetMinimumGpuVoltage(u32 freqMhz) {
|
||||||
#define EMC_REGISTER_REGION_SIZE 0x1000
|
if (freqMhz <= 1600)
|
||||||
|
return 0;
|
||||||
|
|
||||||
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
|
for (u32 voltageIndex = 0; voltageIndex < 22; ++voltageIndex) {
|
||||||
|
if (freqMhz <= ramBrackets[speedoBracket][voltageIndex]) {
|
||||||
#define WRITE_REGISTER_EMC(TIMING_OFFSET, VALUE) \
|
return gpuDvfsArray[voltageIndex];
|
||||||
do { \
|
}
|
||||||
args = {}; \
|
|
||||||
args.X[0] = 0xF0000002; \
|
|
||||||
args.X[1] = EMC_REGISTER_BASE + (TIMING_OFFSET); \
|
|
||||||
args.X[2] = 0xFFFFFFFF; \
|
|
||||||
args.X[3] = (VALUE); \
|
|
||||||
svcCallSecureMonitor(&args); \
|
|
||||||
} while (false)
|
|
||||||
|
|
||||||
#define WRITE_REGISTER_MC(TIMING_OFFSET, VALUE) \
|
|
||||||
do { \
|
|
||||||
args = {}; \
|
|
||||||
args.X[0] = 0xF0000002; \
|
|
||||||
args.X[1] = MC_REGISTER_BASE + (TIMING_OFFSET); \
|
|
||||||
args.X[2] = 0xFFFFFFFF; \
|
|
||||||
args.X[3] = (VALUE); \
|
|
||||||
svcCallSecureMonitor(&args); \
|
|
||||||
} while (false)
|
|
||||||
|
|
||||||
|
|
||||||
// NOTE: needs patch to exosphere to expose emc region to secmon. MC does NOT need this patch
|
|
||||||
|
|
||||||
u32 tRCD_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
|
||||||
u32 tRP_values[] = { 18, 17, 16, 15, 14, 13, 12, 11 };
|
|
||||||
u32 tRAS_values[] = { 42, 36, 34, 32, 30, 28, 26, 24, 22, 20 };
|
|
||||||
double tRRD_values[] = { /*10.0,*/ 7.5, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0 }; /* 10.0 is used for <2133mhz; do we care? */
|
|
||||||
u32 tRFC_values[] = { 140, 130, 120, 110, 100, 90, 80, 70, 60, 50, 40 };
|
|
||||||
u32 tWTR_values[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
|
||||||
u32 tREFpb_values[] = { 3900, 5850, 7800, 11700, 15600, 99999 };
|
|
||||||
|
|
||||||
// Credit to Lightos for these timings!
|
|
||||||
|
|
||||||
|
|
||||||
void Board::UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode) {
|
|
||||||
// timing stuff
|
|
||||||
|
|
||||||
SecmonArgs args = {};
|
|
||||||
|
|
||||||
constexpr double MC_ARB_DIV = 4.0;
|
|
||||||
constexpr u32 MC_ARB_SFA = 2;
|
|
||||||
|
|
||||||
double tCK_avg = 1000'000.0 / ramFreq;
|
|
||||||
u32 BL = 16;
|
|
||||||
u32 RL = 28 + rlAdd;
|
|
||||||
u32 WL = 14 + wlAdd;
|
|
||||||
u32 RL_DBI = RL + 4;
|
|
||||||
|
|
||||||
u32 tRCD = tRCD_values[tRCD_i];
|
|
||||||
u32 tRPpb = tRP_values[tRP_i];
|
|
||||||
u32 tRAS = tRAS_values[tRAS_i];
|
|
||||||
double tRRD = tRRD_values[tRRD_i];
|
|
||||||
u32 tRFCpb = tRFC_values[tRFC_i];
|
|
||||||
u32 tWTR = 10 - tWTR_values[tWTR_i];
|
|
||||||
u32 tFAW = static_cast<u32>(tRRD * 4.0);
|
|
||||||
|
|
||||||
double tDQSCK_max = 3.5;
|
|
||||||
u32 tWPRE = 2;
|
|
||||||
|
|
||||||
double tRPST = 0.5;
|
|
||||||
|
|
||||||
u32 tR2W = CEIL(RL_DBI + (tDQSCK_max / tCK_avg) + (BL / 2) - WL + tWPRE + FLOOR(tRPST) + 9.0) - (tRTW_i * 3);
|
|
||||||
|
|
||||||
u32 tRC = tRAS + tRPpb;
|
|
||||||
u32 tRFCab = tRFCpb * 2;
|
|
||||||
u32 tRPab = tRPpb + 3;
|
|
||||||
|
|
||||||
u32 tW2R = CEIL(MAX(WL + (0.010322547033278747 * (ramFreq / 1000.0)), (WL * -0.2067922202979121) + FLOOR(((RL_DBI * -0.1331159971685554) + WL) * 3.654131957826108)) - (tWTR / tCK_avg));
|
|
||||||
|
|
||||||
double tMMRI = tRCD + (tCK_avg * 3);
|
|
||||||
double pdex2mrr = tMMRI + 10;
|
|
||||||
u32 emc_cfg = hpMode ? 0x13200000 : 0xF3200000;
|
|
||||||
|
|
||||||
u32 refresh_raw = 0xFFFF;
|
|
||||||
if (tREFpb_i != 6) {
|
|
||||||
refresh_raw = CEIL(tREFpb_values[tREFpb_i] / tCK_avg) - 0x40;
|
|
||||||
refresh_raw = MIN(refresh_raw, static_cast<u32>(0xFFFF));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 trefbw = refresh_raw + 0x40;
|
return 800;
|
||||||
trefbw = MIN(trefbw, static_cast<u32>(0x3FFF));
|
}
|
||||||
|
|
||||||
u32 tR2P = 12 + (rlAdd / 2);
|
Handle Board::GetPcvHandle() {
|
||||||
u32 tW2P = (CEIL(WL * 1.7303) * 2) - 5;
|
constexpr u64 PcvID = 0x10000000000001a;
|
||||||
|
u64 processIDList[80]{};
|
||||||
|
s32 processCount = 0;
|
||||||
|
Handle handle = INVALID_HANDLE;
|
||||||
|
|
||||||
double tXSR = (double) (tRFCab + 7.5);
|
DebugEventInfo debugEvent{};
|
||||||
|
|
||||||
args = {};
|
/* Get all running processes. */
|
||||||
args.X[0] = 0xF0000002;
|
Result resultGetProcessList = svcGetProcessList(&processCount, processIDList, std::size(processIDList));
|
||||||
args.X[1] = EMC_REGISTER_BASE + EMC_INTSTATUS_0;
|
if (R_FAILED(resultGetProcessList)) {
|
||||||
svcCallSecureMonitor(&args);
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
if(args.X[1] == (EMC_REGISTER_BASE + EMC_INTSTATUS_0)) { // if param 1 is identical read failed, exosphere needs patch!
|
/* Try to find pcv. */
|
||||||
writeNotification("Horizon OC\nExosphere not patched\nfor EMC r/w");
|
for (int i = 0; i < processCount; ++i) {
|
||||||
|
if (handle != INVALID_HANDLE) {
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to debug process, if it fails, try next process. */
|
||||||
|
Result resultSvcDebugProcess = svcDebugActiveProcess(&handle, processIDList[i]);
|
||||||
|
if (R_FAILED(resultSvcDebugProcess)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get a debug event. */
|
||||||
|
Result resultDebugEvent = svcGetDebugEvent(&debugEvent, handle);
|
||||||
|
if (R_SUCCEEDED(resultDebugEvent)) {
|
||||||
|
if (debugEvent.info.create_process.program_id == PcvID) {
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Failed to get handle. */
|
||||||
|
return INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::CacheDvfsTable() {
|
||||||
|
const u32 voltagePattern[] = { 600000, 12500, 1400000, };
|
||||||
|
|
||||||
|
Handle handle = GetPcvHandle();
|
||||||
|
if (handle == INVALID_HANDLE) {
|
||||||
|
FileUtils::LogLine("[Board] Invalid handle!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// actually write the timings
|
MemoryInfo memoryInfo = {};
|
||||||
WRITE_REGISTER_EMC(EMC_CFG_0, emc_cfg);
|
u64 address = 0;
|
||||||
WRITE_REGISTER_EMC(EMC_RD_RCD_0, GET_CYCLE_CEIL(tRCD));
|
u32 pageInfo = 0;
|
||||||
WRITE_REGISTER_EMC(EMC_WR_RCD_0, GET_CYCLE_CEIL(tRCD));
|
constexpr u32 PageSize = 0x1000;
|
||||||
WRITE_REGISTER_EMC(EMC_RC_0, MIN(GET_CYCLE_CEIL(tRC), static_cast<u32>(0xB8)));
|
u8 buffer[PageSize];
|
||||||
WRITE_REGISTER_EMC(EMC_RAS_0, MIN(GET_CYCLE_CEIL(tRAS), static_cast<u32>(0x7F)));
|
|
||||||
WRITE_REGISTER_EMC(EMC_RRD_0, GET_CYCLE_CEIL(tRRD));
|
|
||||||
WRITE_REGISTER_EMC(EMC_RFCPB_0, GET_CYCLE_CEIL(tRFCpb));
|
|
||||||
WRITE_REGISTER_EMC(EMC_RFC_0, GET_CYCLE_CEIL(tRFCab));
|
|
||||||
WRITE_REGISTER_EMC(EMC_RP_0, GET_CYCLE_CEIL(tRPpb));
|
|
||||||
WRITE_REGISTER_EMC(EMC_TRPAB_0, MIN(GET_CYCLE_CEIL(tRPab), static_cast<u32>(0x3F)));
|
|
||||||
WRITE_REGISTER_EMC(EMC_R2W_0, tR2W);
|
|
||||||
WRITE_REGISTER_EMC(EMC_W2R_0, tW2R);
|
|
||||||
WRITE_REGISTER_EMC(EMC_REFRESH_0, refresh_raw);
|
|
||||||
WRITE_REGISTER_EMC(EMC_PRE_REFRESH_REQ_CNT_0, refresh_raw / 4);
|
|
||||||
WRITE_REGISTER_EMC(EMC_TREFBW_0, trefbw);
|
|
||||||
WRITE_REGISTER_EMC(EMC_PDEX2MRR_0, GET_CYCLE_CEIL(pdex2mrr));
|
|
||||||
WRITE_REGISTER_EMC(EMC_TXSR_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
|
||||||
WRITE_REGISTER_EMC(EMC_TXSRDLL_0, MIN(GET_CYCLE_CEIL(tXSR), static_cast<u32>(0x3fe)));
|
|
||||||
|
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RCD_0, CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2);
|
/* Loop until failure. */
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RP_0, CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1);
|
while (true) {
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RC_0, CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1);
|
/* Find pcv heap. */
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAS_0, CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2);
|
while (true) {
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_FAW_0, CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1);
|
Result resultProcessMemory = svcQueryDebugProcessMemory(&memoryInfo, &pageInfo, handle, address);
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RRD_0, CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1);
|
address = memoryInfo.addr + memoryInfo.size;
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RFCPB_0, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV) - 1);
|
|
||||||
|
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_R2W_0, CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
if (R_FAILED(resultProcessMemory) || !address) {
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_W2R_0, CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA);
|
svcCloseHandle(handle);
|
||||||
|
FileUtils::LogLine("[Board] Failed to get process data. %u", R_DESCRIPTION(resultProcessMemory));
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_RAP2PRE_0, CEIL(tR2P / MC_ARB_DIV));
|
if (memoryInfo.size && (memoryInfo.perm & 3) == 3 && static_cast<char>(memoryInfo.type) == 0x04) {
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_TIMING_WAP2PRE_0, CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA);
|
/* Found valid memory. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u32 da_turns = 0;
|
for (u64 base = 0; base < memoryInfo.size; base += PageSize) {
|
||||||
da_turns |= u8((CEIL(tR2W / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 16;
|
u32 memorySize = std::min(memoryInfo.size, static_cast<u64>(PageSize));
|
||||||
da_turns |= u8((CEIL(tW2R / MC_ARB_DIV) - 1 + MC_ARB_SFA) / 2) << 24;
|
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, base + memoryInfo.addr, memorySize))) {
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_TURNS_0, da_turns);
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
u32 da_covers = 0;
|
u8 *resultPattern = static_cast<u8 *>(memmem_impl(buffer, sizeof(buffer), voltagePattern, sizeof(voltagePattern)));
|
||||||
u8 r_cover = ((CEIL(tR2P / MC_ARB_DIV)) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
u32 index = resultPattern - buffer;
|
||||||
u8 w_cover = ((CEIL(tW2P / MC_ARB_DIV) + MC_ARB_SFA) + (CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1) + (CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)) / 2;
|
|
||||||
da_covers |= ((u32)(CEIL(GET_CYCLE_CEIL(tRC) / (u32)MC_ARB_DIV) - 1) / 2);
|
|
||||||
da_covers |= (r_cover << 8);
|
|
||||||
da_covers |= (w_cover << 16);
|
|
||||||
|
|
||||||
WRITE_REGISTER_MC(MC_EMEM_ARB_DA_COVERS_0, da_covers);
|
if (!resultPattern) {
|
||||||
// TODO: modify mc_emem_arb_misc0
|
continue;
|
||||||
|
}
|
||||||
WRITE_REGISTER_MC(MC_TIMING_CONTROL_0, 0x1); // update timing regs as they are shadowed
|
|
||||||
WRITE_REGISTER_EMC(EMC_TIMING_CONTROL_0, 0x1);
|
/* Assuming mariko. */
|
||||||
|
const u32 vmax = 800;
|
||||||
|
constexpr u32 DvfsTableOffset = 312;
|
||||||
|
if (!std::memcmp(&buffer[index + DvfsTableOffset], &vmax, sizeof(vmax))) {
|
||||||
|
std::memcpy(dvfsTable, &buffer[index + DvfsTableOffset], sizeof(dvfsTable));
|
||||||
|
dvfsAddress = base + memoryInfo.addr + DvfsTableOffset + index;
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
handle = INVALID_HANDLE;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Board::PcvHijackDvfs(u32 vmin) {
|
||||||
|
u32 table[192];
|
||||||
|
static_assert(sizeof(table) == sizeof(dvfsTable));
|
||||||
|
std::memcpy(table, dvfsTable, sizeof(dvfsTable));
|
||||||
|
|
||||||
|
if (ramVmin == vmin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < std::size(table); ++i) {
|
||||||
|
if (table[i] && table[i] <= vmin) {
|
||||||
|
table[i] = vmin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle handle = GetPcvHandle();
|
||||||
|
if (handle == INVALID_HANDLE) {
|
||||||
|
FileUtils::LogLine("Invalid handle!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rc = svcWriteDebugProcessMemory(handle, table, dvfsAddress, sizeof(table));
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
ramVmin = vmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
svcCloseHandle(handle);
|
||||||
|
FileUtils::LogLine("[dvfs] voltage set to %u mV", vmin);
|
||||||
|
}
|
||||||
|
|
||||||
bool Board::IsDram8GB() {
|
bool Board::IsDram8GB() {
|
||||||
SecmonArgs args = {};
|
SecmonArgs args = {};
|
||||||
args.X[0] = 0xF0000002;
|
args.X[0] = 0xF0000002;
|
||||||
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
args.X[1] = MC_REGISTER_BASE + MC_EMEM_CFG_0;
|
||||||
svcCallSecureMonitor(&args);
|
svcCallSecureMonitor(&args);
|
||||||
|
|
||||||
if(args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
|
if(args.X[1] == (MC_REGISTER_BASE + MC_EMEM_CFG_0)) { // if param 1 is identical read failed
|
||||||
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
writeNotification("Horizon OC\nSecmon read failed!\n This may be a hardware issue!");
|
||||||
return false;
|
return false;
|
||||||
} else
|
} else
|
||||||
return args.X[1] == 0x00002000 ? true : false;
|
return args.X[1] == 0x00002000 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board::SetGpuSchedulingMode(GpuSchedulingMode mode, GpuSchedulingOverrideMethod method) {
|
||||||
|
if (nvCheck_sched == 1 && method == GpuSchedulingOverrideMethod_NvService) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
u32 temp;
|
||||||
|
bool enabled = false;
|
||||||
|
switch(mode) {
|
||||||
|
case GpuSchedulingMode_DoNotOverride: break;
|
||||||
|
case GpuSchedulingMode_Disabled:
|
||||||
|
if(method == GpuSchedulingOverrideMethod_NvService)
|
||||||
|
nvIoctl(fd2, NVSCHED_CTRL_DISABLE, &temp);
|
||||||
|
else
|
||||||
|
enabled = false;
|
||||||
|
break;
|
||||||
|
case GpuSchedulingMode_Enabled:
|
||||||
|
if(method == GpuSchedulingOverrideMethod_NvService)
|
||||||
|
nvIoctl(fd2, NVSCHED_CTRL_ENABLE, &temp);
|
||||||
|
else
|
||||||
|
enabled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT_ENUM_VALID(GpuSchedulingMode, mode);
|
||||||
|
}
|
||||||
|
if(method == GpuSchedulingOverrideMethod_Ini) {
|
||||||
|
const char* ini_path = "sdmc:/atmosphere/config/system_settings.ini";
|
||||||
|
const char* section = "am.gpu";
|
||||||
|
const char* key = "gpu_scheduling_enabled";
|
||||||
|
|
||||||
|
const char* value = enabled ? "u8!0x1" : "u8!0x0";
|
||||||
|
|
||||||
|
ini_puts(section, key, value, ini_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Board::SetDisplayRefreshDockedState(bool docked) {
|
||||||
|
if(Board::GetConsoleType() != HorizonOCConsoleType_Hoag) {
|
||||||
|
DisplayRefresh_SetDockedState(docked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct EristaCpuUvEntry {
|
||||||
|
u32 tune0;
|
||||||
|
u32 tune1;
|
||||||
|
} EristaCpuUvEntry;
|
||||||
|
typedef struct MarikoCpuUvEntry {
|
||||||
|
u32 tune0_low;
|
||||||
|
u32 tune0_high;
|
||||||
|
u32 tune1_low;
|
||||||
|
u32 tune1_high;
|
||||||
|
} MarikoCpuUvEntry;
|
||||||
|
|
||||||
|
EristaCpuUvEntry eristaCpuUvTable[5] = {
|
||||||
|
{0xffff, 0x27007ff},
|
||||||
|
{0xefff, 0x27407ff},
|
||||||
|
{0xdfff, 0x27807ff},
|
||||||
|
{0xdfdf, 0x27a07ff},
|
||||||
|
{0xcfdf, 0x37007ff},
|
||||||
|
};
|
||||||
|
|
||||||
|
MarikoCpuUvEntry marikoCpuUvLow[12] = {
|
||||||
|
{0xffa0, 0xffff, 0x21107ff, 0},
|
||||||
|
{0x0, 0xffdf, 0x21107ff, 0x27207ff},
|
||||||
|
{0xffdf, 0xffdf, 0x21107ff, 0x27307ff},
|
||||||
|
{0xffff, 0xffdf, 0x21107ff, 0x27407ff},
|
||||||
|
{0x0, 0xffdf, 0x21607ff, 0x27707ff},
|
||||||
|
{0x0, 0xffdf, 0x21607ff, 0x27807ff},
|
||||||
|
{0x0, 0xdfff, 0x21607ff, 0x27b07ff},
|
||||||
|
{0xdfff, 0xdfff, 0x21707ff, 0x27b07ff},
|
||||||
|
{0xdfff, 0xdfff, 0x21707ff, 0x27c07ff},
|
||||||
|
{0xdfff, 0xdfff, 0x21707ff, 0x27d07ff},
|
||||||
|
{0xdfff, 0xdfff, 0x21707ff, 0x27e07ff},
|
||||||
|
{0xdfff, 0xdfff, 0x21707ff, 0x27f07ff},
|
||||||
|
};
|
||||||
|
|
||||||
|
MarikoCpuUvEntry marikoCpuUvHigh[12] = {
|
||||||
|
{0x0, 0xffff, 0, 0},
|
||||||
|
{0x0, 0xffdf, 0, 0x27207ff},
|
||||||
|
{0x0, 0xffdf, 0, 0x27307ff},
|
||||||
|
{0x0, 0xffdf, 0, 0x27407ff},
|
||||||
|
{0x0, 0xffdf, 0, 0x27707ff},
|
||||||
|
{0x0, 0xffdf, 0, 0x27807ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27b07ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27c07ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27d07ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27e07ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27f07ff},
|
||||||
|
{0x0, 0xdfff, 0, 0x27f07ff},
|
||||||
|
};
|
||||||
|
void Board::SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint) {
|
||||||
|
u32* tune0_ptr = (u32*)(cldvfs + CL_DVFS_TUNE0_0);
|
||||||
|
u32* tune1_ptr = (u32*)(cldvfs + CL_DVFS_TUNE1_0);
|
||||||
|
if(Board::GetSocType() == SysClkSocType_Mariko) {
|
||||||
|
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint && (levelLow || levelHigh)) {
|
||||||
|
if(levelLow) {
|
||||||
|
*tune0_ptr = marikoCpuUvLow[levelLow-1].tune0_low;
|
||||||
|
*tune1_ptr = marikoCpuUvLow[levelLow-1].tune1_low;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if(levelLow) {
|
||||||
|
*tune0_ptr = marikoCpuUvLow[levelLow-1].tune0_low;
|
||||||
|
*tune1_ptr = marikoCpuUvLow[levelLow-1].tune1_low;
|
||||||
|
}
|
||||||
|
if(levelHigh) {
|
||||||
|
*tune0_ptr = marikoCpuUvHigh[levelHigh-1].tune0_high;
|
||||||
|
*tune1_ptr = marikoCpuUvHigh[levelHigh-1].tune1_high;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
|
||||||
|
*tune0_ptr = 0xCFFF;
|
||||||
|
*tune1_ptr = 0xFF072201;
|
||||||
|
return;
|
||||||
|
} else if (Board::GetHz(SysClkModule_CPU) >= tbreakPoint || (!levelHigh)) {
|
||||||
|
*tune0_ptr = cachedMarikoUvHighTune0; // per console?
|
||||||
|
*tune1_ptr = 0xFFF7FF3F;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Board::GetHz(SysClkModule_CPU) < tbreakPoint || (!levelLow)) { // account for tbreak
|
||||||
|
*tune0_ptr = cachedEristaUvLowTune0; // I think each erista has a different tune0/tune1?
|
||||||
|
*tune1_ptr = cachedEristaUvLowTune1;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if(levelLow) {
|
||||||
|
*tune0_ptr = eristaCpuUvTable[levelLow-1].tune0;
|
||||||
|
*tune1_ptr = eristaCpuUvTable[levelLow-1].tune1;
|
||||||
|
} else {
|
||||||
|
*tune0_ptr = 0x0;
|
||||||
|
*tune1_ptr = 0x0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
enum TableConfig: u32 {
|
||||||
|
DEFAULT_TABLE = 1,
|
||||||
|
TBREAK_1581 = 2,
|
||||||
|
TBREAK_1683 = 3,
|
||||||
|
EXTREME_TABLE = 4,
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
u32 Board::CalculateTbreak(u32 table) {
|
||||||
|
if(Board::GetSocType() == SysClkSocType_Erista)
|
||||||
|
return 1581000000;
|
||||||
|
else {
|
||||||
|
switch(table) {
|
||||||
|
case 1 ... 2:
|
||||||
|
case 4:
|
||||||
|
return 1581000000;
|
||||||
|
case 3:
|
||||||
|
return 1683000000;
|
||||||
|
default:
|
||||||
|
return 1581000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Board::IsHoag() {
|
||||||
|
return Board::GetConsoleType() == HorizonOCConsoleType_Hoag;
|
||||||
}
|
}
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -33,6 +33,8 @@
|
|||||||
class Board
|
class Board
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
static void PcvHijackDvfs(u32 vmin);
|
||||||
|
static u32 GetMinimumGpuVoltage(u32 freqMhz);
|
||||||
static void fuseReadSpeedos();
|
static void fuseReadSpeedos();
|
||||||
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
static u16 getSpeedo(HorizonOCSpeedo speedoType);
|
||||||
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
static u16 getIDDQ(HorizonOCSpeedo speedoType);
|
||||||
@@ -61,10 +63,18 @@ class Board
|
|||||||
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
||||||
static u8 GetFanRotationLevel();
|
static u8 GetFanRotationLevel();
|
||||||
static u8 GetDramID();
|
static u8 GetDramID();
|
||||||
static void UpdateShadowRegs(u32 tRCD_i, u32 tRP_i, u32 tRAS_i, u32 tRRD_i, u32 tRFC_i, u32 tRTW_i, u32 tWTR_i, u32 tREFpb_i, u32 ramFreq, u32 rlAdd, u32 wlAdd, bool hpMode);
|
|
||||||
static bool IsDram8GB();
|
static bool IsDram8GB();
|
||||||
|
static void SetGpuSchedulingMode(GpuSchedulingMode mode, GpuSchedulingOverrideMethod method);
|
||||||
|
static void SetDisplayRefreshDockedState(bool docked);
|
||||||
|
static void SetCpuUvLevel(u32 levelLow, u32 levelHigh, u32 tbreakPoint);
|
||||||
|
static u32 CalculateTbreak(u32 table);
|
||||||
|
static bool IsHoag();
|
||||||
protected:
|
protected:
|
||||||
static void FetchHardwareInfos();
|
static void FetchHardwareInfos();
|
||||||
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
static PcvModule GetPcvModule(SysClkModule sysclkModule);
|
||||||
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
static PcvModuleId GetPcvModuleId(SysClkModule sysclkModule);
|
||||||
|
private:
|
||||||
|
static void SetSpeedoBracket();
|
||||||
|
static void CacheDvfsTable();
|
||||||
|
static Handle GetPcvHandle();
|
||||||
};
|
};
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,54 +23,231 @@
|
|||||||
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
* stuff is worth it, you can buy us a beer in return. - The sys-clk authors
|
||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <sysclk.h>
|
#include <sysclk.h>
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include <nxExt/cpp/lockable_mutex.h>
|
#include <nxExt/cpp/lockable_mutex.h>
|
||||||
#include "integrations.h"
|
#include "integrations.h"
|
||||||
void governorThread(void*);
|
|
||||||
|
|
||||||
class ReverseNXSync;
|
|
||||||
|
|
||||||
|
class SysDockIntegration;
|
||||||
|
class SaltyNXIntegration;
|
||||||
class ClockManager
|
class ClockManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* Get instance
|
||||||
|
* @return Pointer to a ClockManager instance
|
||||||
|
*/
|
||||||
static ClockManager* GetInstance();
|
static ClockManager* GetInstance();
|
||||||
static void Initialize();
|
static void Initialize();
|
||||||
static void Exit();
|
static void Exit();
|
||||||
|
|
||||||
|
|
||||||
ClockManager();
|
ClockManager();
|
||||||
virtual ~ClockManager();
|
virtual ~ClockManager();
|
||||||
void FixCpuBug();
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get context object
|
||||||
|
* @return Context instance
|
||||||
|
*/
|
||||||
SysClkContext GetCurrentContext();
|
SysClkContext GetCurrentContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get config object
|
||||||
|
* @return Pointer to a config instance
|
||||||
|
*/
|
||||||
Config* GetConfig();
|
Config* GetConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set clock manager running
|
||||||
|
* @param running Is running or not?
|
||||||
|
*/
|
||||||
void SetRunning(bool running);
|
void SetRunning(bool running);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is clock manager running
|
||||||
|
* @return running or not?
|
||||||
|
*/
|
||||||
bool Running();
|
bool Running();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get frequency list from clkrst
|
||||||
|
*
|
||||||
|
* @param module Module to get frequency list for
|
||||||
|
* @param list List of frequencies
|
||||||
|
* @param maxCount How many entries to expect in list. Usually 32
|
||||||
|
* @param outCount How many entries were retrived
|
||||||
|
*/
|
||||||
void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount);
|
void GetFreqList(SysClkModule module, std::uint32_t* list, std::uint32_t maxCount, std::uint32_t* outCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles safety features
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void HandleSafetyFeatures();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles misc features (currently only battery charge current).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void HandleMiscFeatures();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles governor state resolution and applies CPU/GPU governor transitions.
|
||||||
|
*
|
||||||
|
* @param targetHz Governor override value for the current profile.
|
||||||
|
*/
|
||||||
|
void HandleGovernor(uint32_t targetHz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles DVFS logic before the frequency set
|
||||||
|
*
|
||||||
|
* @param targetHz Governor override value for the current profile.
|
||||||
|
*/
|
||||||
|
void DVFSBeforeSet(u32 targetHz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles DVFS logic after the frequency set
|
||||||
|
*
|
||||||
|
* @param targetHz Governor override value for the current profile.
|
||||||
|
*/
|
||||||
|
void DVFSAfterSet(u32 targetHz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the GPU vMin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void DVFSReset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the Live CPU UV Feature
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void HandleCpuUv();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles frequency resets
|
||||||
|
*
|
||||||
|
* @param module The module to reset frequency for
|
||||||
|
* @param isBoost Is in boost mode
|
||||||
|
*/
|
||||||
|
void HandleFreqReset(SysClkModule module, bool isBoost);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets clocks
|
||||||
|
*
|
||||||
|
* @param isBoost Is in boost mode
|
||||||
|
*/
|
||||||
|
void SetClocks(bool isBoost);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main function, runs every 5s in sleep mode, and a user specified amount when awake
|
||||||
|
*
|
||||||
|
*/
|
||||||
void Tick();
|
void Tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset CPU/GPU to stock values
|
||||||
|
*
|
||||||
|
*/
|
||||||
void ResetToStockClocks();
|
void ResetToStockClocks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the next tick event
|
||||||
|
*
|
||||||
|
*/
|
||||||
void WaitForNextTick();
|
void WaitForNextTick();
|
||||||
void SetRNXRTMode(ReverseNXMode mode);
|
|
||||||
|
/**
|
||||||
|
* Set the data in the KIP
|
||||||
|
*
|
||||||
|
*/
|
||||||
void SetKipData();
|
void SetKipData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data from the KIP
|
||||||
|
*
|
||||||
|
*/
|
||||||
void GetKipData();
|
void GetKipData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the CPU Governor
|
||||||
|
*
|
||||||
|
* @param arg Cast to ClockManager* for context
|
||||||
|
*/
|
||||||
|
static void CpuGovernorThread(void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the GPU Governor
|
||||||
|
*
|
||||||
|
* @param arg Cast to ClockManager* for context
|
||||||
|
*/
|
||||||
static void GovernorThread(void* arg);
|
static void GovernorThread(void* arg);
|
||||||
void UpdateRamTimings();
|
|
||||||
struct {
|
/**
|
||||||
|
* Runs the VRR Algorithm
|
||||||
|
*
|
||||||
|
* @param arg Cast to ClockManager* for context
|
||||||
|
*/
|
||||||
|
static void VRRThread(void* arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the effective governor state from application/temporary override
|
||||||
|
*
|
||||||
|
* @param appState Governor state from app
|
||||||
|
* @param tempState Governor state from temporary override
|
||||||
|
*/
|
||||||
|
GovernorState GetEffectiveGovernorState(GovernorState appState, GovernorState tempState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Frequency table
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct FreqTable {
|
||||||
std::uint32_t count;
|
std::uint32_t count;
|
||||||
std::uint32_t list[SYSCLK_FREQ_LIST_MAX];
|
std::uint32_t list[SYSCLK_FREQ_LIST_MAX];
|
||||||
} freqTable[SysClkModule_EnumMax];
|
} freqTable[SysClkModule_EnumMax];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current GPU speedo bracket
|
||||||
|
*
|
||||||
|
* @param speedo GPU Speedo
|
||||||
|
*/
|
||||||
int GetSpeedoBracket (int speedo);
|
int GetSpeedoBracket (int speedo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the required vMin for a ram frequency for a speedo
|
||||||
|
*
|
||||||
|
* @param freq RAM Freq in MHz
|
||||||
|
* @param speedo GPU Speedo
|
||||||
|
*/
|
||||||
unsigned int GetGpuVoltage (unsigned int freq, int speedo);
|
unsigned int GetGpuVoltage (unsigned int freq, int speedo);
|
||||||
void calculateGpuVmin(void);
|
|
||||||
|
/**
|
||||||
|
* Gets the required vMin for a ram frequency for a speedo
|
||||||
|
*
|
||||||
|
* @param util Utilization in percentile
|
||||||
|
* @param tableMaxHz Table Max Hz
|
||||||
|
*/
|
||||||
|
static u32 SchedutilTargetHz(u32 util, u32 tableMaxHz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the required vMin for a ram frequency for a speedo
|
||||||
|
*
|
||||||
|
* @param table FreqTable for module
|
||||||
|
* @param targetHz Hz to search for
|
||||||
|
*/
|
||||||
|
static u32 TableIndexForHz(const FreqTable& table, u32 targetHz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the required vMin for a ram frequency for a speedo
|
||||||
|
*
|
||||||
|
* @param mgr ClockManager instance (runs in a thread so must be passed)
|
||||||
|
* @param module Module for which to resolve target Hz
|
||||||
|
*/
|
||||||
|
static u32 ResolveTargetHz(ClockManager* mgr, SysClkModule module);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool IsAssignableHz(SysClkModule module, std::uint32_t hz);
|
bool IsAssignableHz(SysClkModule module, std::uint32_t hz);
|
||||||
inline std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile);
|
inline std::uint32_t GetMaxAllowedHz(SysClkModule module, SysClkProfile profile);
|
||||||
@@ -78,9 +255,7 @@ class ClockManager
|
|||||||
bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t* lastLogNs);
|
bool ConfigIntervalTimeout(SysClkConfigValue intervalMsConfigValue, std::uint64_t ns, std::uint64_t* lastLogNs);
|
||||||
void RefreshFreqTableRow(SysClkModule module);
|
void RefreshFreqTableRow(SysClkModule module);
|
||||||
bool RefreshContext();
|
bool RefreshContext();
|
||||||
|
|
||||||
static ClockManager *instance;
|
static ClockManager *instance;
|
||||||
|
|
||||||
std::atomic_bool running;
|
std::atomic_bool running;
|
||||||
LockableMutex contextMutex;
|
LockableMutex contextMutex;
|
||||||
Config* config;
|
Config* config;
|
||||||
@@ -89,5 +264,6 @@ class ClockManager
|
|||||||
std::uint64_t lastFreqLogNs;
|
std::uint64_t lastFreqLogNs;
|
||||||
std::uint64_t lastPowerLogNs;
|
std::uint64_t lastPowerLogNs;
|
||||||
std::uint64_t lastCsvWriteNs;
|
std::uint64_t lastCsvWriteNs;
|
||||||
ReverseNXSync *rnxSync;
|
SysDockIntegration *sysDockIntegration;
|
||||||
};
|
SaltyNXIntegration *saltyNXIntegration;
|
||||||
|
};
|
||||||
@@ -17,68 +17,94 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "integrations.h"
|
#include "integrations.h"
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <SaltyNX.h>
|
||||||
|
#include "process_management.h"
|
||||||
|
|
||||||
ReverseNXSync::ReverseNXSync()
|
SysDockIntegration::SysDockIntegration() {
|
||||||
: m_rt_mode(ReverseNX_NotFound), m_tool_mode(ReverseNX_NotFound) {
|
|
||||||
FILE *fp = fopen("/atmosphere/contents/0000000000534C56/flags/boot2.flag", "r");
|
|
||||||
m_tool_enabled = fp ? true : false;
|
|
||||||
if (fp)
|
|
||||||
fclose(fp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SysClkProfile ReverseNXSync::GetProfile(SysClkProfile real) {
|
bool SysDockIntegration::getCurrentSysDockState() {
|
||||||
switch (this->GetMode()) {
|
struct stat st = {0};
|
||||||
case ReverseNX_Docked:
|
return stat("sdmc:/atmosphere/contents/42000000000000A0/flags/boot2.flag", &st) == 0;
|
||||||
return SysClkProfile_Docked;
|
|
||||||
case ReverseNX_Handheld:
|
|
||||||
if (real == SysClkProfile_Docked)
|
|
||||||
return SysClkProfile_HandheldChargingOfficial;
|
|
||||||
default:
|
|
||||||
return real;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReverseNXMode ReverseNXSync::GetMode() {
|
SaltyNXIntegration::SaltyNXIntegration() {
|
||||||
if (!this->m_sync_enabled)
|
|
||||||
return ReverseNX_NotFound;
|
|
||||||
if (this->m_rt_mode)
|
|
||||||
return this->m_rt_mode;
|
|
||||||
return this->m_tool_mode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReverseNXMode ReverseNXSync::GetToolModeFromPatch(const char* patch_path) {
|
void SaltyNXIntegration::LoadSaltyNX() {
|
||||||
constexpr uint32_t DOCKED_MAGIC = 0x320003E0;
|
if (!CheckPort())
|
||||||
constexpr uint32_t HANDHELD_MAGIC = 0x52A00000;
|
return;
|
||||||
FILE *fp = fopen(patch_path, "rb");
|
LoadSharedMemory();
|
||||||
if (fp) {
|
|
||||||
uint32_t buf = 0;
|
|
||||||
fread(&buf, sizeof(buf), 1, fp);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (buf == DOCKED_MAGIC)
|
|
||||||
return ReverseNX_Docked;
|
|
||||||
if (buf == HANDHELD_MAGIC)
|
|
||||||
return ReverseNX_Handheld;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ReverseNX_NotFound;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReverseNXMode ReverseNXSync::RecheckToolMode() {
|
bool SaltyNXIntegration::getCurrentSaltyNXState() {
|
||||||
ReverseNXMode mode = ReverseNX_NotFound;
|
struct stat st = {0};
|
||||||
if (this->m_tool_enabled) {
|
return stat("sdmc:/atmosphere/contents/0000000000534C56/flags/boot2.flag", &st) == 0;
|
||||||
const char* fileName = "_ZN2nn2oe18GetPerformanceModeEv.asm64"; // or _ZN2nn2oe18GetPerformanceModeEv.asm64
|
}
|
||||||
const char* filePath = new char[72];
|
|
||||||
SCOPE_EXIT { delete[] filePath; };
|
bool SaltyNXIntegration::CheckPort() {
|
||||||
/* Check per-game patch */
|
Handle saltysd;
|
||||||
snprintf((char*)filePath, 72, "/SaltySD/patches/%016lX/%s", this->m_app_id, fileName);
|
|
||||||
mode = this->GetToolModeFromPatch(filePath);
|
for (int i = 0; i < 67; i++) {
|
||||||
if (!mode) {
|
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
|
||||||
/* Check global patch */
|
svcCloseHandle(saltysd);
|
||||||
snprintf((char*)filePath, 72, "/SaltySD/patches/%s", fileName);
|
break;
|
||||||
mode = this->GetToolModeFromPatch(filePath);
|
|
||||||
}
|
}
|
||||||
|
if (i == 66) return false;
|
||||||
|
svcSleepThread(1'000'000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mode;
|
for (int i = 0; i < 67; i++) {
|
||||||
|
if (R_SUCCEEDED(svcConnectToNamedPort(&saltysd, "InjectServ"))) {
|
||||||
|
svcCloseHandle(saltysd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
svcSleepThread(1'000'000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaltyNXIntegration::LoadSharedMemory() {
|
||||||
|
if (SaltySD_Connect())
|
||||||
|
return;
|
||||||
|
SaltySD_GetSharedMemoryHandle(&remoteSharedMemory);
|
||||||
|
SaltySD_Term();
|
||||||
|
shmemLoadRemote(&_sharedmemory, remoteSharedMemory, 0x1000, Perm_Rw);
|
||||||
|
if (!shmemMap(&_sharedmemory))
|
||||||
|
SharedMemoryUsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaltyNXIntegration::searchSharedMemoryBlock(uintptr_t base) {
|
||||||
|
ptrdiff_t search_offset = 0;
|
||||||
|
while (search_offset < 0x1000) {
|
||||||
|
NxFps = (NxFpsSharedBlock*)(base + search_offset);
|
||||||
|
if (NxFps->MAGIC == 0x465053)
|
||||||
|
return;
|
||||||
|
search_offset += 4;
|
||||||
|
}
|
||||||
|
NxFps = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 prevTid = 0;
|
||||||
|
u8 SaltyNXIntegration::GetFPS() {
|
||||||
|
if (!SharedMemoryUsed)
|
||||||
|
return 254;
|
||||||
|
|
||||||
|
u64 tid = ProcessManagement::GetCurrentApplicationId();
|
||||||
|
if (tid == 0)
|
||||||
|
return 254;
|
||||||
|
|
||||||
|
if (prevTid != tid) {
|
||||||
|
NxFps = 0;
|
||||||
|
prevTid = tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NxFps) {
|
||||||
|
uintptr_t base = (uintptr_t)shmemGetAddr(&_sharedmemory);
|
||||||
|
searchSharedMemoryBlock(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NxFps ? NxFps->FPS : 254;
|
||||||
}
|
}
|
||||||
@@ -29,25 +29,65 @@
|
|||||||
|
|
||||||
#include "clock_manager.h"
|
#include "clock_manager.h"
|
||||||
|
|
||||||
class ReverseNXSync {
|
class SysDockIntegration {
|
||||||
public:
|
public:
|
||||||
ReverseNXSync ();
|
SysDockIntegration();
|
||||||
|
|
||||||
void ToggleSync(bool enable) { m_sync_enabled = enable; };
|
bool getCurrentSysDockState();
|
||||||
void Reset(uint64_t app_id) { m_app_id = app_id; SetRTMode(ReverseNX_NotFound); GetToolMode(); }
|
};
|
||||||
ReverseNXMode GetRTMode() { return m_rt_mode; };
|
|
||||||
void SetRTMode(ReverseNXMode mode) { m_rt_mode = mode; };
|
|
||||||
ReverseNXMode GetToolMode() { return m_tool_mode = RecheckToolMode(); };
|
|
||||||
SysClkProfile GetProfile(SysClkProfile real);
|
|
||||||
ReverseNXMode GetMode();
|
|
||||||
|
|
||||||
protected:
|
class SaltyNXIntegration {
|
||||||
std::atomic<ReverseNXMode> m_rt_mode;
|
public:
|
||||||
ReverseNXMode m_tool_mode;
|
struct resolutionCalls {
|
||||||
uint64_t m_app_id = 0;
|
uint16_t width;
|
||||||
bool m_tool_enabled;
|
uint16_t height;
|
||||||
bool m_sync_enabled;
|
uint16_t calls;
|
||||||
|
};
|
||||||
|
|
||||||
ReverseNXMode GetToolModeFromPatch(const char* patch_path);
|
struct NxFpsSharedBlock {
|
||||||
ReverseNXMode RecheckToolMode();
|
uint32_t MAGIC;
|
||||||
|
uint8_t FPS;
|
||||||
|
float FPSavg;
|
||||||
|
bool pluginActive;
|
||||||
|
uint8_t FPSlocked;
|
||||||
|
uint8_t FPSmode;
|
||||||
|
uint8_t ZeroSync;
|
||||||
|
uint8_t patchApplied;
|
||||||
|
uint8_t API;
|
||||||
|
uint32_t FPSticks[10];
|
||||||
|
uint8_t Buffers;
|
||||||
|
uint8_t SetBuffers;
|
||||||
|
uint8_t ActiveBuffers;
|
||||||
|
uint8_t SetActiveBuffers;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
bool handheld: 1;
|
||||||
|
bool docked: 1;
|
||||||
|
unsigned int reserved: 6;
|
||||||
|
} NX_PACKED ds;
|
||||||
|
uint8_t general;
|
||||||
|
} displaySync;
|
||||||
|
resolutionCalls renderCalls[8];
|
||||||
|
resolutionCalls viewportCalls[8];
|
||||||
|
bool forceOriginalRefreshRate;
|
||||||
|
bool dontForce60InDocked;
|
||||||
|
bool forceSuspend;
|
||||||
|
uint8_t currentRefreshRate;
|
||||||
|
float readSpeedPerSecond;
|
||||||
|
uint8_t FPSlockedDocked;
|
||||||
|
uint64_t frameNumber;
|
||||||
|
} NX_PACKED;
|
||||||
|
|
||||||
|
NxFpsSharedBlock* NxFps = 0;
|
||||||
|
SharedMemory _sharedmemory = {};
|
||||||
|
bool SharedMemoryUsed = false;
|
||||||
|
Handle remoteSharedMemory = 1;
|
||||||
|
SaltyNXIntegration();
|
||||||
|
void LoadSaltyNX();
|
||||||
|
bool getCurrentSaltyNXState();
|
||||||
|
|
||||||
|
bool CheckPort();
|
||||||
|
void LoadSharedMemory();
|
||||||
|
void searchSharedMemoryBlock(uintptr_t base);
|
||||||
|
u8 GetFPS();
|
||||||
};
|
};
|
||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -43,7 +43,7 @@ IpcService::IpcService(ClockManager* clockMgr)
|
|||||||
|
|
||||||
this->running = false;
|
this->running = false;
|
||||||
this->clockMgr = clockMgr;
|
this->clockMgr = clockMgr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IpcService::SetRunning(bool running)
|
void IpcService::SetRunning(bool running)
|
||||||
@@ -119,9 +119,15 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SysClkIpcCmd_GetCurrentContext:
|
case SysClkIpcCmd_GetCurrentContext:
|
||||||
*out_dataSize = sizeof(SysClkContext);
|
if(r->data.size >= sizeof(std::uint64_t) && r->hipc.meta.num_recv_buffers >= 1)
|
||||||
return ipcSrv->GetCurrentContext((SysClkContext*)out_data);
|
{
|
||||||
|
size_t bufSize = hipcGetBufferSize(r->hipc.data.recv_buffers);
|
||||||
|
if(bufSize >= sizeof(SysClkContext))
|
||||||
|
{
|
||||||
|
return ipcSrv->GetCurrentContext((SysClkContext*)hipcGetBufferAddress(r->hipc.data.recv_buffers));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SysClkIpcCmd_Exit:
|
case SysClkIpcCmd_Exit:
|
||||||
return ipcSrv->Exit();
|
return ipcSrv->Exit();
|
||||||
|
|
||||||
@@ -198,27 +204,11 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8*
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SysClkIpcCmd_SetReverseNXRTMode:
|
|
||||||
if (r->data.size >= sizeof(ReverseNXMode)) {
|
|
||||||
ReverseNXMode mode = *((ReverseNXMode*)r->data.ptr);
|
|
||||||
return ipcSrv->SetReverseNXRTMode(mode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HocClkIpcCmd_SetKipData:
|
case HocClkIpcCmd_SetKipData:
|
||||||
if (r->data.size >= 0) {
|
if (r->data.size >= 0) {
|
||||||
return ipcSrv->SetKipData();
|
return ipcSrv->SetKipData();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HocClkIpcCmd_UpdateEmcRegs:
|
|
||||||
if (r->data.size >= 0) {
|
|
||||||
return ipcSrv->UpdateEmcRegs();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case HocClkIpcCmd_CalculateGpuVmin:
|
|
||||||
if (r->data.size >= 0) {
|
|
||||||
return ipcSrv->CalculateGPUVmin();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SYSCLK_ERROR(Generic);
|
return SYSCLK_ERROR(Generic);
|
||||||
@@ -371,29 +361,14 @@ Result IpcService::GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t*
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IpcService::SetReverseNXRTMode(ReverseNXMode mode) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IpcService::SetKipData() {
|
Result IpcService::SetKipData() {
|
||||||
this->clockMgr->SetKipData();
|
this->clockMgr->SetKipData();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IpcService::GetKipData() {
|
Result IpcService::GetKipData() {
|
||||||
this->clockMgr->GetKipData();
|
this->clockMgr->GetKipData();
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IpcService::UpdateEmcRegs() {
|
|
||||||
this->clockMgr->UpdateRamTimings();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IpcService::CalculateGPUVmin() {
|
|
||||||
this->clockMgr->calculateGpuVmin();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,8 @@ class IpcService
|
|||||||
Result GetConfigValues(SysClkConfigValueList* out_configValues);
|
Result GetConfigValues(SysClkConfigValueList* out_configValues);
|
||||||
Result SetConfigValues(SysClkConfigValueList* configValues);
|
Result SetConfigValues(SysClkConfigValueList* configValues);
|
||||||
Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count);
|
Result GetFreqList(SysClkIpc_GetFreqList_Args* args, std::uint32_t* out_list, std::size_t size, std::uint32_t* out_count);
|
||||||
Result SetReverseNXRTMode(ReverseNXMode mode);
|
|
||||||
Result SetKipData();
|
Result SetKipData();
|
||||||
Result GetKipData();
|
Result GetKipData();
|
||||||
Result UpdateEmcRegs();
|
|
||||||
Result CalculateGPUVmin();
|
|
||||||
bool running;
|
bool running;
|
||||||
Thread thread;
|
Thread thread;
|
||||||
LockableMutex threadMutex;
|
LockableMutex threadMutex;
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <switch.h>
|
#include <switch.h>
|
||||||
@@ -32,6 +32,8 @@ typedef struct {
|
|||||||
u32 hpMode;
|
u32 hpMode;
|
||||||
u32 commonEmcMemVolt;
|
u32 commonEmcMemVolt;
|
||||||
u32 eristaEmcMaxClock;
|
u32 eristaEmcMaxClock;
|
||||||
|
u32 eristaEmcMaxClock1;
|
||||||
|
u32 eristaEmcMaxClock2;
|
||||||
u32 marikoEmcMaxClock;
|
u32 marikoEmcMaxClock;
|
||||||
u32 marikoEmcVddqVolt;
|
u32 marikoEmcVddqVolt;
|
||||||
u32 emcDvbShift;
|
u32 emcDvbShift;
|
||||||
@@ -77,7 +79,11 @@ typedef struct {
|
|||||||
|
|
||||||
u32 eristaGpuVoltArray[27];
|
u32 eristaGpuVoltArray[27];
|
||||||
u32 marikoGpuVoltArray[24];
|
u32 marikoGpuVoltArray[24];
|
||||||
u32 reserved[64];
|
|
||||||
|
u32 t6_tRTW_fine_tune;
|
||||||
|
u32 t7_tWTR_fine_tune;
|
||||||
|
|
||||||
|
u32 reserved[60];
|
||||||
} CustomizeTable;
|
} CustomizeTable;
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
@@ -188,6 +194,8 @@ static inline bool cust_set_hp_mode(const char* p, u32 v) { CUST_WRITE_FIELD(p,
|
|||||||
|
|
||||||
static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); }
|
static inline bool cust_set_common_emc_volt(const char* p, u32 v) { CUST_WRITE_FIELD(p, commonEmcMemVolt, v); }
|
||||||
static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); }
|
static inline bool cust_set_erista_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock, v); }
|
||||||
|
static inline bool cust_set_erista_emc_max1(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock1, v); }
|
||||||
|
static inline bool cust_set_erista_emc_max2(const char* p, u32 v) { CUST_WRITE_FIELD(p, eristaEmcMaxClock2, v); }
|
||||||
static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); }
|
static inline bool cust_set_mariko_emc_max(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcMaxClock, v); }
|
||||||
static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); }
|
static inline bool cust_set_mariko_emc_vddq(const char* p, u32 v) { CUST_WRITE_FIELD(p, marikoEmcVddqVolt, v); }
|
||||||
static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); }
|
static inline bool cust_set_emc_dvb_shift(const char* p, u32 v) { CUST_WRITE_FIELD(p, emcDvbShift, v); }
|
||||||
@@ -200,6 +208,8 @@ static inline bool cust_set_tRFC(const char* p, u32 v) { CUST_WRITE_FIELD(p, t5_
|
|||||||
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
|
static inline bool cust_set_tRTW(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW, v); }
|
||||||
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
|
static inline bool cust_set_tWTR(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR, v); }
|
||||||
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
|
static inline bool cust_set_tREFI(const char* p, u32 v) { CUST_WRITE_FIELD(p, t8_tREFI, v); }
|
||||||
|
static inline bool cust_set_tRTW_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t6_tRTW_fine_tune, v); }
|
||||||
|
static inline bool cust_set_tWTR_fine_tune(const char* p, u32 v) { CUST_WRITE_FIELD(p, t7_tWTR_fine_tune, v); }
|
||||||
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
|
static inline bool cust_set_burst_read_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_read_latency, v); }
|
||||||
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
|
static inline bool cust_set_burst_write_lat(const char* p, u32 v) { CUST_WRITE_FIELD(p, mem_burst_write_latency, v); }
|
||||||
|
|
||||||
@@ -255,6 +265,8 @@ static inline u32 cust_get_hp_mode(const CustomizeTable* t) { return CUST_GET_FI
|
|||||||
|
|
||||||
static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); }
|
static inline u32 cust_get_common_emc_volt(const CustomizeTable* t) { return CUST_GET_FIELD(t, commonEmcMemVolt); }
|
||||||
static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); }
|
static inline u32 cust_get_erista_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock); }
|
||||||
|
static inline u32 cust_get_erista_emc_max1(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock1); }
|
||||||
|
static inline u32 cust_get_erista_emc_max2(const CustomizeTable* t) { return CUST_GET_FIELD(t, eristaEmcMaxClock2); }
|
||||||
static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); }
|
static inline u32 cust_get_mariko_emc_max(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcMaxClock); }
|
||||||
static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); }
|
static inline u32 cust_get_mariko_emc_vddq(const CustomizeTable* t) { return CUST_GET_FIELD(t, marikoEmcVddqVolt); }
|
||||||
static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); }
|
static inline u32 cust_get_emc_dvb_shift(const CustomizeTable* t) { return CUST_GET_FIELD(t, emcDvbShift); }
|
||||||
@@ -267,6 +279,8 @@ static inline u32 cust_get_tRFC(const CustomizeTable* t) { return CUST_GET_FIELD
|
|||||||
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
|
static inline u32 cust_get_tRTW(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW); }
|
||||||
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
|
static inline u32 cust_get_tWTR(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR); }
|
||||||
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
|
static inline u32 cust_get_tREFI(const CustomizeTable* t) { return CUST_GET_FIELD(t, t8_tREFI); }
|
||||||
|
static inline u32 cust_get_tRTW_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t6_tRTW_fine_tune); }
|
||||||
|
static inline u32 cust_get_tWTR_fine_tune(const CustomizeTable* t) { return CUST_GET_FIELD(t, t7_tWTR_fine_tune); }
|
||||||
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
|
static inline u32 cust_get_burst_read_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_read_latency); }
|
||||||
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }
|
static inline u32 cust_get_burst_write_lat(const CustomizeTable* t) { return CUST_GET_FIELD(t, mem_burst_write_latency); }
|
||||||
|
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -36,10 +36,13 @@
|
|||||||
#include "process_management.h"
|
#include "process_management.h"
|
||||||
#include "clock_manager.h"
|
#include "clock_manager.h"
|
||||||
#include "ipc_service.h"
|
#include "ipc_service.h"
|
||||||
#define INNER_HEAP_SIZE 0x30000
|
#define INNER_HEAP_SIZE 0x40000
|
||||||
|
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
void virtmemSetup(void);
|
||||||
|
|
||||||
extern std::uint32_t __start__;
|
extern std::uint32_t __start__;
|
||||||
|
|
||||||
std::uint32_t __nx_applet_type = AppletType_None;
|
std::uint32_t __nx_applet_type = AppletType_None;
|
||||||
@@ -62,6 +65,8 @@ extern "C"
|
|||||||
|
|
||||||
fake_heap_start = (char*)addr;
|
fake_heap_start = (char*)addr;
|
||||||
fake_heap_end = (char*)addr + size;
|
fake_heap_end = (char*)addr + size;
|
||||||
|
|
||||||
|
virtmemSetup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __appInit(void)
|
void __appInit(void)
|
||||||
@@ -80,14 +85,17 @@ extern "C"
|
|||||||
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro));
|
||||||
setsysExit();
|
setsysExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
// rc = fanInitialize();
|
// rc = fanInitialize();
|
||||||
// if (R_FAILED(rc))
|
// if (R_FAILED(rc))
|
||||||
// diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
// diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||||
|
|
||||||
rc = i2cInitialize();
|
rc = i2cInitialize();
|
||||||
if (R_FAILED(rc))
|
if (R_FAILED(rc))
|
||||||
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||||
|
rc = appletInitialize();
|
||||||
|
if (R_FAILED(rc))
|
||||||
|
diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen));
|
||||||
}
|
}
|
||||||
|
|
||||||
void __appExit(void)
|
void __appExit(void)
|
||||||
@@ -96,7 +104,8 @@ extern "C"
|
|||||||
// fanExit();
|
// fanExit();
|
||||||
i2cExit();
|
i2cExit();
|
||||||
fsExit();
|
fsExit();
|
||||||
fsdevUnmountAll();
|
fsdevUnmountAll();
|
||||||
|
appletExit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +163,6 @@ int main(int argc, char** argv)
|
|||||||
FileUtils::LogLine("Exit");
|
FileUtils::LogLine("Exit");
|
||||||
svcSleepThread(1000000ULL);
|
svcSleepThread(1000000ULL);
|
||||||
FileUtils::Exit();
|
FileUtils::Exit();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
assets/logo.png
BIN
assets/logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 233 KiB |
18
build.sh
18
build.sh
@@ -21,20 +21,4 @@ cd ../../
|
|||||||
|
|
||||||
cd Source/Horizon-OC-Monitor/
|
cd Source/Horizon-OC-Monitor/
|
||||||
make -j"$(nproc)"
|
make -j"$(nproc)"
|
||||||
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
cp Horizon-OC-Monitor.ovl ../../dist/switch/.overlays/Horizon-OC-Monitor.ovl
|
||||||
|
|
||||||
cd ../../
|
|
||||||
|
|
||||||
ROOT="build"
|
|
||||||
PATCHES="Source/Atmosphere-Patches"
|
|
||||||
|
|
||||||
cp "$PATCHES/secmon_memory_layout.hpp" "$ROOT/libraries/libexosphere/include/exosphere/secmon/"
|
|
||||||
cp "$PATCHES/secmon_emc_access_table_data.inc" "$ROOT/exosphere/program/source/smc/"
|
|
||||||
cp "$PATCHES/secmon_define_emc_access_table.inc" "$ROOT/exosphere/program/source/smc/"
|
|
||||||
cp "$PATCHES/secmon_smc_register_access.cpp" "$ROOT/exosphere/program/source/smc/"
|
|
||||||
cd build/exosphere
|
|
||||||
|
|
||||||
make -j"$(nproc)"
|
|
||||||
|
|
||||||
cd out/nintendo_nx_arm64_armv8a/release
|
|
||||||
cp "exosphere.bin" "../../../../../dist/"
|
|
||||||
18
dist/README.md
vendored
18
dist/README.md
vendored
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
|
|
||||||
<img src="assets/logo.png" alt="logo" width="350"/>
|
<img src="assets/logo.png" alt="logo" width="768"/>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -36,12 +36,12 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
|
|||||||
|
|
||||||
* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista)
|
* **CPU:** Up to 1963MHz (Mariko) / 1785MHz (Erista)
|
||||||
* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista)
|
* **GPU:** Up to 1075MHz (Mariko) / 921MHz (Erista)
|
||||||
* **RAM:** Up to 1866MHz (Mariko) / 1600MHz (Erista)
|
* **RAM:** Up to 1866/2133MHz (Mariko) / 1600MHz (Erista)
|
||||||
* Over/undervolting support
|
* Over/undervolting support
|
||||||
* Built-in configurator
|
* Built-in configurator
|
||||||
* Compatible with most homebrew
|
* Compatible with most homebrew
|
||||||
|
|
||||||
> It is reccomended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
|
> It is recommended to read the [guide](https://rentry.co/howtoget60fps) before proceeding, as this can help you get a *significant* performance boost over the default settings, often times with less power draw and heat output
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -56,7 +56,6 @@ It enables advanced CPU, GPU, and RAM tuning with user-friendly configuration to
|
|||||||
|
|
||||||
```
|
```
|
||||||
kip1=atmosphere/kips/hoc.kip
|
kip1=atmosphere/kips/hoc.kip
|
||||||
secmon=exosphere.bin
|
|
||||||
```
|
```
|
||||||
|
|
||||||
*(No changes needed if using fusee.)*
|
*(No changes needed if using fusee.)*
|
||||||
@@ -114,6 +113,9 @@ Refer to COMPILATION.md
|
|||||||
* 816
|
* 816
|
||||||
* 714
|
* 714
|
||||||
* 612 → sleep mode
|
* 612 → sleep mode
|
||||||
|
|
||||||
|
**Notes:**
|
||||||
|
1. On Erista, CPU in handheld is capped to 1581MHz
|
||||||
|
|
||||||
### GPU clocks
|
### GPU clocks
|
||||||
* 1536 → absolute max clock on mariko. very dangerous
|
* 1536 → absolute max clock on mariko. very dangerous
|
||||||
@@ -140,8 +142,10 @@ Refer to COMPILATION.md
|
|||||||
* 76 → boost mode
|
* 76 → boost mode
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
1. GPU overclock is capped at 460MHz in handheld and capped at 768MHz if charging, unless you're using the official charger.
|
1. GPU overclock is capped at 460MHz on erista in handheld
|
||||||
2. Clocks higher than 768MHz need the official charger is plugged in.
|
2. On Mariko, cap with No uv is 614MHz, with SLT it is 691MHz and with HiOPT it's 768MHz
|
||||||
|
3. Clocks higher than 768MHz on erista need the official charger is plugged in.
|
||||||
|
4. On Mariko, cap with No uv is 844MHz, with SLT it is 921MHz and with HiOPT it's 998MHz
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -160,5 +164,5 @@ Refer to COMPILATION.md
|
|||||||
* **b0rd2death** – Ultrahand sys-clk & Status Monitor fork
|
* **b0rd2death** – Ultrahand sys-clk & Status Monitor fork
|
||||||
* **MasaGratoR and ZachyCatGames** - General help
|
* **MasaGratoR and ZachyCatGames** - General help
|
||||||
* **MasaGratoR** - Status Monitor & Display Refresh Rate Driver
|
* **MasaGratoR** - Status Monitor & Display Refresh Rate Driver
|
||||||
* **Dom, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh and Xenshen** - Testing
|
* **Dom, Samybigio, Arcdelta, Miki, Happy, Flopsider, Winnerboi77, Blaise, Alvise, TDRR, agjeococh, frost, letum00 and Xenshen** - Testing
|
||||||
* **Samybigio2011** - Italian translations
|
* **Samybigio2011** - Italian translations
|
||||||
|
|||||||
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
BIN
dist/atmosphere/contents/00FF0000636C6BFF/exefs.nsp
vendored
Binary file not shown.
BIN
dist/atmosphere/kips/hoc.kip
vendored
BIN
dist/atmosphere/kips/hoc.kip
vendored
Binary file not shown.
132
dist/config/horizon-oc/lang/en.json
vendored
Normal file
132
dist/config/horizon-oc/lang/en.json
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "Edit App Profile",
|
||||||
|
"Advanced": "Advanced",
|
||||||
|
"Edit Global Profile": "Edit Global Profile",
|
||||||
|
"Temporary Overrides": "Temporary Overrides",
|
||||||
|
"Temporary Overrides Reset": "Temporary Overrides Reset",
|
||||||
|
"Settings": "Settings",
|
||||||
|
"Information": "Information",
|
||||||
|
"Enable": "Enable",
|
||||||
|
"Uncapped Clocks": "Uncapped Clocks",
|
||||||
|
"Override Boost Mode": "Override Boost Mode",
|
||||||
|
"CPU Max Display Clock": "CPU Max Display Clock",
|
||||||
|
"Thermal Throttle": "Thermal Throttle",
|
||||||
|
"Thermal Throttle Threshold": "Thermal Throttle Threshold",
|
||||||
|
"Handheld TDP": "Handheld TDP",
|
||||||
|
"Handheld TDP Limit": "Handheld TDP Limit",
|
||||||
|
"Lite TDP Limit": "Lite TDP Limit",
|
||||||
|
"Enforce Board Limit": "Enforce Board Limit",
|
||||||
|
"Battery Charge Current": "Battery Charge Current",
|
||||||
|
"Display Refresh Rate Changing": "Display Refresh Rate Changing",
|
||||||
|
"Fix CPU Volt Bug": "Fix CPU Volt Bug",
|
||||||
|
"[cfg] no enum format string": "[cfg] no enum format string",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "Save KIP Settings",
|
||||||
|
"RAM Settings": "RAM Settings",
|
||||||
|
"CPU Settings": "CPU Settings",
|
||||||
|
"GPU Settings": "GPU Settings",
|
||||||
|
"Experimental": "Experimental",
|
||||||
|
"Charge Current Override": "Charge Current Override",
|
||||||
|
"Disabled": "Disabled",
|
||||||
|
"HP Mode": "HP Mode",
|
||||||
|
"EMC Max Clock": "EMC Max Clock",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 Voltage",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ Voltage",
|
||||||
|
"DVB Shift": "DVB Shift",
|
||||||
|
"Memory Timings": "Memory Timings",
|
||||||
|
"Memory Latencies": "Memory Latencies",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "Update RAM Timings",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 This feature is EXPERIMENTAL",
|
||||||
|
"and should only be used for testing!": "and should only be used for testing!",
|
||||||
|
"Read Latency": "Read Latency",
|
||||||
|
"Write Latency": "Write Latency",
|
||||||
|
"CPU UV": "CPU UV",
|
||||||
|
"CPU Unlock": "CPU Unlock",
|
||||||
|
"CPU VMIN": "CPU VMIN",
|
||||||
|
"CPU Max Voltage": "CPU Max Voltage",
|
||||||
|
"CPU UV Table": "CPU UV Table",
|
||||||
|
"CPU Low UV": "CPU Low UV",
|
||||||
|
"CPU High UV": "CPU High UV",
|
||||||
|
"CPU Max Clock": "CPU Max Clock",
|
||||||
|
"CPU Low VMIN": "CPU Low VMIN",
|
||||||
|
"CPU High VMIN": "CPU High VMIN",
|
||||||
|
"GPU Undervolt Table": "GPU Undervolt Table",
|
||||||
|
"Calculate GPU Vmin": "Calculate GPU Vmin",
|
||||||
|
"GPU VMIN": "GPU VMIN",
|
||||||
|
"GPU VMAX": "GPU VMAX",
|
||||||
|
"GPU Volt Offset": "GPU Volt Offset",
|
||||||
|
"GPU Custom Table": "GPU Custom Table",
|
||||||
|
"GPU Custom Table (mV)": "GPU Custom Table (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 Setting GPU Clocks past",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "1075MHz without UV, 1152MHz on SLT or ",
|
||||||
|
"1228MHz on HiOPT can cause ": "1228MHz on HiOPT can cause ",
|
||||||
|
"permanent damage to your Switch!": "permanent damage to your Switch!",
|
||||||
|
"Proceed at your own risk!": "Proceed at your own risk!",
|
||||||
|
"921MHz without UV and 960MHz on": "921MHz without UV and 960MHz on",
|
||||||
|
"SLT or HiOPT can cause ": "SLT or HiOPT can cause ",
|
||||||
|
"Auto": "Auto",
|
||||||
|
"Sleep Mode": "Sleep Mode",
|
||||||
|
"Stock": "Stock",
|
||||||
|
"Dev OC": "Dev OC",
|
||||||
|
"Boost Mode": "Boost Mode",
|
||||||
|
"Safe Max": "Safe Max",
|
||||||
|
"Unsafe Max": "Unsafe Max",
|
||||||
|
"Absolute Max": "Absolute Max",
|
||||||
|
"Boost Mode & Safe Max": "Boost Mode & Safe Max",
|
||||||
|
"Official Rating": "Official Rating",
|
||||||
|
"Default (Mariko)": "Default (Mariko)",
|
||||||
|
"Default (Erista)": "Default (Erista)",
|
||||||
|
"Rating": "Rating",
|
||||||
|
"Safe Max (Mariko)": "Safe Max (Mariko)",
|
||||||
|
"Safe Max (Erista)": "Safe Max (Erista)",
|
||||||
|
"Default": "Default",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "Extreme UV Table",
|
||||||
|
"No UV": "No UV",
|
||||||
|
"SLT Table": "SLT Table",
|
||||||
|
"HiOPT Table": "HiOPT Table",
|
||||||
|
"Power": "Power",
|
||||||
|
"Temp": "Temp",
|
||||||
|
"Voltage": "Voltage",
|
||||||
|
"TDP Threshold": "TDP Threshold",
|
||||||
|
"Lite TDP Threshold": "Lite TDP Threshold",
|
||||||
|
"Thermal Throttle Limit": "Thermal Throttle Limit",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "BAT",
|
||||||
|
"FAN": "FAN",
|
||||||
|
"DISP": "DISP",
|
||||||
|
"Board": "Board",
|
||||||
|
"Skin": "Skin",
|
||||||
|
"Now": "Now",
|
||||||
|
"Avg": "Avg",
|
||||||
|
"App ID": "App ID",
|
||||||
|
"Profile": "Profile",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "Memory",
|
||||||
|
"Display": "Display",
|
||||||
|
"Governor": "Governor",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "Docked",
|
||||||
|
"Handheld": "Handheld",
|
||||||
|
"Charging": "Charging",
|
||||||
|
"USB Charger": "USB Charger",
|
||||||
|
"PD Charger": "PD Charger",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
35
dist/config/horizon-oc/lang/es.json
vendored
Normal file
35
dist/config/horizon-oc/lang/es.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"Edit App Profile": "Editar perfil de la app",
|
||||||
|
"Advanced": "Avanzado",
|
||||||
|
"Edit Global Profile": "Editar perfil global",
|
||||||
|
"Temporary Overrides": "Anulaciones temporales",
|
||||||
|
"Temporary Overrides Reset": "Anulaciones temporales Reiniciar",
|
||||||
|
"Settings": "Configuración",
|
||||||
|
"Enable": "Habilitar",
|
||||||
|
"Uncapped Clocks": "Relojes sin límite",
|
||||||
|
"Override Boost Mode": "Sobrescribir modo Boost",
|
||||||
|
"Auto CPU Boost": "Impulso automático de CPU",
|
||||||
|
"Sync ReverseNX": "Sincronizar con ReverseNX",
|
||||||
|
"GPU DVFS": "GPU DVFS",
|
||||||
|
"Off": "Apagado",
|
||||||
|
"Official Service Method": "Método de servicio oficial",
|
||||||
|
"Hijack Method": "Método de secuestro",
|
||||||
|
"App ID": "ID App",
|
||||||
|
"EOS mode": "Modo EOS",
|
||||||
|
"Skin": "Tema",
|
||||||
|
"Now": "Ahora",
|
||||||
|
"Avg": "Med",
|
||||||
|
"Docked": "Conectado al dock",
|
||||||
|
"Handheld": "Portátil",
|
||||||
|
"Charging": "Cargando",
|
||||||
|
"PD Charger": "Cargador oficial",
|
||||||
|
"USB Charger": "Cargador USB",
|
||||||
|
"Docked Reset": "Conectado al dock Reiniciar",
|
||||||
|
"Handheld Reset": "Portátil Reiniciar",
|
||||||
|
"Charging Reset": "Cargando Reiniciar",
|
||||||
|
"PD Charger Reset": "Cargador oficial Reiniciar",
|
||||||
|
"USB Charger Reset": "Cargador USB Reiniciar",
|
||||||
|
"Memory": "Memoria",
|
||||||
|
"Default": "No sobrescribir",
|
||||||
|
"Profile": "Perfil"
|
||||||
|
}
|
||||||
132
dist/config/horizon-oc/lang/it.json
vendored
Normal file
132
dist/config/horizon-oc/lang/it.json
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Information about Translation": "This is a translation made by Samybigio2011. If you find any errors, please report them on GitHub, or feel free to contribute!",
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "Profilo App",
|
||||||
|
"Advanced": "Avanzate",
|
||||||
|
"Edit Global Profile": "Profilo Globale",
|
||||||
|
"Temporary Overrides": "Override Temporaneo",
|
||||||
|
"Temporary Overrides Reset": "Temporary Overrides Reset",
|
||||||
|
"Settings": "Impostazioni",
|
||||||
|
"Information": "Informazioni",
|
||||||
|
"Enable": "Abilita",
|
||||||
|
"Uncapped Clocks": "Sblocca Clock",
|
||||||
|
"Override Boost Mode": "Sovrascrivi Boost Mode",
|
||||||
|
"CPU Max Display Clock": "Massimo Clock CPU mostrato",
|
||||||
|
"Thermal Throttle": "Rallentamento Termico",
|
||||||
|
"Thermal Throttle Threshold": "Soglia Rallentamento Termico",
|
||||||
|
"Handheld TDP": "TPD Handheld",
|
||||||
|
"Handheld TDP Limit": "Limite TDP Handheld",
|
||||||
|
"Lite TDP Limit": "Limite TDP Lite",
|
||||||
|
"Enforce Board Limit": "Forza Limite di Potenza",
|
||||||
|
"Battery Charge Current": "Corrente di Ricarica",
|
||||||
|
"Display Refresh Rate Changing": "Cambio di Frequenza Display",
|
||||||
|
"Fix CPU Volt Bug": "Risolvi Bug CPU",
|
||||||
|
"[cfg] no enum format string": "[cfg] no enum format string",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "Salva Impotazioni KIP",
|
||||||
|
"RAM Settings": "Impostazioni RAM",
|
||||||
|
"CPU Settings": "Impostazioni CPU",
|
||||||
|
"GPU Settings": "Impostazioni GPU",
|
||||||
|
"Experimental": "Esperimentale",
|
||||||
|
"Charge Current Override": "Sovrascrivi Corrente di Ricarica",
|
||||||
|
"Disabled": "Disabilitato",
|
||||||
|
"HP Mode": "Modalità HP",
|
||||||
|
"EMC Max Clock": "Clock EMC Massimo",
|
||||||
|
"EMC VDD2 Voltage": "Voltaggio VDD2 EMC",
|
||||||
|
"EMC VDDQ Voltage": "Voltaggio VDDQ EMC",
|
||||||
|
"DVB Shift": "Shift DVB",
|
||||||
|
"Memory Timings": "Timing Memoria",
|
||||||
|
"Memory Latencies": "Latency Memoria",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "Aggiorna Timing RAM",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 Questa funzione è ESPERIMENRALE!",
|
||||||
|
"and should only be used for testing!": "e dovrebbe essere usata solo per testare!",
|
||||||
|
"Read Latency": "Latency Lettura",
|
||||||
|
"Write Latency": "Latency Scrittura",
|
||||||
|
"CPU UV": "UV CPU",
|
||||||
|
"CPU Unlock": "Sblocco CPU",
|
||||||
|
"CPU VMIN": "VMIN CPU",
|
||||||
|
"CPU Max Voltage": "Voltaggio Massimo CPU",
|
||||||
|
"CPU UV Table": "Tavola UV CPU",
|
||||||
|
"CPU Low UV": "UV Basso CPU",
|
||||||
|
"CPU High UV": "UV Alto CPU",
|
||||||
|
"CPU Max Clock": "Clock Massimo CPU",
|
||||||
|
"CPU Low VMIN": "VMIN Basso CPU",
|
||||||
|
"CPU High VMIN": "VMIN Alto CPU",
|
||||||
|
"GPU Undervolt Table": "Tavola Undervolt GPU",
|
||||||
|
"Calculate GPU Vmin": "Calcola VMIN GPU",
|
||||||
|
"GPU VMIN": "VMIN GPU",
|
||||||
|
"GPU VMAX": "VMAX GPU",
|
||||||
|
"GPU Volt Offset": "Offset Voltaggio GPU",
|
||||||
|
"GPU Custom Table": "Tavola GPU Custom",
|
||||||
|
"GPU Custom Table (mV)": "Tavola GPU Custom (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 Impostare Clock GPU oltre",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "1075MHz senza UV, 1152MHz su SLT o ",
|
||||||
|
"1228MHz on HiOPT can cause ": "1228MHz su HiOPT può causare ",
|
||||||
|
"permanent damage to your Switch!": "danni permanenti alla tua console!",
|
||||||
|
"Proceed at your own risk!": "Procedi al tuo rischio!",
|
||||||
|
"921MHz without UV and 960MHz on": "921MHz senza UV e 960MHz su",
|
||||||
|
"SLT or HiOPT can cause ": "SLT o HiOPT può causare ",
|
||||||
|
"Auto": "Auto",
|
||||||
|
"Sleep Mode": "Modalità Sleep",
|
||||||
|
"Stock": "Stock",
|
||||||
|
"Dev OC": "OC Sviluppo",
|
||||||
|
"Boost Mode": "Modalità Boost",
|
||||||
|
"Safe Max": "Massimo Sicuro",
|
||||||
|
"Unsafe Max": "Massimo Insicuro",
|
||||||
|
"Absolute Max": "Massimo Assoluto",
|
||||||
|
"Boost Mode & Safe Max": "Modalità Boost e Massimo Sicuro",
|
||||||
|
"Official Rating": "Rating Ufficiale",
|
||||||
|
"Default (Mariko)": "Default (Mariko)",
|
||||||
|
"Default (Erista)": "Default (Erista)",
|
||||||
|
"Rating": "Rating",
|
||||||
|
"Safe Max (Mariko)": "Max Sicuro (Mariko)",
|
||||||
|
"Safe Max (Erista)": "Max Sicuro (Erista)",
|
||||||
|
"Default": "Default",
|
||||||
|
"1581MHz Tbreak": "Tbreak 1581MHz",
|
||||||
|
"1683MHz Tbreak": "Tbreak 1683MHz",
|
||||||
|
"Extreme UV Table": "Tavola UV Estremo",
|
||||||
|
"No UV": "No UV",
|
||||||
|
"SLT Table": "Tavola SLT",
|
||||||
|
"HiOPT Table": "Tavola HiOPT",
|
||||||
|
"Power": "Potenza",
|
||||||
|
"Temp": "Temperatura",
|
||||||
|
"Voltage": "Voltaggio",
|
||||||
|
"TDP Threshold": "Soglia TDP",
|
||||||
|
"Lite TDP Threshold": "Soglia TDP Lite",
|
||||||
|
"Thermal Throttle Limit": "Limite Rallentamento Termico",
|
||||||
|
"1600BL": "BL1600",
|
||||||
|
"1866BL": "BL1866",
|
||||||
|
"2133BL": "BL2133",
|
||||||
|
"BAT": "BAT",
|
||||||
|
"FAN": "FAN",
|
||||||
|
"DISP": "DISP",
|
||||||
|
"Board": "Scheda",
|
||||||
|
"Skin": "Skin",
|
||||||
|
"Now": "Ora",
|
||||||
|
"Avg": "Med",
|
||||||
|
"App ID": "ID App",
|
||||||
|
"Profile": "Profilo",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "Memoria",
|
||||||
|
"Display": "Display",
|
||||||
|
"Governor": "Governor",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "Dock",
|
||||||
|
"Handheld": "Handheld",
|
||||||
|
"Charging": "In Carica",
|
||||||
|
"USB Charger": "Caricatore USB",
|
||||||
|
"PD Charger": "Caricatore PD",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ"
|
||||||
|
}
|
||||||
132
dist/config/horizon-oc/lang/lang/en.json
vendored
Normal file
132
dist/config/horizon-oc/lang/lang/en.json
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "Edit App Profile",
|
||||||
|
"Advanced": "Advanced",
|
||||||
|
"Edit Global Profile": "Edit Global Profile",
|
||||||
|
"Temporary Overrides": "Temporary Overrides",
|
||||||
|
"Temporary Overrides Reset": "Temporary Overrides Reset",
|
||||||
|
"Settings": "Settings",
|
||||||
|
"Information": "Information",
|
||||||
|
"Enable": "Enable",
|
||||||
|
"Uncapped Clocks": "Uncapped Clocks",
|
||||||
|
"Override Boost Mode": "Override Boost Mode",
|
||||||
|
"CPU Max Display Clock": "CPU Max Display Clock",
|
||||||
|
"Thermal Throttle": "Thermal Throttle",
|
||||||
|
"Thermal Throttle Threshold": "Thermal Throttle Threshold",
|
||||||
|
"Handheld TDP": "Handheld TDP",
|
||||||
|
"Handheld TDP Limit": "Handheld TDP Limit",
|
||||||
|
"Lite TDP Limit": "Lite TDP Limit",
|
||||||
|
"Enforce Board Limit": "Enforce Board Limit",
|
||||||
|
"Battery Charge Current": "Battery Charge Current",
|
||||||
|
"Display Refresh Rate Changing": "Display Refresh Rate Changing",
|
||||||
|
"Fix CPU Volt Bug": "Fix CPU Volt Bug",
|
||||||
|
"[cfg] no enum format string": "[cfg] no enum format string",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "Save KIP Settings",
|
||||||
|
"RAM Settings": "RAM Settings",
|
||||||
|
"CPU Settings": "CPU Settings",
|
||||||
|
"GPU Settings": "GPU Settings",
|
||||||
|
"Experimental": "Experimental",
|
||||||
|
"Charge Current Override": "Charge Current Override",
|
||||||
|
"Disabled": "Disabled",
|
||||||
|
"HP Mode": "HP Mode",
|
||||||
|
"EMC Max Clock": "EMC Max Clock",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 Voltage",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ Voltage",
|
||||||
|
"DVB Shift": "DVB Shift",
|
||||||
|
"Memory Timings": "Memory Timings",
|
||||||
|
"Memory Latencies": "Memory Latencies",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "Update RAM Timings",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 This feature is EXPERIMENTAL",
|
||||||
|
"and should only be used for testing!": "and should only be used for testing!",
|
||||||
|
"Read Latency": "Read Latency",
|
||||||
|
"Write Latency": "Write Latency",
|
||||||
|
"CPU UV": "CPU UV",
|
||||||
|
"CPU Unlock": "CPU Unlock",
|
||||||
|
"CPU VMIN": "CPU VMIN",
|
||||||
|
"CPU Max Voltage": "CPU Max Voltage",
|
||||||
|
"CPU UV Table": "CPU UV Table",
|
||||||
|
"CPU Low UV": "CPU Low UV",
|
||||||
|
"CPU High UV": "CPU High UV",
|
||||||
|
"CPU Max Clock": "CPU Max Clock",
|
||||||
|
"CPU Low VMIN": "CPU Low VMIN",
|
||||||
|
"CPU High VMIN": "CPU High VMIN",
|
||||||
|
"GPU Undervolt Table": "GPU Undervolt Table",
|
||||||
|
"Calculate GPU Vmin": "Calculate GPU Vmin",
|
||||||
|
"GPU VMIN": "GPU VMIN",
|
||||||
|
"GPU VMAX": "GPU VMAX",
|
||||||
|
"GPU Volt Offset": "GPU Volt Offset",
|
||||||
|
"GPU Custom Table": "GPU Custom Table",
|
||||||
|
"GPU Custom Table (mV)": "GPU Custom Table (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 Setting GPU Clocks past",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "1075MHz without UV, 1152MHz on SLT or ",
|
||||||
|
"1228MHz on HiOPT can cause ": "1228MHz on HiOPT can cause ",
|
||||||
|
"permanent damage to your Switch!": "permanent damage to your Switch!",
|
||||||
|
"Proceed at your own risk!": "Proceed at your own risk!",
|
||||||
|
"921MHz without UV and 960MHz on": "921MHz without UV and 960MHz on",
|
||||||
|
"SLT or HiOPT can cause ": "SLT or HiOPT can cause ",
|
||||||
|
"Auto": "Auto",
|
||||||
|
"Sleep Mode": "Sleep Mode",
|
||||||
|
"Stock": "Stock",
|
||||||
|
"Dev OC": "Dev OC",
|
||||||
|
"Boost Mode": "Boost Mode",
|
||||||
|
"Safe Max": "Safe Max",
|
||||||
|
"Unsafe Max": "Unsafe Max",
|
||||||
|
"Absolute Max": "Absolute Max",
|
||||||
|
"Boost Mode & Safe Max": "Boost Mode & Safe Max",
|
||||||
|
"Official Rating": "Official Rating",
|
||||||
|
"Default (Mariko)": "Default (Mariko)",
|
||||||
|
"Default (Erista)": "Default (Erista)",
|
||||||
|
"Rating": "Rating",
|
||||||
|
"Safe Max (Mariko)": "Safe Max (Mariko)",
|
||||||
|
"Safe Max (Erista)": "Safe Max (Erista)",
|
||||||
|
"Default": "Default",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "Extreme UV Table",
|
||||||
|
"No UV": "No UV",
|
||||||
|
"SLT Table": "SLT Table",
|
||||||
|
"HiOPT Table": "HiOPT Table",
|
||||||
|
"Power": "Power",
|
||||||
|
"Temp": "Temp",
|
||||||
|
"Voltage": "Voltage",
|
||||||
|
"TDP Threshold": "TDP Threshold",
|
||||||
|
"Lite TDP Threshold": "Lite TDP Threshold",
|
||||||
|
"Thermal Throttle Limit": "Thermal Throttle Limit",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "BAT",
|
||||||
|
"FAN": "FAN",
|
||||||
|
"DISP": "DISP",
|
||||||
|
"Board": "Board",
|
||||||
|
"Skin": "Skin",
|
||||||
|
"Now": "Now",
|
||||||
|
"Avg": "Avg",
|
||||||
|
"App ID": "App ID",
|
||||||
|
"Profile": "Profile",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "Memory",
|
||||||
|
"Display": "Display",
|
||||||
|
"Governor": "Governor",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "Docked",
|
||||||
|
"Handheld": "Handheld",
|
||||||
|
"Charging": "Charging",
|
||||||
|
"USB Charger": "USB Charger",
|
||||||
|
"PD Charger": "PD Charger",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
35
dist/config/horizon-oc/lang/lang/es.json
vendored
Normal file
35
dist/config/horizon-oc/lang/lang/es.json
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"Edit App Profile": "Editar perfil de la app",
|
||||||
|
"Advanced": "Avanzado",
|
||||||
|
"Edit Global Profile": "Editar perfil global",
|
||||||
|
"Temporary Overrides": "Anulaciones temporales",
|
||||||
|
"Temporary Overrides Reset": "Anulaciones temporales Reiniciar",
|
||||||
|
"Settings": "Configuración",
|
||||||
|
"Enable": "Habilitar",
|
||||||
|
"Uncapped Clocks": "Relojes sin límite",
|
||||||
|
"Override Boost Mode": "Sobrescribir modo Boost",
|
||||||
|
"Auto CPU Boost": "Impulso automático de CPU",
|
||||||
|
"Sync ReverseNX": "Sincronizar con ReverseNX",
|
||||||
|
"GPU DVFS": "GPU DVFS",
|
||||||
|
"Off": "Apagado",
|
||||||
|
"Official Service Method": "Método de servicio oficial",
|
||||||
|
"Hijack Method": "Método de secuestro",
|
||||||
|
"App ID": "ID App",
|
||||||
|
"EOS mode": "Modo EOS",
|
||||||
|
"Skin": "Tema",
|
||||||
|
"Now": "Ahora",
|
||||||
|
"Avg": "Med",
|
||||||
|
"Docked": "Conectado al dock",
|
||||||
|
"Handheld": "Portátil",
|
||||||
|
"Charging": "Cargando",
|
||||||
|
"PD Charger": "Cargador oficial",
|
||||||
|
"USB Charger": "Cargador USB",
|
||||||
|
"Docked Reset": "Conectado al dock Reiniciar",
|
||||||
|
"Handheld Reset": "Portátil Reiniciar",
|
||||||
|
"Charging Reset": "Cargando Reiniciar",
|
||||||
|
"PD Charger Reset": "Cargador oficial Reiniciar",
|
||||||
|
"USB Charger Reset": "Cargador USB Reiniciar",
|
||||||
|
"Memory": "Memoria",
|
||||||
|
"Default": "No sobrescribir",
|
||||||
|
"Profile": "Perfil"
|
||||||
|
}
|
||||||
132
dist/config/horizon-oc/lang/lang/it.json
vendored
Normal file
132
dist/config/horizon-oc/lang/lang/it.json
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Information about Translation": "This is a translation made by Samybigio2011. If you find any errors, please report them on GitHub, or feel free to contribute!",
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "Profilo App",
|
||||||
|
"Advanced": "Avanzate",
|
||||||
|
"Edit Global Profile": "Profilo Globale",
|
||||||
|
"Temporary Overrides": "Override Temporaneo",
|
||||||
|
"Temporary Overrides Reset": "Temporary Overrides Reset",
|
||||||
|
"Settings": "Impostazioni",
|
||||||
|
"Information": "Informazioni",
|
||||||
|
"Enable": "Abilita",
|
||||||
|
"Uncapped Clocks": "Sblocca Clock",
|
||||||
|
"Override Boost Mode": "Sovrascrivi Boost Mode",
|
||||||
|
"CPU Max Display Clock": "Massimo Clock CPU mostrato",
|
||||||
|
"Thermal Throttle": "Rallentamento Termico",
|
||||||
|
"Thermal Throttle Threshold": "Soglia Rallentamento Termico",
|
||||||
|
"Handheld TDP": "TPD Handheld",
|
||||||
|
"Handheld TDP Limit": "Limite TDP Handheld",
|
||||||
|
"Lite TDP Limit": "Limite TDP Lite",
|
||||||
|
"Enforce Board Limit": "Forza Limite di Potenza",
|
||||||
|
"Battery Charge Current": "Corrente di Ricarica",
|
||||||
|
"Display Refresh Rate Changing": "Cambio di Frequenza Display",
|
||||||
|
"Fix CPU Volt Bug": "Risolvi Bug CPU",
|
||||||
|
"[cfg] no enum format string": "[cfg] no enum format string",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "Salva Impotazioni KIP",
|
||||||
|
"RAM Settings": "Impostazioni RAM",
|
||||||
|
"CPU Settings": "Impostazioni CPU",
|
||||||
|
"GPU Settings": "Impostazioni GPU",
|
||||||
|
"Experimental": "Esperimentale",
|
||||||
|
"Charge Current Override": "Sovrascrivi Corrente di Ricarica",
|
||||||
|
"Disabled": "Disabilitato",
|
||||||
|
"HP Mode": "Modalità HP",
|
||||||
|
"EMC Max Clock": "Clock EMC Massimo",
|
||||||
|
"EMC VDD2 Voltage": "Voltaggio VDD2 EMC",
|
||||||
|
"EMC VDDQ Voltage": "Voltaggio VDDQ EMC",
|
||||||
|
"DVB Shift": "Shift DVB",
|
||||||
|
"Memory Timings": "Timing Memoria",
|
||||||
|
"Memory Latencies": "Latency Memoria",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "Aggiorna Timing RAM",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 Questa funzione è ESPERIMENRALE!",
|
||||||
|
"and should only be used for testing!": "e dovrebbe essere usata solo per testare!",
|
||||||
|
"Read Latency": "Latency Lettura",
|
||||||
|
"Write Latency": "Latency Scrittura",
|
||||||
|
"CPU UV": "UV CPU",
|
||||||
|
"CPU Unlock": "Sblocco CPU",
|
||||||
|
"CPU VMIN": "VMIN CPU",
|
||||||
|
"CPU Max Voltage": "Voltaggio Massimo CPU",
|
||||||
|
"CPU UV Table": "Tavola UV CPU",
|
||||||
|
"CPU Low UV": "UV Basso CPU",
|
||||||
|
"CPU High UV": "UV Alto CPU",
|
||||||
|
"CPU Max Clock": "Clock Massimo CPU",
|
||||||
|
"CPU Low VMIN": "VMIN Basso CPU",
|
||||||
|
"CPU High VMIN": "VMIN Alto CPU",
|
||||||
|
"GPU Undervolt Table": "Tavola Undervolt GPU",
|
||||||
|
"Calculate GPU Vmin": "Calcola VMIN GPU",
|
||||||
|
"GPU VMIN": "VMIN GPU",
|
||||||
|
"GPU VMAX": "VMAX GPU",
|
||||||
|
"GPU Volt Offset": "Offset Voltaggio GPU",
|
||||||
|
"GPU Custom Table": "Tavola GPU Custom",
|
||||||
|
"GPU Custom Table (mV)": "Tavola GPU Custom (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 Impostare Clock GPU oltre",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "1075MHz senza UV, 1152MHz su SLT o ",
|
||||||
|
"1228MHz on HiOPT can cause ": "1228MHz su HiOPT può causare ",
|
||||||
|
"permanent damage to your Switch!": "danni permanenti alla tua console!",
|
||||||
|
"Proceed at your own risk!": "Procedi al tuo rischio!",
|
||||||
|
"921MHz without UV and 960MHz on": "921MHz senza UV e 960MHz su",
|
||||||
|
"SLT or HiOPT can cause ": "SLT o HiOPT può causare ",
|
||||||
|
"Auto": "Auto",
|
||||||
|
"Sleep Mode": "Modalità Sleep",
|
||||||
|
"Stock": "Stock",
|
||||||
|
"Dev OC": "OC Sviluppo",
|
||||||
|
"Boost Mode": "Modalità Boost",
|
||||||
|
"Safe Max": "Massimo Sicuro",
|
||||||
|
"Unsafe Max": "Massimo Insicuro",
|
||||||
|
"Absolute Max": "Massimo Assoluto",
|
||||||
|
"Boost Mode & Safe Max": "Modalità Boost e Massimo Sicuro",
|
||||||
|
"Official Rating": "Rating Ufficiale",
|
||||||
|
"Default (Mariko)": "Default (Mariko)",
|
||||||
|
"Default (Erista)": "Default (Erista)",
|
||||||
|
"Rating": "Rating",
|
||||||
|
"Safe Max (Mariko)": "Max Sicuro (Mariko)",
|
||||||
|
"Safe Max (Erista)": "Max Sicuro (Erista)",
|
||||||
|
"Default": "Default",
|
||||||
|
"1581MHz Tbreak": "Tbreak 1581MHz",
|
||||||
|
"1683MHz Tbreak": "Tbreak 1683MHz",
|
||||||
|
"Extreme UV Table": "Tavola UV Estremo",
|
||||||
|
"No UV": "No UV",
|
||||||
|
"SLT Table": "Tavola SLT",
|
||||||
|
"HiOPT Table": "Tavola HiOPT",
|
||||||
|
"Power": "Potenza",
|
||||||
|
"Temp": "Temperatura",
|
||||||
|
"Voltage": "Voltaggio",
|
||||||
|
"TDP Threshold": "Soglia TDP",
|
||||||
|
"Lite TDP Threshold": "Soglia TDP Lite",
|
||||||
|
"Thermal Throttle Limit": "Limite Rallentamento Termico",
|
||||||
|
"1600BL": "BL1600",
|
||||||
|
"1866BL": "BL1866",
|
||||||
|
"2133BL": "BL2133",
|
||||||
|
"BAT": "BAT",
|
||||||
|
"FAN": "FAN",
|
||||||
|
"DISP": "DISP",
|
||||||
|
"Board": "Scheda",
|
||||||
|
"Skin": "Skin",
|
||||||
|
"Now": "Ora",
|
||||||
|
"Avg": "Med",
|
||||||
|
"App ID": "ID App",
|
||||||
|
"Profile": "Profilo",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "Memoria",
|
||||||
|
"Display": "Display",
|
||||||
|
"Governor": "Governor",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "Dock",
|
||||||
|
"Handheld": "Handheld",
|
||||||
|
"Charging": "In Carica",
|
||||||
|
"USB Charger": "Caricatore USB",
|
||||||
|
"PD Charger": "Caricatore PD",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ"
|
||||||
|
}
|
||||||
133
dist/config/horizon-oc/lang/lang/zh-cn.json
vendored
Normal file
133
dist/config/horizon-oc/lang/lang/zh-cn.json
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"Information about Translation": "This is a machine translation. If you find any errors, please report them on GitHub, or feel free to contribute!",
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "编辑应用配置",
|
||||||
|
"Advanced": "高级",
|
||||||
|
"Edit Global Profile": "编辑全局配置",
|
||||||
|
"Temporary Overrides": "临时覆盖",
|
||||||
|
"Temporary Overrides Reset": "临时覆盖 重置",
|
||||||
|
"Settings": "设置",
|
||||||
|
"Information": "信息",
|
||||||
|
"Enable": "启用",
|
||||||
|
"Uncapped Clocks": "解除频率上限",
|
||||||
|
"Override Boost Mode": "覆盖加速模式",
|
||||||
|
"CPU Max Display Clock": "CPU 最大显示频率",
|
||||||
|
"Thermal Throttle": "温度节流",
|
||||||
|
"Thermal Throttle Threshold": "温度节流阈值",
|
||||||
|
"Handheld TDP": "掌机模式 TDP",
|
||||||
|
"Handheld TDP Limit": "掌机模式 TDP 限制",
|
||||||
|
"Lite TDP Limit": "Lite TDP 限制",
|
||||||
|
"Enforce Board Limit": "强制主板限制",
|
||||||
|
"Battery Charge Current": "电池充电电流",
|
||||||
|
"Display Refresh Rate Changing": "显示刷新率变更",
|
||||||
|
"Fix CPU Volt Bug": "修复 CPU 电压错误",
|
||||||
|
"[cfg] no enum format string": "[cfg] 无枚举格式字符串",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "保存 KIP 设置",
|
||||||
|
"RAM Settings": "内存设置",
|
||||||
|
"CPU Settings": "CPU 设置",
|
||||||
|
"GPU Settings": "GPU 设置",
|
||||||
|
"Experimental": "实验性功能",
|
||||||
|
"Charge Current Override": "充电电流覆盖",
|
||||||
|
"Disabled": "禁用",
|
||||||
|
"HP Mode": "高性能模式",
|
||||||
|
"EMC Max Clock": "EMC 最大频率",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 电压",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ 电压",
|
||||||
|
"DVB Shift": "DVB 偏移",
|
||||||
|
"Memory Timings": "内存时序",
|
||||||
|
"Memory Latencies": "内存延迟",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "更新内存时序",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 此功能为实验性功能",
|
||||||
|
"and should only be used for testing!": "仅应用于测试!",
|
||||||
|
"Read Latency": "读取延迟",
|
||||||
|
"Write Latency": "写入延迟",
|
||||||
|
"CPU UV": "CPU 降压",
|
||||||
|
"CPU Unlock": "CPU 解锁",
|
||||||
|
"CPU VMIN": "CPU 最低电压",
|
||||||
|
"CPU Max Voltage": "CPU 最大电压",
|
||||||
|
"CPU UV Table": "CPU 降压表",
|
||||||
|
"CPU Low UV": "CPU 低频降压",
|
||||||
|
"CPU High UV": "CPU 高频降压",
|
||||||
|
"CPU Max Clock": "CPU 最大频率",
|
||||||
|
"CPU Low VMIN": "CPU 低频最低电压",
|
||||||
|
"CPU High VMIN": "CPU 高频最低电压",
|
||||||
|
"GPU Undervolt Table": "GPU 降压表",
|
||||||
|
"Calculate GPU Vmin": "计算 GPU 最低电压",
|
||||||
|
"GPU VMIN": "GPU 最低电压",
|
||||||
|
"GPU VMAX": "GPU 最大电压",
|
||||||
|
"GPU Volt Offset": "GPU 电压偏移",
|
||||||
|
"GPU Custom Table": "GPU 自定义表",
|
||||||
|
"GPU Custom Table (mV)": "GPU 自定义表 (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 将 GPU 频率设置超过",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "无降压时的 1075MHz、SLT 时的 1152MHz 或",
|
||||||
|
"1228MHz on HiOPT can cause ": "HiOPT 时的 1228MHz 可能会造成",
|
||||||
|
"permanent damage to your Switch!": "对您的 Switch 造成永久性损坏!",
|
||||||
|
"Proceed at your own risk!": "风险自负!",
|
||||||
|
"921MHz without UV and 960MHz on": "无降压时的 921MHz 和",
|
||||||
|
"SLT or HiOPT can cause ": "SLT 或 HiOPT 时的 960MHz 可能会造成",
|
||||||
|
"Auto": "自动",
|
||||||
|
"Sleep Mode": "休眠模式",
|
||||||
|
"Stock": "默认",
|
||||||
|
"Dev OC": "开发超频",
|
||||||
|
"Boost Mode": "加速模式",
|
||||||
|
"Safe Max": "安全最大值",
|
||||||
|
"Unsafe Max": "不安全最大值",
|
||||||
|
"Absolute Max": "绝对最大值",
|
||||||
|
"Boost Mode & Safe Max": "加速模式 & 安全最大值",
|
||||||
|
"Official Rating": "官方额定值",
|
||||||
|
"Default (Mariko)": "默认 (Mariko)",
|
||||||
|
"Default (Erista)": "默认 (Erista)",
|
||||||
|
"Rating": "额定值",
|
||||||
|
"Safe Max (Mariko)": "安全最大值 (Mariko)",
|
||||||
|
"Safe Max (Erista)": "安全最大值 (Erista)",
|
||||||
|
"Default": "默认",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "极限降压表",
|
||||||
|
"No UV": "不降压",
|
||||||
|
"SLT Table": "SLT 表",
|
||||||
|
"HiOPT Table": "HiOPT 表",
|
||||||
|
"Power": "功耗",
|
||||||
|
"Temp": "温度",
|
||||||
|
"Voltage": "电压",
|
||||||
|
"TDP Threshold": "TDP 阈值",
|
||||||
|
"Lite TDP Threshold": "Lite TDP 阈值",
|
||||||
|
"Thermal Throttle Limit": "温度节流限制",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "电池",
|
||||||
|
"FAN": "风扇",
|
||||||
|
"DISP": "显示",
|
||||||
|
"Board": "主板",
|
||||||
|
"Skin": "外壳",
|
||||||
|
"Now": "当前",
|
||||||
|
"Avg": "平均",
|
||||||
|
"App ID": "应用 ID",
|
||||||
|
"Profile": "配置",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "内存",
|
||||||
|
"Display": "显示",
|
||||||
|
"Governor": "调速器",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "底座模式",
|
||||||
|
"Handheld": "掌机模式",
|
||||||
|
"Charging": "充电中",
|
||||||
|
"USB Charger": "USB 充电器",
|
||||||
|
"PD Charger": "PD 充电器",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
132
dist/config/horizon-oc/lang/lang/zh-tw.json
vendored
Normal file
132
dist/config/horizon-oc/lang/lang/zh-tw.json
vendored
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "編輯應用配置",
|
||||||
|
"Advanced": "高級",
|
||||||
|
"Edit Global Profile": "編輯全局配置",
|
||||||
|
"Temporary Overrides": "臨時覆蓋",
|
||||||
|
"Temporary Overrides Reset": "臨時覆蓋 重設",
|
||||||
|
"Settings": "設置",
|
||||||
|
"Information": "資訊",
|
||||||
|
"Enable": "啟用",
|
||||||
|
"Uncapped Clocks": "解除頻率上限",
|
||||||
|
"Override Boost Mode": "覆蓋加速模式",
|
||||||
|
"CPU Max Display Clock": "CPU 最大顯示頻率",
|
||||||
|
"Thermal Throttle": "溫度節流",
|
||||||
|
"Thermal Throttle Threshold": "溫度節流閾值",
|
||||||
|
"Handheld TDP": "掌機模式 TDP",
|
||||||
|
"Handheld TDP Limit": "掌機模式 TDP 限制",
|
||||||
|
"Lite TDP Limit": "Lite TDP 限制",
|
||||||
|
"Enforce Board Limit": "強制主板限制",
|
||||||
|
"Battery Charge Current": "電池充電電流",
|
||||||
|
"Display Refresh Rate Changing": "顯示刷新率變更",
|
||||||
|
"Fix CPU Volt Bug": "修復 CPU 電壓錯誤",
|
||||||
|
"[cfg] no enum format string": "[cfg] 無枚舉格式字串",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "保存 KIP 設置",
|
||||||
|
"RAM Settings": "記憶體設定",
|
||||||
|
"CPU Settings": "CPU 設置",
|
||||||
|
"GPU Settings": "GPU 設置",
|
||||||
|
"Experimental": "實驗性功能",
|
||||||
|
"Charge Current Override": "充電電流覆蓋",
|
||||||
|
"Disabled": "禁用",
|
||||||
|
"HP Mode": "高性能模式",
|
||||||
|
"EMC Max Clock": "EMC 最大頻率",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 電壓",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ 電壓",
|
||||||
|
"DVB Shift": "DVB 偏移",
|
||||||
|
"Memory Timings": "記憶體時序",
|
||||||
|
"Memory Latencies": "記憶體延遲",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "更新記憶體時序",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 此功能為實驗性功能",
|
||||||
|
"and should only be used for testing!": "僅應用於測試!",
|
||||||
|
"Read Latency": "讀取延遲",
|
||||||
|
"Write Latency": "寫入延遲",
|
||||||
|
"CPU UV": "CPU 降壓",
|
||||||
|
"CPU Unlock": "CPU 解鎖",
|
||||||
|
"CPU VMIN": "CPU 最低電壓",
|
||||||
|
"CPU Max Voltage": "CPU 最大電壓",
|
||||||
|
"CPU UV Table": "CPU 降壓表",
|
||||||
|
"CPU Low UV": "CPU 低頻降壓",
|
||||||
|
"CPU High UV": "CPU 高頻降壓",
|
||||||
|
"CPU Max Clock": "CPU 最大頻率",
|
||||||
|
"CPU Low VMIN": "CPU 低頻最低電壓",
|
||||||
|
"CPU High VMIN": "CPU 高頻最低電壓",
|
||||||
|
"GPU Undervolt Table": "GPU 降壓表",
|
||||||
|
"Calculate GPU Vmin": "計算 GPU 最低電壓",
|
||||||
|
"GPU VMIN": "GPU 最低電壓",
|
||||||
|
"GPU VMAX": "GPU 最大電壓",
|
||||||
|
"GPU Volt Offset": "GPU 電壓偏移",
|
||||||
|
"GPU Custom Table": "GPU 自訂表",
|
||||||
|
"GPU Custom Table (mV)": "GPU 自訂表 (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 將 GPU 頻率設置超過",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "無降壓時的 1075MHz、SLT 時的 1152MHz 或",
|
||||||
|
"1228MHz on HiOPT can cause ": "HiOPT 時的 1228MHz 可能會造成",
|
||||||
|
"permanent damage to your Switch!": "對您的 Switch 造成永久性損壞!",
|
||||||
|
"Proceed at your own risk!": "風險自負!",
|
||||||
|
"921MHz without UV and 960MHz on": "無降壓時的 921MHz 和",
|
||||||
|
"SLT or HiOPT can cause ": "SLT 或 HiOPT 時的 960MHz 可能會造成",
|
||||||
|
"Auto": "自動",
|
||||||
|
"Sleep Mode": "休眠模式",
|
||||||
|
"Stock": "默認",
|
||||||
|
"Dev OC": "開發超頻",
|
||||||
|
"Boost Mode": "加速模式",
|
||||||
|
"Safe Max": "安全最大值",
|
||||||
|
"Unsafe Max": "不安全最大值",
|
||||||
|
"Absolute Max": "絕對最大值",
|
||||||
|
"Boost Mode & Safe Max": "加速模式 & 安全最大值",
|
||||||
|
"Official Rating": "官方額定值",
|
||||||
|
"Default (Mariko)": "默認 (Mariko)",
|
||||||
|
"Default (Erista)": "默認 (Erista)",
|
||||||
|
"Rating": "額定值",
|
||||||
|
"Safe Max (Mariko)": "安全最大值 (Mariko)",
|
||||||
|
"Safe Max (Erista)": "安全最大值 (Erista)",
|
||||||
|
"Default": "默認",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "極限降壓表",
|
||||||
|
"No UV": "不降壓",
|
||||||
|
"SLT Table": "SLT 表",
|
||||||
|
"HiOPT Table": "HiOPT 表",
|
||||||
|
"Power": "功耗",
|
||||||
|
"Temp": "溫度",
|
||||||
|
"Voltage": "電壓",
|
||||||
|
"TDP Threshold": "TDP 閾值",
|
||||||
|
"Lite TDP Threshold": "Lite TDP 閾值",
|
||||||
|
"Thermal Throttle Limit": "溫度節流限制",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "電池",
|
||||||
|
"FAN": "風扇",
|
||||||
|
"DISP": "顯示",
|
||||||
|
"Board": "主板",
|
||||||
|
"Skin": "外殼",
|
||||||
|
"Now": "當前",
|
||||||
|
"Avg": "平均",
|
||||||
|
"App ID": "應用 ID",
|
||||||
|
"Profile": "配置",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "記憶體",
|
||||||
|
"Display": "顯示",
|
||||||
|
"Governor": "調速器",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "底座模式",
|
||||||
|
"Handheld": "掌機模式",
|
||||||
|
"Charging": "充電中",
|
||||||
|
"USB Charger": "USB 充電器",
|
||||||
|
"PD Charger": "PD 充電器",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
133
dist/config/horizon-oc/lang/zh-cn.json
vendored
Normal file
133
dist/config/horizon-oc/lang/zh-cn.json
vendored
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
"Information about Translation": "This is a machine translation. If you find any errors, please report them on GitHub, or feel free to contribute!",
|
||||||
|
"Horizon OC Zeus": "Horizon OC Zeus",
|
||||||
|
"Edit App Profile": "编辑应用配置",
|
||||||
|
"Advanced": "高级",
|
||||||
|
"Edit Global Profile": "编辑全局配置",
|
||||||
|
"Temporary Overrides": "临时覆盖",
|
||||||
|
"Temporary Overrides Reset": "临时覆盖 重置",
|
||||||
|
"Settings": "设置",
|
||||||
|
"Information": "信息",
|
||||||
|
"Enable": "启用",
|
||||||
|
"Uncapped Clocks": "解除频率上限",
|
||||||
|
"Override Boost Mode": "覆盖加速模式",
|
||||||
|
"CPU Max Display Clock": "CPU 最大显示频率",
|
||||||
|
"Thermal Throttle": "温度节流",
|
||||||
|
"Thermal Throttle Threshold": "温度节流阈值",
|
||||||
|
"Handheld TDP": "掌机模式 TDP",
|
||||||
|
"Handheld TDP Limit": "掌机模式 TDP 限制",
|
||||||
|
"Lite TDP Limit": "Lite TDP 限制",
|
||||||
|
"Enforce Board Limit": "强制主板限制",
|
||||||
|
"Battery Charge Current": "电池充电电流",
|
||||||
|
"Display Refresh Rate Changing": "显示刷新率变更",
|
||||||
|
"Fix CPU Volt Bug": "修复 CPU 电压错误",
|
||||||
|
"[cfg] no enum format string": "[cfg] 无枚举格式字符串",
|
||||||
|
"KIP": "KIP",
|
||||||
|
"Save KIP Settings": "保存 KIP 设置",
|
||||||
|
"RAM Settings": "内存设置",
|
||||||
|
"CPU Settings": "CPU 设置",
|
||||||
|
"GPU Settings": "GPU 设置",
|
||||||
|
"Experimental": "实验性功能",
|
||||||
|
"Charge Current Override": "充电电流覆盖",
|
||||||
|
"Disabled": "禁用",
|
||||||
|
"HP Mode": "高性能模式",
|
||||||
|
"EMC Max Clock": "EMC 最大频率",
|
||||||
|
"EMC VDD2 Voltage": "EMC VDD2 电压",
|
||||||
|
"EMC VDDQ Voltage": "EMC VDDQ 电压",
|
||||||
|
"DVB Shift": "DVB 偏移",
|
||||||
|
"Memory Timings": "内存时序",
|
||||||
|
"Memory Latencies": "内存延迟",
|
||||||
|
"t1 tRCD": "t1 tRCD",
|
||||||
|
"t2 tRP": "t2 tRP",
|
||||||
|
"t3 tRAS": "t3 tRAS",
|
||||||
|
"t4 tRRD": "t4 tRRD",
|
||||||
|
"t5 tRFC": "t5 tRFC",
|
||||||
|
"t6 tRTW": "t6 tRTW",
|
||||||
|
"t7 tWTR": "t7 tWTR",
|
||||||
|
"t8 tREFI": "t8 tREFI",
|
||||||
|
"Update RAM Timings": "更新内存时序",
|
||||||
|
"\uE150 This feature is EXPERIMENTAL": "\uE150 此功能为实验性功能",
|
||||||
|
"and should only be used for testing!": "仅应用于测试!",
|
||||||
|
"Read Latency": "读取延迟",
|
||||||
|
"Write Latency": "写入延迟",
|
||||||
|
"CPU UV": "CPU 降压",
|
||||||
|
"CPU Unlock": "CPU 解锁",
|
||||||
|
"CPU VMIN": "CPU 最低电压",
|
||||||
|
"CPU Max Voltage": "CPU 最大电压",
|
||||||
|
"CPU UV Table": "CPU 降压表",
|
||||||
|
"CPU Low UV": "CPU 低频降压",
|
||||||
|
"CPU High UV": "CPU 高频降压",
|
||||||
|
"CPU Max Clock": "CPU 最大频率",
|
||||||
|
"CPU Low VMIN": "CPU 低频最低电压",
|
||||||
|
"CPU High VMIN": "CPU 高频最低电压",
|
||||||
|
"GPU Undervolt Table": "GPU 降压表",
|
||||||
|
"Calculate GPU Vmin": "计算 GPU 最低电压",
|
||||||
|
"GPU VMIN": "GPU 最低电压",
|
||||||
|
"GPU VMAX": "GPU 最大电压",
|
||||||
|
"GPU Volt Offset": "GPU 电压偏移",
|
||||||
|
"GPU Custom Table": "GPU 自定义表",
|
||||||
|
"GPU Custom Table (mV)": "GPU 自定义表 (mV)",
|
||||||
|
"\uE150 Setting GPU Clocks past": "\uE150 将 GPU 频率设置超过",
|
||||||
|
"1075MHz without UV, 1152MHz on SLT or ": "无降压时的 1075MHz、SLT 时的 1152MHz 或",
|
||||||
|
"1228MHz on HiOPT can cause ": "HiOPT 时的 1228MHz 可能会造成",
|
||||||
|
"permanent damage to your Switch!": "对您的 Switch 造成永久性损坏!",
|
||||||
|
"Proceed at your own risk!": "风险自负!",
|
||||||
|
"921MHz without UV and 960MHz on": "无降压时的 921MHz 和",
|
||||||
|
"SLT or HiOPT can cause ": "SLT 或 HiOPT 时的 960MHz 可能会造成",
|
||||||
|
"Auto": "自动",
|
||||||
|
"Sleep Mode": "休眠模式",
|
||||||
|
"Stock": "默认",
|
||||||
|
"Dev OC": "开发超频",
|
||||||
|
"Boost Mode": "加速模式",
|
||||||
|
"Safe Max": "安全最大值",
|
||||||
|
"Unsafe Max": "不安全最大值",
|
||||||
|
"Absolute Max": "绝对最大值",
|
||||||
|
"Boost Mode & Safe Max": "加速模式 & 安全最大值",
|
||||||
|
"Official Rating": "官方额定值",
|
||||||
|
"Default (Mariko)": "默认 (Mariko)",
|
||||||
|
"Default (Erista)": "默认 (Erista)",
|
||||||
|
"Rating": "额定值",
|
||||||
|
"Safe Max (Mariko)": "安全最大值 (Mariko)",
|
||||||
|
"Safe Max (Erista)": "安全最大值 (Erista)",
|
||||||
|
"Default": "默认",
|
||||||
|
"1581MHz Tbreak": "1581MHz Tbreak",
|
||||||
|
"1683MHz Tbreak": "1683MHz Tbreak",
|
||||||
|
"Extreme UV Table": "极限降压表",
|
||||||
|
"No UV": "不降压",
|
||||||
|
"SLT Table": "SLT 表",
|
||||||
|
"HiOPT Table": "HiOPT 表",
|
||||||
|
"Power": "功耗",
|
||||||
|
"Temp": "温度",
|
||||||
|
"Voltage": "电压",
|
||||||
|
"TDP Threshold": "TDP 阈值",
|
||||||
|
"Lite TDP Threshold": "Lite TDP 阈值",
|
||||||
|
"Thermal Throttle Limit": "温度节流限制",
|
||||||
|
"1600BL": "1600BL",
|
||||||
|
"1866BL": "1866BL",
|
||||||
|
"2133BL": "2133BL",
|
||||||
|
"BAT": "电池",
|
||||||
|
"FAN": "风扇",
|
||||||
|
"DISP": "显示",
|
||||||
|
"Board": "主板",
|
||||||
|
"Skin": "外壳",
|
||||||
|
"Now": "当前",
|
||||||
|
"Avg": "平均",
|
||||||
|
"App ID": "应用 ID",
|
||||||
|
"Profile": "配置",
|
||||||
|
"CPU": "CPU",
|
||||||
|
"GPU": "GPU",
|
||||||
|
"Memory": "内存",
|
||||||
|
"Display": "显示",
|
||||||
|
"Governor": "调速器",
|
||||||
|
"SOC": "SOC",
|
||||||
|
"PCB": "PCB",
|
||||||
|
"PMIC": "PMIC",
|
||||||
|
"Docked": "底座模式",
|
||||||
|
"Handheld": "掌机模式",
|
||||||
|
"Charging": "充电中",
|
||||||
|
"USB Charger": "USB 充电器",
|
||||||
|
"PD Charger": "PD 充电器",
|
||||||
|
"VDD2": "VDD2",
|
||||||
|
"VDDQ": "VDDQ",
|
||||||
|
"GPU DVFS": "GPU DVFS"
|
||||||
|
}
|
||||||
BIN
dist/exosphere.bin
vendored
BIN
dist/exosphere.bin
vendored
Binary file not shown.
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
BIN
dist/switch/.overlays/Horizon-OC-Monitor.ovl
vendored
Binary file not shown.
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
BIN
dist/switch/.overlays/horizon-oc-overlay.ovl
vendored
Binary file not shown.
@@ -1,140 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Horizon OC Configurator</title>
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
background: linear-gradient(160deg, #1a1a1a 0%, #2a2a2a 50%, #3a3a3a 100%);
|
|
||||||
color: white;
|
|
||||||
font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glass {
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border-radius: 20px;
|
|
||||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glass:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.12);
|
|
||||||
transform: translateY(-3px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-glass {
|
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
||||||
color: white;
|
|
||||||
padding: 0.8rem 1.6rem;
|
|
||||||
border-radius: 9999px;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.3s;
|
|
||||||
display: inline-block;
|
|
||||||
text-decoration: none;
|
|
||||||
margin: 0.25rem 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-glass:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.25);
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="number"], input[type="file"] {
|
|
||||||
padding: 0.5rem 0.8rem;
|
|
||||||
border-radius: 12px;
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
||||||
background: rgba(255, 255, 255, 0.1);
|
|
||||||
color: white;
|
|
||||||
font-weight: 500;
|
|
||||||
outline: none;
|
|
||||||
transition: all 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="number"]:focus, input[type="file"]:focus {
|
|
||||||
border-color: #b8f3ff;
|
|
||||||
background: rgba(255, 255, 255, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
margin-right: 0.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
section {
|
|
||||||
margin-top: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
text-align: center;
|
|
||||||
color: #ccc;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
margin-top: 4rem;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- Navigation / Go Back -->
|
|
||||||
<nav class="flex justify-start p-6">
|
|
||||||
<a href="index.html" class="button-glass">← Go Back to Main Page</a>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Configurator -->
|
|
||||||
<section id="config" class="max-w-4xl mx-auto px-6 py-16 glass mt-6" data-aos="fade-up">
|
|
||||||
<h2 class="text-3xl font-bold mb-4 text-center">Configurator</h2>
|
|
||||||
<p class="text-gray-400 text-center mb-8">Configure frequencies and voltages to suit your hardware and preferences.</p>
|
|
||||||
|
|
||||||
<form class="space-y-6 text-center">
|
|
||||||
<!-- Unit selection buttons -->
|
|
||||||
<div class="flex justify-center gap-2">
|
|
||||||
<button type="button" class="button-glass">All</button>
|
|
||||||
<button type="button" class="button-glass">Erista</button>
|
|
||||||
<button type="button" class="button-glass">Mariko</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- File upload -->
|
|
||||||
<div class="flex flex-col items-center">
|
|
||||||
<input type="file" id="file">
|
|
||||||
<p class="text-sm text-gray-400 mt-2">Upload loader.kip here</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Example numeric inputs -->
|
|
||||||
<div class="flex flex-wrap justify-center gap-4 mt-4">
|
|
||||||
<div>
|
|
||||||
<label for="commonEmcMemVolt">EMC Voltage:</label>
|
|
||||||
<input type="number" id="commonEmcMemVolt" min="0" max="1250000" step="12500">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="commonCpuVolt">CPU Voltage:</label>
|
|
||||||
<input type="number" id="commonCpuVolt" min="0" max="1250000" step="12500">
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label for="commonGpuVolt">GPU Voltage:</label>
|
|
||||||
<input type="number" id="commonGpuVolt" min="0" max="1250000" step="12500">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer>
|
|
||||||
Built with ❤️. All trademarks and logos are the property of their respective owners.
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
|
||||||
<script>AOS.init({ once: true, duration: 700 });</script>
|
|
||||||
<script src="configurator.js"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,683 +0,0 @@
|
|||||||
/* configurator.js
|
|
||||||
Clean, readable reconstruction of the original minified configurator
|
|
||||||
- Keeps original behavior (tables, parsing, localStorage, GitHub release fetching)
|
|
||||||
- Uses modern async/await and DOMContentLoaded guarding
|
|
||||||
*/
|
|
||||||
|
|
||||||
const CUST_REV_ADV = 11;
|
|
||||||
|
|
||||||
const CustPlatform = Object.freeze({
|
|
||||||
Undefined: 0,
|
|
||||||
Erista: 1,
|
|
||||||
Mariko: 2,
|
|
||||||
All: 3
|
|
||||||
});
|
|
||||||
|
|
||||||
class CustEntry {
|
|
||||||
constructor(id, name, platform, size, desc = [], defval = 0, range = [0, 1e6], step = 1, zeroable = true) {
|
|
||||||
this.id = id;
|
|
||||||
this.name = name;
|
|
||||||
this.platform = platform;
|
|
||||||
this.size = size;
|
|
||||||
this.desc = desc;
|
|
||||||
this.defval = defval;
|
|
||||||
this.step = step;
|
|
||||||
this.zeroable = zeroable;
|
|
||||||
this.min = range[0];
|
|
||||||
this.max = range[1];
|
|
||||||
this.value = this.defval;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate() {
|
|
||||||
const err = new ErrorToolTip(this.id).clear();
|
|
||||||
if (Number.isNaN(this.value) || this.value === undefined) {
|
|
||||||
err.setMsg("Invalid value: Not a number").show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!this.zeroable && this.value === 0) {
|
|
||||||
err.setMsg("Zero is not allowed for this entry").show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (this.value < this.min || this.value > this.max) {
|
|
||||||
err.setMsg(`Expected range: [${this.min}, ${this.max}], got ${this.value}.`).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((this.value % this.step) !== 0) {
|
|
||||||
err.setMsg(`${this.value} % ${this.step} ≠ 0`).show();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
getInputElement() {
|
|
||||||
return document.getElementById(this.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateValueFromElement() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
this.value = Number(el?.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
isAvailableFor(platform) {
|
|
||||||
return platform === CustPlatform.Undefined || this.platform === platform || this.platform === CustPlatform.All;
|
|
||||||
}
|
|
||||||
|
|
||||||
createElement(containerId = "config-list-basic") {
|
|
||||||
let input = this.getInputElement();
|
|
||||||
if (!input) {
|
|
||||||
const wrapper = document.createElement("div");
|
|
||||||
wrapper.classList.add("grid", "cust-element", "mb-3");
|
|
||||||
|
|
||||||
input = document.createElement("input");
|
|
||||||
input.min = String(this.zeroable ? 0 : this.min);
|
|
||||||
input.max = String(this.max);
|
|
||||||
input.id = this.id;
|
|
||||||
input.type = "number";
|
|
||||||
input.step = String(this.step);
|
|
||||||
input.classList.add("text-black", "w-36");
|
|
||||||
|
|
||||||
const label = document.createElement("label");
|
|
||||||
label.setAttribute("for", this.id);
|
|
||||||
label.innerHTML = `<strong>${this.name}</strong>`;
|
|
||||||
label.classList.add("block", "mb-1");
|
|
||||||
|
|
||||||
const desc = document.createElement("blockquote");
|
|
||||||
desc.innerHTML = "<ul>" + (this.desc || []).map(d => `<li>${d}</li>`).join("") + "</ul>";
|
|
||||||
desc.setAttribute("for", this.id);
|
|
||||||
desc.classList.add("text-sm", "text-gray-300");
|
|
||||||
|
|
||||||
wrapper.appendChild(label);
|
|
||||||
wrapper.appendChild(input);
|
|
||||||
wrapper.appendChild(desc);
|
|
||||||
|
|
||||||
const container = document.getElementById(containerId);
|
|
||||||
if (container) container.appendChild(wrapper);
|
|
||||||
new ErrorToolTip(this.id).addChangeListener();
|
|
||||||
}
|
|
||||||
input.value = String(this.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
setElementValue() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
if (el) el.value = String(this.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
setElementDefaultValue() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
if (el) el.value = String(this.defval);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeElement() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
if (el && el.parentElement && el.parentElement.parentElement) el.parentElement.parentElement.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
showElement() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
if (el && el.parentElement && el.parentElement.parentElement) el.parentElement.parentElement.style.removeProperty("display");
|
|
||||||
}
|
|
||||||
|
|
||||||
hideElement() {
|
|
||||||
const el = this.getInputElement();
|
|
||||||
if (el && el.parentElement && el.parentElement.parentElement) el.parentElement.parentElement.style.setProperty("display", "none");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class AdvEntry extends CustEntry {
|
|
||||||
createElement() {
|
|
||||||
super.createElement("config-list-advanced");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class GpuEntry extends CustEntry {
|
|
||||||
constructor(id, name, platform = CustPlatform.Mariko, size = 4, desc = ["range: 610 ≤ x ≤ 1000"], defval = 610, range = [610, 1000], step = 5, zeroable = false) {
|
|
||||||
super(id, name, platform, size, desc, defval, range, step, zeroable);
|
|
||||||
}
|
|
||||||
|
|
||||||
createElement() {
|
|
||||||
super.createElement("config-list-gpu");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === Tables (reconstructed from original) ===
|
|
||||||
Note: Numeric defaults preserved where feasible.
|
|
||||||
*/
|
|
||||||
const CustTable = [
|
|
||||||
new CustEntry("mtcConf", "DRAM Timing", CustPlatform.All, 4,
|
|
||||||
[
|
|
||||||
"<b>0</b>: AUTO_ADJ_ALL: Auto adjust mtc table with LPDDR4 3733 Mbps specs, 8Gb density. Change timing with Advanced Config (Default)",
|
|
||||||
"<b>1</b>: CUSTOM_ADJ_ALL: Adjust only non-zero preset timings in Advanced Config",
|
|
||||||
"<b>2</b>: NO_ADJ_ALL: Use 1600 mtc table without adjusting (Timing becomes tighter if you raise dram clock)."
|
|
||||||
], 0, [0, 2], 1),
|
|
||||||
new CustEntry("commonCpuBoostClock", "Boost Clock in kHz", CustPlatform.All, 4,
|
|
||||||
["System default: 1785000", "Boost clock will be applied when applications request Boost Mode via performance configuration."],
|
|
||||||
1785000, [1020000, 3000000], 1, false),
|
|
||||||
new CustEntry("commonEmcMemVolt", "EMC Vdd2 Voltage in uV", CustPlatform.All, 4,
|
|
||||||
["Acceptable range: 1100000 ≤ x ≤ 1250000, and it should be divided evenly by 12500.", "Erista Default: 1125000", "Mariko Default: 1100000", "Official lpddr4(x) range: 1060mV~1175mV (1100mV nominal)", "OCS need high voltage unlike l4t because of not scaling mtc table well. However it is recommended to stay within official limits", "Not enabled by default"],
|
|
||||||
0, [1100000, 1250000], 12500),
|
|
||||||
new CustEntry("eristaCpuMaxVolt", "Erista CPU Max Voltage in mV", CustPlatform.Erista, 4,
|
|
||||||
["Acceptable range: 1120 ≤ x ≤ 1300", "L4T Default: 1235"], 1235, [1120, 1300], 1),
|
|
||||||
new CustEntry("eristaEmcMaxClock", "Erista RAM Max Clock in kHz", CustPlatform.Erista, 4,
|
|
||||||
["Values should be ≥ 1600000, and divided evenly by 3200.", "Recommended Clocks: 1862400, 2131200 (JEDEC)", "<b>WARNING:</b> RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM"], 1862400, [1600000, 2131200], 3200),
|
|
||||||
new CustEntry("marikoCpuMaxVolt", "Mariko CPU Max Voltage in mV", CustPlatform.Mariko, 4,
|
|
||||||
["System default: 1120", "Acceptable range: 1120 ≤ x ≤ 1300", "Changing this value affects cpu voltage calculation"], 1235, [1120, 1300], 5),
|
|
||||||
new CustEntry("marikoEmcMaxClock", "Mariko RAM Max Clock in kHz", CustPlatform.Mariko, 4,
|
|
||||||
["Values should be ≥ 1600000, and divided evenly by 3200.", "Recommended Clocks: 1862400, 2131200, 2400000 (JEDEC)", "Some clocks above 2400Mhz might not boot, because OCS doesn't scale table very well", "<b>WARNING:</b> RAM overclock could be UNSTABLE if timing parameters are not suitable for your DRAM."],
|
|
||||||
1996800, [1600000, 2502400], 3200),
|
|
||||||
new CustEntry("marikoEmcVddqVolt", "EMC Vddq (Mariko Only) Voltage in uV", CustPlatform.Mariko, 4,
|
|
||||||
["Acceptable range: 550000 ≤ x ≤ 650000", "Value should be divided evenly by 5000", "Default: 600000", "Official lpddr4(x) range: 570mV~650mV (600mV nominal)", "Not enabled by default."],
|
|
||||||
0, [550000, 650000], 5000),
|
|
||||||
new CustEntry("marikoCpuUV", "Enable Mariko CPU Undervolt", CustPlatform.Mariko, 4,
|
|
||||||
["Reduce CPU power draw", "<b>0</b> : Default Table", "<b>1</b> : Undervolt Level 1 (SLT - CPU speedo < 1650)", "<b>2</b> : Undervolt Level 1 (SLT - CPU speedo >= 1650)"], 0, [0, 2], 1),
|
|
||||||
new CustEntry("marikoGpuUV", "Enable Mariko GPU Undervolt", CustPlatform.Mariko, 4,
|
|
||||||
["Reduce GPU power draw", "Your GPU might not withstand undervolt, and can hang your console, or crash games", "Undervolting too much will drop GPU performance even if it seems stable", "GPU voltages are dynamic and will change with temperature and gpu speedo", "<b>0</b> : Default Table", "<b>1</b> : Undervolt Level 1 (SLT: Aggressive)", "<b>2</b> : Undervolt Level 2 (HiOPT: Drastic)", "<b>3</b> : Custom static GPU Voltage Table (Use Gpu Configuration below)"],
|
|
||||||
0, [0, 3], 1),
|
|
||||||
new CustEntry("commonGpuVoltOffset", "GPU Volt Offset", CustPlatform.All, 4,
|
|
||||||
["Negative Voltage offset value for gpu dynamic voltage calculation", "For example, value of 10 will decrease 10mV gpu volt from all frequencies", "Default gpu vmin: Erista - 812.5mV / Mariko - 610mV", "Acceptable range: 0 ~ 100"],
|
|
||||||
0, [0, 100], 1)
|
|
||||||
];
|
|
||||||
|
|
||||||
const AdvTable = [
|
|
||||||
new AdvEntry("marikoEmcDvbShift", "Step up Mariko EMC DVB Table", CustPlatform.Mariko, 4,
|
|
||||||
["Each number adds 25mV to SoC voltage", "Helps with stability at higher memory clock", "Acceptable range : 0~9"], 0, [0, 9], 1),
|
|
||||||
new AdvEntry("ramTimingPresetOne", "Primary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["<b>WARNING</b>: Unstable timings can corrupt your nand", "Select Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tRCD - tRP - tRAS (tRC = tRP + tRAS)", "<b>0</b> : Do Not Adjust (2400Mhz: 12 - 12 - 28) (CUST_ADJ only)", "<b>1</b> : 18 - 18 - 42 (Default timing)", "<b>2</b> : 17 - 17 - 39", "<b>3</b> : 16 - 16 - 36", "<b>4</b> : 15 - 15 - 34", "<b>5</b> : 14 - 14 - 32", "<b>6</b> : 13 - 13 - 30"],
|
|
||||||
1, [0, 6], 1),
|
|
||||||
new AdvEntry("ramTimingPresetTwo", "Secondary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tRRD - tFAW", "<b>0</b> : Do Not Adjust (2400Mhz: 6.6 - 26.6) (CUST_ADJ only)", "<b>1</b> : 10 - 40 (Default timing) (3733 specs)", "<b>2</b> : 7.5 - 30 (4266 specs)", "<b>3</b> : 6 - 24", "<b>4</b> : 4 - 16", "<b>5</b> : 3 - 12"],
|
|
||||||
1, [0, 5], 1),
|
|
||||||
new AdvEntry("ramTimingPresetThree", "Secondary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tWR - tRTP", "<b>0</b> : Do Not Adjust (2400Mhz: ?? - 5) (CUST_ADJ only)", "<b>1</b> : 18 - 7.5 (Default timing)", "<b>2</b> : 15 - 7.5", "<b>3</b> : 15 - 6", "<b>4</b> : 12 - 6", "<b>5</b> : 12 - 4", "<b>6</b> : 8 - 4"],
|
|
||||||
1, [0, 6], 1),
|
|
||||||
new AdvEntry("ramTimingPresetFour", "Secondary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tRFC", "<b>0</b> : Do Not Adjust (2400Mhz: 93.3) (CUST_ADJ only)", "<b>1</b> : 140 (Default timing)", "<b>2</b> : 120", "<b>3</b> : 100", "<b>4</b> : 80", "<b>5</b> : 70", "<b>6</b> : 60"],
|
|
||||||
1, [0, 6], 1),
|
|
||||||
new AdvEntry("ramTimingPresetFive", "Secondary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tWTR", "<b>0</b> : Do Not Adjust (2400Mhz: ??) (CUST_ADJ only)", "<b>1</b> : 10 (Default timing)", "<b>2</b> : 8", "<b>3</b> : 6", "<b>4</b> : 4", "<b>5</b> : 2", "<b>6</b> : 1"],
|
|
||||||
1, [0, 6], 1),
|
|
||||||
new AdvEntry("ramTimingPresetSix", "Tertiary RAM Timing Preset", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Tertiary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ", "Values are : tREFpb", "<b>0</b> : Do Not Adjust (2400Mhz: 325) (CUST_ADJ only)", "<b>1</b> : 488 (Default timing)", "<b>2</b> : 976", "<b>3</b> : 1952", "<b>4</b> : 3256", "<b>5</b> : MAX"],
|
|
||||||
1, [0, 5], 1),
|
|
||||||
new AdvEntry("ramTimingPresetSeven", "Latency Decrement", CustPlatform.Mariko, 4,
|
|
||||||
["WARNING: Unstable timings can corrupt your nand", "Latency decrement for both AUTO_ADJ and CUSTOM_ADJ", "This preset decreases Write/Read related delays. Values are Write - Read", "<b>0</b> : 0 - 0, Do Not Adjust for CUST_ADJ", "<b>1</b> : '-2' - '-4'", "<b>2</b> : '-4' - '-8'", "<b>3</b> : '-6' - '-12'", "<b>4</b> : '-8' - '-16'", "<b>5</b> : '-10' - '-20'", "<b>6</b> : '-12' - '-24'"],
|
|
||||||
0, [0, 6], 1)
|
|
||||||
];
|
|
||||||
|
|
||||||
const GpuTable = [
|
|
||||||
new GpuEntry("0", "76.8"),
|
|
||||||
new GpuEntry("1", "153.6"),
|
|
||||||
new GpuEntry("2", "230.4"),
|
|
||||||
new GpuEntry("3", "307.2"),
|
|
||||||
new GpuEntry("4", "384.0"),
|
|
||||||
new GpuEntry("5", "460.8"),
|
|
||||||
new GpuEntry("6", "537.6"),
|
|
||||||
new GpuEntry("7", "614.4"),
|
|
||||||
new GpuEntry("8", "691.2"),
|
|
||||||
new GpuEntry("9", "768.0"),
|
|
||||||
new GpuEntry("10", "844.8"),
|
|
||||||
new GpuEntry("11", "921.6"),
|
|
||||||
new GpuEntry("12", "998.4"),
|
|
||||||
new GpuEntry("13", "1075.2"),
|
|
||||||
new GpuEntry("14", "1152.0"),
|
|
||||||
new GpuEntry("15", "1228.8"),
|
|
||||||
new GpuEntry("16", "1267.2")
|
|
||||||
];
|
|
||||||
|
|
||||||
/* ===== ErrorToolTip ===== */
|
|
||||||
class ErrorToolTip {
|
|
||||||
constructor(id, msg) {
|
|
||||||
this.id = id;
|
|
||||||
this.msg = msg;
|
|
||||||
this.element = document.getElementById(id);
|
|
||||||
if (msg) this.setMsg(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
setMsg(msg) {
|
|
||||||
this.msg = String(msg);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
show() {
|
|
||||||
if (this.element) this.element.setAttribute("aria-invalid", "true");
|
|
||||||
if (this.msg && this.element) {
|
|
||||||
this.element.setAttribute("title", this.msg);
|
|
||||||
if (this.element.parentElement) {
|
|
||||||
this.element.parentElement.setAttribute("data-tooltip", this.msg);
|
|
||||||
this.element.parentElement.setAttribute("data-placement", "top");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
if (this.element) this.element.removeAttribute("aria-invalid");
|
|
||||||
if (this.element) this.element.removeAttribute("title");
|
|
||||||
if (this.element && this.element.parentElement) {
|
|
||||||
this.element.parentElement.removeAttribute("data-tooltip");
|
|
||||||
this.element.parentElement.removeAttribute("data-placement");
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
addChangeListener() {
|
|
||||||
if (!this.element) return;
|
|
||||||
this.element.addEventListener("change", () => {
|
|
||||||
const tableEntry = CustTable.find(e => e.id === this.id);
|
|
||||||
if (tableEntry) {
|
|
||||||
tableEntry.value = Number(this.element.value);
|
|
||||||
tableEntry.validate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===== CustStorage ===== */
|
|
||||||
class CustStorage {
|
|
||||||
constructor() {
|
|
||||||
this.storage = {};
|
|
||||||
this.key = "last_saved";
|
|
||||||
}
|
|
||||||
|
|
||||||
updateFromTable() {
|
|
||||||
// helper to update and validate each entry
|
|
||||||
const updateOne = (entry) => {
|
|
||||||
entry.updateValueFromElement();
|
|
||||||
if (!entry.validate()) {
|
|
||||||
const el = entry.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Invalid ${entry.name}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CustTable.forEach(updateOne);
|
|
||||||
AdvTable.forEach(updateOne);
|
|
||||||
GpuTable.forEach(updateOne);
|
|
||||||
|
|
||||||
this.storage = {};
|
|
||||||
let t = Object.fromEntries(CustTable.map(e => [e.id, e.value]));
|
|
||||||
Object.keys(t).forEach(k => (this.storage[k] = t[k]));
|
|
||||||
t = Object.fromEntries(AdvTable.map(e => [e.id, e.value]));
|
|
||||||
Object.keys(t).forEach(k => (this.storage[k] = t[k]));
|
|
||||||
// GPU table could be included too if desired
|
|
||||||
}
|
|
||||||
|
|
||||||
setTable() {
|
|
||||||
const keys = Object.keys(this.storage);
|
|
||||||
keys.forEach(k => {
|
|
||||||
const c = CustTable.find(e => e.id === k);
|
|
||||||
if (c) c.value = this.storage[k];
|
|
||||||
});
|
|
||||||
keys.forEach(k => {
|
|
||||||
const a = AdvTable.find(e => e.id === k);
|
|
||||||
if (a) a.value = this.storage[k];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Set defaults for entries not found
|
|
||||||
CustTable.filter(e => !keys.includes(e.id)).forEach(e => e.value = e.defval);
|
|
||||||
AdvTable.filter(e => !keys.includes(e.id)).forEach(e => e.value = e.defval);
|
|
||||||
|
|
||||||
// Validate and set element values
|
|
||||||
CustTable.forEach(e => {
|
|
||||||
if (!e.validate()) {
|
|
||||||
const el = e.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Invalid ${e.name}`);
|
|
||||||
}
|
|
||||||
e.setElementValue();
|
|
||||||
});
|
|
||||||
AdvTable.forEach(e => {
|
|
||||||
if (!e.validate()) {
|
|
||||||
const el = e.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Invalid ${e.name}`);
|
|
||||||
}
|
|
||||||
e.setElementValue();
|
|
||||||
});
|
|
||||||
GpuTable.forEach(e => {
|
|
||||||
if (!e.validate()) {
|
|
||||||
const el = e.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Invalid ${e.name}`);
|
|
||||||
}
|
|
||||||
e.setElementValue();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
localStorage.setItem(this.key, JSON.stringify(this.storage));
|
|
||||||
}
|
|
||||||
|
|
||||||
load() {
|
|
||||||
const raw = localStorage.getItem(this.key);
|
|
||||||
if (!raw) return null;
|
|
||||||
const parsed = JSON.parse(raw);
|
|
||||||
|
|
||||||
// Filter unknown keys and warn
|
|
||||||
const custIds = CustTable.map(e => e.id);
|
|
||||||
const ignoredCust = Object.keys(parsed).filter(k => !custIds.includes(k));
|
|
||||||
if (ignoredCust.length) console.log("Ignored (cust):", ignoredCust);
|
|
||||||
Object.keys(parsed).filter(k => custIds.includes(k)).forEach(k => (this.storage[k] = parsed[k]));
|
|
||||||
|
|
||||||
const advIds = AdvTable.map(e => e.id);
|
|
||||||
const ignoredAdv = Object.keys(parsed).filter(k => !advIds.includes(k));
|
|
||||||
if (ignoredAdv.length) console.log("Ignored (adv):", ignoredAdv);
|
|
||||||
Object.keys(parsed).filter(k => advIds.includes(k)).forEach(k => (this.storage[k] = parsed[k]));
|
|
||||||
|
|
||||||
return this.storage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===== Cust (binary parser/patcher) =====
|
|
||||||
This class follows the original structure:
|
|
||||||
- find magic in buffer using magicLen, mapper sizes
|
|
||||||
- parse data using size-mapped getters/setters
|
|
||||||
- produce Blob for download (patched buffer)
|
|
||||||
*/
|
|
||||||
class Cust {
|
|
||||||
constructor() {
|
|
||||||
this.storage = new CustStorage();
|
|
||||||
this.magic = 1414747459; // original magic
|
|
||||||
this.magicLen = 4;
|
|
||||||
this.mapper = {
|
|
||||||
2: { get: (offset) => this.view.getUint16(offset, true), set: (offset, v) => this.view.setUint16(offset, v, true) },
|
|
||||||
4: { get: (offset) => this.view.getUint32(offset, true), set: (offset, v) => this.view.setUint32(offset, v, true) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
findMagicOffset() {
|
|
||||||
this.view = new DataView(this.buffer);
|
|
||||||
for (let offset = 0; offset < this.view.byteLength; offset += this.magicLen) {
|
|
||||||
if (this.mapper[this.magicLen].get(offset) === this.magic) {
|
|
||||||
this.beginOffset = offset;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new Error("Invalid loader.kip file (magic not found)");
|
|
||||||
}
|
|
||||||
|
|
||||||
save() {
|
|
||||||
// update from table (validate & populate storage)
|
|
||||||
this.storage.updateFromTable();
|
|
||||||
|
|
||||||
const writeOne = (entry) => {
|
|
||||||
if (!entry.offset && entry.offset !== 0) {
|
|
||||||
// If offset is missing in the UI, it's an error in mapping
|
|
||||||
const el = entry.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Failed to get offset for ${entry.name}`);
|
|
||||||
}
|
|
||||||
const mapper = this.mapper[entry.size];
|
|
||||||
if (!mapper) {
|
|
||||||
const el = entry.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Unknown size at ${entry.name}`);
|
|
||||||
}
|
|
||||||
mapper.set(entry.offset, entry.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
// The original iterated over tables and used .offset values stored in entries
|
|
||||||
CustTable.forEach(writeOne);
|
|
||||||
AdvTable.forEach(writeOne);
|
|
||||||
GpuTable.forEach(writeOne);
|
|
||||||
|
|
||||||
// persist storage to localStorage
|
|
||||||
this.storage.save();
|
|
||||||
|
|
||||||
// create download link for patched buffer
|
|
||||||
const blob = new Blob([this.buffer], { type: "application/octet-stream" });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
|
|
||||||
const a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = "loader.kip";
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
|
|
||||||
// UI: enable load last saved if needed
|
|
||||||
this.toggleLoadLastSavedBtn(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
removeHTMLForm() {
|
|
||||||
CustTable.forEach(e => e.removeElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleLoadLastSavedBtn(visible) {
|
|
||||||
const btn = document.getElementById("load_saved");
|
|
||||||
if (!btn) return;
|
|
||||||
if (visible) {
|
|
||||||
btn.addEventListener("click", () => {
|
|
||||||
if (this.storage.load()) this.storage.setTable();
|
|
||||||
});
|
|
||||||
btn.style.removeProperty("display");
|
|
||||||
btn.removeAttribute("disabled");
|
|
||||||
} else {
|
|
||||||
btn.style.setProperty("display", "none");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createHTMLForm() {
|
|
||||||
// create elements for each table entry
|
|
||||||
CustTable.forEach(e => e.createElement("config-list-basic"));
|
|
||||||
|
|
||||||
// Add separators/titles for advanced and gpu lists
|
|
||||||
const advContainer = document.getElementById("config-list-advanced");
|
|
||||||
if (advContainer) {
|
|
||||||
const p = document.createElement("p");
|
|
||||||
p.innerHTML = "Advanced configuration";
|
|
||||||
advContainer.appendChild(p);
|
|
||||||
}
|
|
||||||
const gpuContainer = document.getElementById("config-list-gpu");
|
|
||||||
if (gpuContainer) {
|
|
||||||
const p = document.createElement("p");
|
|
||||||
p.innerHTML = "Gpu Volt configuration";
|
|
||||||
gpuContainer.appendChild(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
AdvTable.forEach(e => e.createElement("config-list-advanced"));
|
|
||||||
GpuTable.forEach(e => e.createElement("config-list-gpu"));
|
|
||||||
|
|
||||||
// Buttons: load default, load saved, save
|
|
||||||
const loadDefaultBtn = document.getElementById("load_default");
|
|
||||||
if (loadDefaultBtn) {
|
|
||||||
loadDefaultBtn.removeAttribute("disabled");
|
|
||||||
loadDefaultBtn.addEventListener("click", () => {
|
|
||||||
CustTable.forEach(e => e.setElementDefaultValue());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// show load saved if we have saved storage
|
|
||||||
this.toggleLoadLastSavedBtn(this.storage.load() !== null);
|
|
||||||
|
|
||||||
const saveBtn = document.getElementById("save");
|
|
||||||
if (saveBtn) {
|
|
||||||
saveBtn.removeAttribute("disabled");
|
|
||||||
saveBtn.addEventListener("click", () => {
|
|
||||||
try {
|
|
||||||
this.save();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
alert(String(err));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initCustTabs() {
|
|
||||||
// map nav buttons (role="tablist") to platform toggles
|
|
||||||
const tabButtons = Array.from(document.querySelectorAll('nav[role="tablist"] > button, .cust-platform-tabs > button'));
|
|
||||||
if (!tabButtons.length) return;
|
|
||||||
tabButtons.forEach(btn => {
|
|
||||||
btn.removeAttribute("disabled");
|
|
||||||
const plat = Number(btn.getAttribute("data-platform"));
|
|
||||||
btn.addEventListener("click", (ev) => {
|
|
||||||
// style toggling
|
|
||||||
const outlineClass = ["outline"];
|
|
||||||
btn.classList.remove(...outlineClass);
|
|
||||||
tabButtons.filter(x => x !== btn).forEach(x => x.classList.add(...outlineClass));
|
|
||||||
// show/hide entries
|
|
||||||
CustTable.forEach(e => {
|
|
||||||
if (e.isAvailableFor(plat)) e.showElement(); else e.hideElement();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
parse() {
|
|
||||||
// beginOffset should already exist
|
|
||||||
let offset = this.beginOffset + this.magicLen;
|
|
||||||
// read revision (4-byte)
|
|
||||||
this.rev = this.mapper[4].get(offset);
|
|
||||||
if (this.rev !== CUST_REV_ADV) throw new Error(`Unsupported custRev, expected: ${CUST_REV_ADV}, got ${this.rev}`);
|
|
||||||
offset += 4;
|
|
||||||
const revEl = document.getElementById("cust_rev");
|
|
||||||
if (revEl) revEl.innerHTML = `Cust v${this.rev} is loaded.`;
|
|
||||||
|
|
||||||
const readOne = (entry) => {
|
|
||||||
entry.offset = offset;
|
|
||||||
const mapper = this.mapper[entry.size];
|
|
||||||
if (!mapper) {
|
|
||||||
const el = entry.getInputElement();
|
|
||||||
if (el) el.focus();
|
|
||||||
throw new Error(`Unknown size at ${entry.name}`);
|
|
||||||
}
|
|
||||||
entry.value = mapper.get(offset);
|
|
||||||
offset += entry.size;
|
|
||||||
entry.validate();
|
|
||||||
};
|
|
||||||
|
|
||||||
CustTable.forEach(readOne);
|
|
||||||
AdvTable.forEach(readOne);
|
|
||||||
GpuTable.forEach(readOne);
|
|
||||||
}
|
|
||||||
|
|
||||||
load(buffer) {
|
|
||||||
try {
|
|
||||||
this.buffer = buffer;
|
|
||||||
this.findMagicOffset();
|
|
||||||
this.removeHTMLForm();
|
|
||||||
this.parse();
|
|
||||||
this.initCustTabs();
|
|
||||||
this.createHTMLForm();
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
alert(String(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===== Release fetching classes ===== */
|
|
||||||
class ReleaseAsset {
|
|
||||||
constructor(obj) {
|
|
||||||
this.downloadUrl = obj?.browser_download_url;
|
|
||||||
this.updatedAt = obj?.updated_at;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ReleaseInfo {
|
|
||||||
constructor() {
|
|
||||||
this.ocLatestApi = "https://api.github.com/repos/Horizon-OC/Horizon-OC/releases/latest";
|
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
try {
|
|
||||||
const json = await this.responseFromApi(this.ocLatestApi);
|
|
||||||
this.parseOcResponse(json);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
alert(String(err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async responseFromApi(url) {
|
|
||||||
const res = await fetch(url, { method: "GET", headers: { Accept: "application/json" } });
|
|
||||||
if (!res.ok) throw new Error(`Failed to connect to "${url}": ${res.status}`);
|
|
||||||
return await res.json();
|
|
||||||
}
|
|
||||||
|
|
||||||
parseOcResponse(json) {
|
|
||||||
this.ocVer = json.tag_name;
|
|
||||||
const assets = json.assets || [];
|
|
||||||
this.loaderKipAsset = new ReleaseAsset(assets.find(a => a.name.endsWith("hoc.kip")) || {});
|
|
||||||
this.sdOutZipAsset = new ReleaseAsset(assets.find(a => a.name.endsWith("dist.zip")) || {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DownloadSection {
|
|
||||||
constructor() {
|
|
||||||
this.element = document.getElementById("download_btn_grid") || document.getElementById("download");
|
|
||||||
}
|
|
||||||
|
|
||||||
async load() {
|
|
||||||
// Wait until the element is visible in the viewport
|
|
||||||
for (; !this.isVisible();) {
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
||||||
}
|
|
||||||
const release = new ReleaseInfo();
|
|
||||||
await release.load();
|
|
||||||
this.update("loader_kip_btn", `hoc.kip <b>${release.ocVer}</b><br>${release.loaderKipAsset.updatedAt}`, release.loaderKipAsset.downloadUrl);
|
|
||||||
this.update("sdout_zip_btn", `dist.zip <b>${release.ocVer}</b><br>${release.sdOutZipAsset.updatedAt}`, release.sdOutZipAsset.downloadUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
isVisible() {
|
|
||||||
if (!this.element) return true;
|
|
||||||
const r = this.element.getBoundingClientRect();
|
|
||||||
return r.top > 0 && r.left > 0 && r.bottom - r.height < (window.innerHeight || document.documentElement.clientHeight) && r.right - r.width < (window.innerWidth || document.documentElement.clientWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
update(id, html, href) {
|
|
||||||
const el = document.getElementById(id);
|
|
||||||
if (!el) return;
|
|
||||||
el.innerHTML = html;
|
|
||||||
el.removeAttribute("aria-busy");
|
|
||||||
if (href) el.setAttribute("href", href);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ===== Initialization wiring ===== */
|
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
|
||||||
// Ensure containers exist (fail gracefully if not)
|
|
||||||
const ensureEl = (id, createTag = "div") => {
|
|
||||||
if (!document.getElementById(id)) {
|
|
||||||
const container = document.createElement(createTag);
|
|
||||||
container.id = id;
|
|
||||||
container.classList.add("mt-4");
|
|
||||||
// append to config section or body as fallback
|
|
||||||
const config = document.getElementById("config") || document.body;
|
|
||||||
config.appendChild(container);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
["config-list-basic", "config-list-advanced", "config-list-gpu"].forEach(id => ensureEl(id));
|
|
||||||
|
|
||||||
// Wire file input
|
|
||||||
const fileInput = document.getElementById("file");
|
|
||||||
if (fileInput) {
|
|
||||||
fileInput.addEventListener("change", (ev) => {
|
|
||||||
const cust = new Cust();
|
|
||||||
const target = ev.target;
|
|
||||||
if (!target || !target.files) return;
|
|
||||||
const fr = new FileReader();
|
|
||||||
fr.readAsArrayBuffer(target.files[0]);
|
|
||||||
fr.onloadend = (e) => {
|
|
||||||
if (e.target && e.target.readyState === FileReader.DONE) {
|
|
||||||
cust.load(e.target.result);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wire DownloadSection (non-blocking)
|
|
||||||
(async () => {
|
|
||||||
try {
|
|
||||||
const ds = new DownloadSection();
|
|
||||||
await ds.load();
|
|
||||||
} catch (err) {
|
|
||||||
console.warn("DownloadSection failed:", err);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// If HTML had DOMContentLoaded wiring in original minified code, emulate it:
|
|
||||||
// some initialization that original file did on DOMContentLoaded -> start the DownloadSection (done above)
|
|
||||||
});
|
|
||||||
153
docs/index.html
153
docs/index.html
@@ -1,153 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Horizon OC</title>
|
|
||||||
<script src="https://cdn.tailwindcss.com"></script>
|
|
||||||
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
/* Background gradient */
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Segoe UI', Roboto, system-ui, sans-serif;
|
|
||||||
color: white;
|
|
||||||
background: linear-gradient(160deg, #1a1a1a 0%, #2a2a2a 50%, #3a3a3a 100%);
|
|
||||||
min-height: 100vh;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Liquid glass panels */
|
|
||||||
.glass {
|
|
||||||
background: rgba(255, 255, 255, 0.08);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border-radius: 20px;
|
|
||||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.glass:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.12);
|
|
||||||
transform: translateY(-4px);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hero gradient text */
|
|
||||||
.gradient-text {
|
|
||||||
background: linear-gradient(to right, #a3baff, #b8f3ff);
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
-webkit-text-fill-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Buttons: Liquid glass style */
|
|
||||||
.button-glass {
|
|
||||||
background: rgba(255, 255, 255, 0.15);
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
|
||||||
color: #fff;
|
|
||||||
padding: 0.8rem 2rem;
|
|
||||||
border-radius: 9999px;
|
|
||||||
font-weight: 600;
|
|
||||||
transition: all 0.25s ease;
|
|
||||||
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.6rem;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-glass:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.25);
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
background: rgba(255, 255, 255, 0.05);
|
|
||||||
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
|
||||||
padding: 1.5rem 0;
|
|
||||||
text-align: center;
|
|
||||||
color: #ccc;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
margin-top: 4rem;
|
|
||||||
backdrop-filter: blur(10px);
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GitHub Icon */
|
|
||||||
.github-icon {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
fill: white;
|
|
||||||
transition: fill 0.3s;
|
|
||||||
}
|
|
||||||
.button-glass:hover .github-icon {
|
|
||||||
fill: #b8f3ff;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Header -->
|
|
||||||
<header class="text-center py-20">
|
|
||||||
<h1 class="text-6xl font-extrabold mb-4 gradient-text">Horizon OC</h1>
|
|
||||||
<p class="text-gray-300 text-lg">Upgrade the performance of your Nintendo Switch Console</p>
|
|
||||||
|
|
||||||
<div class="mt-6 flex justify-center gap-4">
|
|
||||||
<a href="#download" class="button-glass">Download Now</a>
|
|
||||||
<a href="configurator.html" class="button-glass">Open Configurator</a>
|
|
||||||
<a href="https://github.com/Horizon-OC/Horizon-OC" target="_blank" class="button-glass">
|
|
||||||
<!-- GitHub SVG Icon -->
|
|
||||||
<svg class="github-icon" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8a8 8 0 005.47 7.59c.4.07.55-.17.55-.38v-1.32C3.73 14.9 3.27 13.4 3.27 13.4c-.36-.9-.88-1.14-.88-1.14-.72-.49.05-.48.05-.48.8.06 1.22.83 1.22.83.71 1.21 1.87.86 2.33.66.07-.52.28-.86.5-1.06-2.22-.25-4.55-1.11-4.55-4.95 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02A9.56 9.56 0 018 3.43a9.6 9.6 0 012.5.34c1.9-1.29 2.74-1.02 2.74-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.85-2.34 4.7-4.57 4.95.29.25.54.73.54 1.48v2.2c0 .21.15.45.55.38A8 8 0 0016 8c0-4.42-3.58-8-8-8z"/>
|
|
||||||
</svg>
|
|
||||||
GitHub
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<!-- About Section -->
|
|
||||||
<section class="max-w-3xl mx-auto text-center py-16 px-6 glass" data-aos="fade-up">
|
|
||||||
<h2 class="text-3xl font-bold mb-4">What is Horizon OC?</h2>
|
|
||||||
<p class="text-gray-300">
|
|
||||||
Horizon OC is a tool to overclock your modded Nintendo Switch console.
|
|
||||||
This can help improve frame rates, load times, and latency in games.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Features -->
|
|
||||||
<section class="py-20">
|
|
||||||
<div class="max-w-6xl mx-auto grid md:grid-cols-3 gap-8 px-6">
|
|
||||||
<div class="glass p-6 text-center" data-aos="zoom-in" data-aos-delay="100">
|
|
||||||
<h3 class="text-xl font-semibold mb-2">⚡ Performance</h3>
|
|
||||||
<p class="text-gray-300">Overclocking your console can lead to significantly better performance in demanding titles.</p>
|
|
||||||
</div>
|
|
||||||
<div class="glass p-6 text-center" data-aos="zoom-in" data-aos-delay="200">
|
|
||||||
<h3 class="text-xl font-semibold mb-2">☣ Safety</h3>
|
|
||||||
<p class="text-gray-300">Horizon OC aims to be as safe as possible, while allowing advanced users to customize it further.</p>
|
|
||||||
</div>
|
|
||||||
<div class="glass p-6 text-center" data-aos="zoom-in" data-aos-delay="300">
|
|
||||||
<h3 class="text-xl font-semibold mb-2">🔧 Customizable</h3>
|
|
||||||
<p class="text-gray-300">Horizon OC comes with an advanced configurator allowing you to tune it for your own needs.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Download Section -->
|
|
||||||
<section id="download" class="text-center py-20 glass max-w-3xl mx-auto px-6" data-aos="fade-up">
|
|
||||||
<h2 class="text-3xl font-bold mb-6">Get Horizon OC</h2>
|
|
||||||
<a href="#" class="button-glass">Download Latest Release</a>
|
|
||||||
<p class="text-gray-400 mt-4">Ensure you are using the latest version of Atmosphere.</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer>
|
|
||||||
This website is open source and licensed under the GPLv2.
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
|
|
||||||
<script>AOS.init({ once: true, duration: 800 });</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Reference in New Issue
Block a user